From 832c3b6320c892ec27fd6c83835d5f0cc1f789e2 Mon Sep 17 00:00:00 2001 From: jclausen Date: Thu, 11 Apr 2024 12:34:20 -0500 Subject: [PATCH] Implements the BIF XMLFormat --- .../global/{system => xml}/XMLFormat.java | 33 ++++-- .../ortus/boxlang/runtime/scopes/Key.java | 1 + .../bifs/global/xml/XMLFormatTest.java | 104 ++++++++++++++++++ 3 files changed, 126 insertions(+), 12 deletions(-) rename src/main/java/ortus/boxlang/runtime/bifs/global/{system => xml}/XMLFormat.java (58%) create mode 100644 src/test/java/ortus/boxlang/runtime/bifs/global/xml/XMLFormatTest.java diff --git a/src/main/java/ortus/boxlang/runtime/bifs/global/system/XMLFormat.java b/src/main/java/ortus/boxlang/runtime/bifs/global/xml/XMLFormat.java similarity index 58% rename from src/main/java/ortus/boxlang/runtime/bifs/global/system/XMLFormat.java rename to src/main/java/ortus/boxlang/runtime/bifs/global/xml/XMLFormat.java index e50ef40c7..aabb3efe3 100644 --- a/src/main/java/ortus/boxlang/runtime/bifs/global/system/XMLFormat.java +++ b/src/main/java/ortus/boxlang/runtime/bifs/global/xml/XMLFormat.java @@ -1,3 +1,4 @@ + /** * [BoxLang] * @@ -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 { /** @@ -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( "<", "<" ).replace( ">", ">" ).replace( "&", "&" ); + return arguments.getAsBoolean( Key.escapeChars ) + ? StringEscapeUtils.escapeXml10( arguments.getAsString( Key.string ) ) + : StringEscapeUtils.escapeXml11( arguments.getAsString( Key.string ) ); } + } diff --git a/src/main/java/ortus/boxlang/runtime/scopes/Key.java b/src/main/java/ortus/boxlang/runtime/scopes/Key.java index 002e6f394..9b24791a7 100644 --- a/src/main/java/ortus/boxlang/runtime/scopes/Key.java +++ b/src/main/java/ortus/boxlang/runtime/scopes/Key.java @@ -213,6 +213,7 @@ public class Key implements Comparable, 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" ); diff --git a/src/test/java/ortus/boxlang/runtime/bifs/global/xml/XMLFormatTest.java b/src/test/java/ortus/boxlang/runtime/bifs/global/xml/XMLFormatTest.java new file mode 100644 index 000000000..c8fa5a728 --- /dev/null +++ b/src/test/java/ortus/boxlang/runtime/bifs/global/xml/XMLFormatTest.java @@ -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 = ''; + result = XMLFormat( stringXML ); + """, + context ); + + assertEquals( "<root foo="bar" />", variables.getAsString( result ) ); + + instance.executeSource( + """ + stringXML = ''; + result = XMLFormat( stringXML, true ); + """, + context ); + + assertEquals( "<root foo="bar" illegal="" />", variables.getAsString( result ) ); + + } + + @DisplayName( "It tests the member function for String.XMLFormat" ) + @Test + public void testMemberFunction() { + instance.executeSource( + """ + stringXML = ''; + result = stringXML.XMLFormat(); + """, + context ); + + assertEquals( "<root foo="bar" />", variables.getAsString( result ) ); + + instance.executeSource( + """ + stringXML = ''; + result = stringXML.XMLFormat( true ); + """, + context ); + + assertEquals( "<root foo="bar" illegal="" />", variables.getAsString( result ) ); + } + +}