Skip to content

Commit

Permalink
Implements the BIF XMLFormat
Browse files Browse the repository at this point in the history
  • Loading branch information
jclausen committed Apr 11, 2024
1 parent 32b8e7a commit 832c3b6
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 12 deletions.
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

/**
* [BoxLang]
*
Expand All @@ -15,16 +16,23 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ortus.boxlang.runtime.bifs.global.system;

package ortus.boxlang.runtime.bifs.global.xml;

import org.apache.commons.text.StringEscapeUtils;

import ortus.boxlang.runtime.bifs.BIF;
import ortus.boxlang.runtime.bifs.BoxBIF;
import ortus.boxlang.runtime.bifs.BoxMember;
import ortus.boxlang.runtime.context.IBoxContext;
import ortus.boxlang.runtime.scopes.ArgumentsScope;
import ortus.boxlang.runtime.scopes.Key;
import ortus.boxlang.runtime.types.Argument;
import ortus.boxlang.runtime.types.BoxLangType;

@BoxBIF
@BoxMember( type = BoxLangType.STRING )

public class XMLFormat extends BIF {

/**
Expand All @@ -33,25 +41,26 @@ public class XMLFormat extends BIF {
public XMLFormat() {
super();
declaredArguments = new Argument[] {
new Argument( true, "string", Key.string )
new Argument( true, "string", Key.string ),
new Argument( false, "boolean", Key.escapeChars, false )
};
}

/**
* Escapes XML special characters in a string, so that the string is safe to use with XML.
*
* Formats a string so that special XML characters can be used as text in XML
*
* @param context The context in which the BIF is being invoked.
* @param arguments Argument scope for the BIF.
*
* @argument.String The string to encode.
*
* @argument.string The string to format
*
* @argument.escapeChars whether to escape additional characters restricted as per XML standards. For details, see
* http://www.w3.org/TR/2006/REC-xml11-20060816/#NT-RestrictedChar.
*/
public Object _invoke( IBoxContext context, ArgumentsScope arguments ) {
// TODO: Just stubbing this out to make ColdBox work. Convert to ESAPI
String str = arguments.getAsString( Key.string );
if ( str == null ) {
return null;
}
return str.replace( "<", "&lt;" ).replace( ">", "&gt;" ).replace( "&", "&amp;" );
return arguments.getAsBoolean( Key.escapeChars )
? StringEscapeUtils.escapeXml10( arguments.getAsString( Key.string ) )
: StringEscapeUtils.escapeXml11( arguments.getAsString( Key.string ) );
}

}
1 change: 1 addition & 0 deletions src/main/java/ortus/boxlang/runtime/scopes/Key.java
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ public class Key implements Comparable<Key>, Serializable {
public static final Key error = Key.of( "error" );
public static final Key errorcode = Key.of( "errorcode" );
public static final Key errorDetail = Key.of( "errorDetail" );
public static final Key escapeChars = Key.of( "escapeChars" );
public static final Key evictCount = Key.of( "evictCount" );
public static final Key evictionPolicy = Key.of( "evictionPolicy" );
public static final Key execute = Key.of( "execute" );
Expand Down
104 changes: 104 additions & 0 deletions src/test/java/ortus/boxlang/runtime/bifs/global/xml/XMLFormatTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@

/**
* [BoxLang]
*
* Copyright [2023] [Ortus Solutions, Corp]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package ortus.boxlang.runtime.bifs.global.xml;

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import ortus.boxlang.runtime.BoxRuntime;
import ortus.boxlang.runtime.context.IBoxContext;
import ortus.boxlang.runtime.context.ScriptingRequestBoxContext;
import ortus.boxlang.runtime.scopes.IScope;
import ortus.boxlang.runtime.scopes.Key;
import ortus.boxlang.runtime.scopes.VariablesScope;

public class XMLFormatTest {

static BoxRuntime instance;
IBoxContext context;
IScope variables;
static Key result = new Key( "result" );

@BeforeAll
public static void setUp() {
instance = BoxRuntime.getInstance( true );
}

@AfterAll
public static void teardown() {
}

@BeforeEach
public void setupEach() {
context = new ScriptingRequestBoxContext( instance.getRuntimeContext() );
variables = context.getScopeNearby( VariablesScope.name );
}

@DisplayName( "It tests the BIF XMLFormat" )
@Test
public void testBif() {
instance.executeSource(
"""
stringXML = '<root foo="bar" />';
result = XMLFormat( stringXML );
""",
context );

assertEquals( "&lt;root foo=&quot;bar&quot; /&gt;", variables.getAsString( result ) );

instance.executeSource(
"""
stringXML = '<root foo="bar" illegal="#char(00)##char(12)#" />';
result = XMLFormat( stringXML, true );
""",
context );

assertEquals( "&lt;root foo=&quot;bar&quot; illegal=&quot;&quot; /&gt;", variables.getAsString( result ) );

}

@DisplayName( "It tests the member function for String.XMLFormat" )
@Test
public void testMemberFunction() {
instance.executeSource(
"""
stringXML = '<root foo="bar" />';
result = stringXML.XMLFormat();
""",
context );

assertEquals( "&lt;root foo=&quot;bar&quot; /&gt;", variables.getAsString( result ) );

instance.executeSource(
"""
stringXML = '<root foo="bar" illegal="#char(00)##char(12)#" />';
result = stringXML.XMLFormat( true );
""",
context );

assertEquals( "&lt;root foo=&quot;bar&quot; illegal=&quot;&quot; /&gt;", variables.getAsString( result ) );
}

}

0 comments on commit 832c3b6

Please sign in to comment.