From 84d589378ede857f7146d84b382f1f9276d7939e Mon Sep 17 00:00:00 2001 From: Arturo Bernal Date: Sat, 8 Oct 2022 08:55:19 +0200 Subject: [PATCH] Avoid method that assume default platform encoding is suitable. --- ChangeLog.md | 7 +++++++ .../src/main/java/org/apache/wiki/api/Release.java | 2 +- .../org/apache/wiki/auth/user/JDBCUserDatabase.java | 12 ++++++++++-- .../org/apache/wiki/auth/user/XMLUserDatabase.java | 11 ++++++++++- .../org/apache/wiki/diff/ExternalDiffProvider.java | 7 ++++++- .../src/main/java/org/apache/wiki/util/FileUtil.java | 7 ++++--- .../main/java/org/apache/wiki/util/Serializer.java | 6 ++++-- .../java/org/apache/wiki/util/SerializerTest.java | 3 ++- 8 files changed, 44 insertions(+), 11 deletions(-) diff --git a/ChangeLog.md b/ChangeLog.md index eed4cd10ef..6100e2cf85 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -17,6 +17,13 @@ specific language governing permissions and limitations under the License. --> +*2024-02-20 Arturo Bernal (abernal AT apache DOT org)** + +* _2.12.2-git-12_ + +Avoid method that assume default platform encoding is suitable. #232 + + **2023-12-04 Juan Pablo Santos (juanpablo AT apache DOT org)** * _2.12.2-git-11_ diff --git a/jspwiki-api/src/main/java/org/apache/wiki/api/Release.java b/jspwiki-api/src/main/java/org/apache/wiki/api/Release.java index b3699e53a1..1c6bef6af2 100644 --- a/jspwiki-api/src/main/java/org/apache/wiki/api/Release.java +++ b/jspwiki-api/src/main/java/org/apache/wiki/api/Release.java @@ -69,7 +69,7 @@ public final class Release { *

* If the build identifier is empty, it is not added. */ - public static final String BUILD = "11"; + public static final String BUILD = "12"; /** * This is the generic version string you should use when printing out the version. It is of diff --git a/jspwiki-main/src/main/java/org/apache/wiki/auth/user/JDBCUserDatabase.java b/jspwiki-main/src/main/java/org/apache/wiki/auth/user/JDBCUserDatabase.java index 9dd48be064..6bb29fc19b 100644 --- a/jspwiki-main/src/main/java/org/apache/wiki/auth/user/JDBCUserDatabase.java +++ b/jspwiki-main/src/main/java/org/apache/wiki/auth/user/JDBCUserDatabase.java @@ -32,6 +32,7 @@ Licensed to the Apache Software Foundation (ASF) under one import javax.sql.DataSource; import java.io.IOException; import java.io.Serializable; +import java.nio.charset.Charset; import java.security.Principal; import java.sql.Connection; import java.sql.DatabaseMetaData; @@ -298,6 +299,12 @@ public class JDBCUserDatabase extends AbstractUserDatabase { private boolean m_supportsCommits; + /** + * The character set encoding used by this object. This is obtained from {@link org.apache.wiki.WikiEngine#getContentEncoding()}, + * which returns the content encoding of the engine, either UTF-8 or ISO-8859-1. + */ + private Charset m_encoding; + /** * Looks up and deletes the first {@link UserProfile} in the user database * that matches a profile having a given login name. If the user database @@ -415,6 +422,7 @@ public Principal[] getWikiNames() throws WikiSecurityException { @Override public void initialize( final Engine engine, final Properties props ) throws NoRequiredPropertyException, WikiSecurityException { final String jndiName = props.getProperty( PROP_DB_DATASOURCE, DEFAULT_DB_JNDI_NAME ); + m_encoding = engine != null ? engine.getContentEncoding() : Charset.defaultCharset(); try { final Context initCtx = new InitialContext(); final Context ctx = (Context) initCtx.lookup( "java:comp/env" ); @@ -615,7 +623,7 @@ public void save( final UserProfile profile ) throws WikiSecurityException { ps1.setTimestamp( 6, ts ); ps1.setString( 7, profile.getLoginName() ); try { - ps1.setString( 8, Serializer.serializeToBase64( profile.getAttributes() ) ); + ps1.setString( 8, Serializer.serializeToBase64( profile.getAttributes(), m_encoding != null ? m_encoding : Charset.defaultCharset() ) ); } catch ( final IOException e ) { throw new WikiSecurityException( "Could not save user profile attribute. Reason: " + e.getMessage(), e ); } @@ -649,7 +657,7 @@ public void save( final UserProfile profile ) throws WikiSecurityException { ps4.setTimestamp( 6, ts ); ps4.setString( 7, profile.getLoginName() ); try { - ps4.setString( 8, Serializer.serializeToBase64( profile.getAttributes() ) ); + ps4.setString( 8, Serializer.serializeToBase64( profile.getAttributes(), m_encoding != null ? m_encoding : Charset.defaultCharset() ) ); } catch ( final IOException e ) { throw new WikiSecurityException( "Could not save user profile attribute. Reason: " + e.getMessage(), e ); } diff --git a/jspwiki-main/src/main/java/org/apache/wiki/auth/user/XMLUserDatabase.java b/jspwiki-main/src/main/java/org/apache/wiki/auth/user/XMLUserDatabase.java index dd7c6ee582..6e50f3d2b8 100644 --- a/jspwiki-main/src/main/java/org/apache/wiki/auth/user/XMLUserDatabase.java +++ b/jspwiki-main/src/main/java/org/apache/wiki/auth/user/XMLUserDatabase.java @@ -41,6 +41,7 @@ Licensed to the Apache Software Foundation (ASF) under one import java.io.IOException; import java.io.OutputStreamWriter; import java.io.Serializable; +import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.security.Principal; @@ -91,6 +92,12 @@ public class XMLUserDatabase extends AbstractUserDatabase { private Document c_dom; private File c_file; + /** + * The character set encoding used by this object. This is obtained from {@link org.apache.wiki.WikiEngine#getContentEncoding()}, + * which returns the content encoding of the engine, either UTF-8 or ISO-8859-1. + */ + private Charset m_encoding; + /** {@inheritDoc} */ @Override public synchronized void deleteByLoginName( final String loginName ) throws WikiSecurityException { @@ -182,6 +189,8 @@ public void initialize( final Engine engine, final Properties props ) throws NoR defaultFile = new File( engine.getRootPath() + "/WEB-INF/" + DEFAULT_USERDATABASE ); } + m_encoding = engine.getContentEncoding(); + // Get database file location final String file = TextUtil.getStringProperty( props, PROP_USERDATABASE, defaultFile.getAbsolutePath() ); if( file == null ) { @@ -416,7 +425,7 @@ public synchronized void save( final UserProfile profile ) throws WikiSecurityEx // Save the attributes as Base64 string if(!profile.getAttributes().isEmpty()) { try { - final String encodedAttributes = Serializer.serializeToBase64( profile.getAttributes() ); + final String encodedAttributes = Serializer.serializeToBase64( profile.getAttributes(), m_encoding != null ? m_encoding : Charset.defaultCharset() ); final Element attributes = c_dom.createElement( ATTRIBUTES_TAG ); user.appendChild( attributes ); final Text value = c_dom.createTextNode( encodedAttributes ); diff --git a/jspwiki-main/src/main/java/org/apache/wiki/diff/ExternalDiffProvider.java b/jspwiki-main/src/main/java/org/apache/wiki/diff/ExternalDiffProvider.java index d1ae915eed..39f548c768 100644 --- a/jspwiki-main/src/main/java/org/apache/wiki/diff/ExternalDiffProvider.java +++ b/jspwiki-main/src/main/java/org/apache/wiki/diff/ExternalDiffProvider.java @@ -49,6 +49,11 @@ public class ExternalDiffProvider implements DiffProvider { public static final String PROP_DIFFCOMMAND = "jspwiki.diffCommand"; private String m_diffCommand; + + /** + * The character set encoding used by this object. This is obtained from {@link org.apache.wiki.WikiEngine#getContentEncoding()}, + * which returns the content encoding of the engine, either UTF-8 or ISO-8859-1. + */ private Charset m_encoding; private static final char DIFF_ADDED_SYMBOL = '+'; @@ -113,7 +118,7 @@ public String makeDiffHtml( final Context ctx, final String p1, final String p2 String cmd = TextUtil.replaceString(m_diffCommand, "%s1", f1.getPath()); cmd = TextUtil.replaceString(cmd, "%s2", f2.getPath()); - final String output = FileUtil.runSimpleCommand(cmd, f1.getParent()); + final String output = FileUtil.runSimpleCommand(cmd, f1.getParent(), m_encoding != null ? m_encoding : Charset.defaultCharset()); // FIXME: Should this rely on the system default encoding? final String rawWikiDiff = new String( output.getBytes( StandardCharsets.ISO_8859_1 ), m_encoding ); diff --git a/jspwiki-util/src/main/java/org/apache/wiki/util/FileUtil.java b/jspwiki-util/src/main/java/org/apache/wiki/util/FileUtil.java index b8205c04c5..1591736a7d 100644 --- a/jspwiki-util/src/main/java/org/apache/wiki/util/FileUtil.java +++ b/jspwiki-util/src/main/java/org/apache/wiki/util/FileUtil.java @@ -100,16 +100,17 @@ public static File newTmpFile( final String content ) throws IOException { * @return Standard output from the command. * @param command The command to run * @param directory The working directory to run the command in + * @param charset The character set encoding to use for the input streams * @throws IOException If the command failed * @throws InterruptedException If the command was halted */ - public static String runSimpleCommand( final String command, final String directory ) throws IOException, InterruptedException { + public static String runSimpleCommand( final String command, final String directory , final Charset charset) throws IOException, InterruptedException { LOG.info( "Running simple command " + command + " in " + directory ); final StringBuilder result = new StringBuilder(); final Process process = Runtime.getRuntime().exec( command, null, new File( directory ) ); - try( final BufferedReader stdout = new BufferedReader( new InputStreamReader( process.getInputStream() ) ); - final BufferedReader stderr = new BufferedReader( new InputStreamReader( process.getErrorStream() ) ) ) { + try( final BufferedReader stdout = new BufferedReader( new InputStreamReader( process.getInputStream(), charset ) ); + final BufferedReader stderr = new BufferedReader( new InputStreamReader( process.getErrorStream(), charset ) ) ) { String line; while( (line = stdout.readLine()) != null ) { diff --git a/jspwiki-util/src/main/java/org/apache/wiki/util/Serializer.java b/jspwiki-util/src/main/java/org/apache/wiki/util/Serializer.java index 78ca48a7f7..3bb13f476f 100644 --- a/jspwiki-util/src/main/java/org/apache/wiki/util/Serializer.java +++ b/jspwiki-util/src/main/java/org/apache/wiki/util/Serializer.java @@ -25,6 +25,7 @@ Licensed to the Apache Software Foundation (ASF) under one import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; +import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.Base64; import java.util.HashMap; @@ -74,10 +75,11 @@ private Serializer() * Serializes a Map and formats it into a Base64-encoded String. For ease of serialization, the Map contents * are first copied into a HashMap, then serialized into a byte array that is encoded as a Base64 String. * @param map the Map to serialize + * @param charset the character set encoding to use for the Base64-encoded String * @return a String representing the serialized form of the Map * @throws IOException If serialization cannot be done */ - public static String serializeToBase64(final Map< String, Serializable > map ) throws IOException { + public static String serializeToBase64(final Map< String, Serializable > map, final Charset charset) throws IOException { // Load the Map contents into a defensive HashMap final Map serialMap = new HashMap<>(map); @@ -89,7 +91,7 @@ public static String serializeToBase64(final Map< String, Serializable > map ) t // Transform to Base64-encoded String final byte[] result = Base64.getEncoder().encode( bytesOut.toByteArray() ); - return new String( result ) ; + return new String( result, charset ) ; } } diff --git a/jspwiki-util/src/test/java/org/apache/wiki/util/SerializerTest.java b/jspwiki-util/src/test/java/org/apache/wiki/util/SerializerTest.java index 2f022432c4..96f13d765a 100644 --- a/jspwiki-util/src/test/java/org/apache/wiki/util/SerializerTest.java +++ b/jspwiki-util/src/test/java/org/apache/wiki/util/SerializerTest.java @@ -19,6 +19,7 @@ Licensed to the Apache Software Foundation (ASF) under one package org.apache.wiki.util; import java.io.Serializable; +import java.nio.charset.Charset; import java.util.HashMap; import java.util.Map; @@ -34,7 +35,7 @@ public void testSerializeMap() throws Exception final Map map = new HashMap(); map.put( "attribute1", "some random value" ); map.put( "attribute2", "another value" ); - final String serializedForm = Serializer.serializeToBase64( map ); + final String serializedForm = Serializer.serializeToBase64( map , Charset.defaultCharset()); final Map newMap = Serializer.deserializeFromBase64( serializedForm ); Assertions.assertEquals( 2, newMap.size() );