[Git][java-team/axmlrpc][upstream] New upstream version 1.13.0

Emmanuel Bourg (@ebourg) gitlab at salsa.debian.org
Thu Dec 15 09:51:43 GMT 2022



Emmanuel Bourg pushed to branch upstream at Debian Java Maintainers / axmlrpc


Commits:
13ea0979 by Emmanuel Bourg at 2022-12-15T10:47:07+01:00
New upstream version 1.13.0
- - - - -


10 changed files:

- .travis.yml
- Changelog
- README.md
- pom.xml
- src/main/java/de/timroes/axmlrpc/ResponseParser.java
- src/main/java/de/timroes/axmlrpc/XMLRPCClient.java
- src/main/java/de/timroes/axmlrpc/serializer/DateTimeSerializer.java
- src/main/java/de/timroes/axmlrpc/serializer/SerializerHandler.java
- + src/test/java/de/timroes/TestResponseParser.java
- src/test/java/de/timroes/axmlrpc/serializer/TestDateTimeSerializer.java


Changes:

=====================================
.travis.yml
=====================================
@@ -6,3 +6,7 @@ before_install:
   - if [ $TRAVIS_CPU_ARCH = ppc64le ]; then
           sudo apt-get install maven ;
     fi
+
+cache:
+  directories:
+  - $HOME/.m2


=====================================
Changelog
=====================================
@@ -1,4 +1,7 @@
-Fix security issue CWE-611
+DateTime serializer format is now injectable
+
+1.12.1
+Fix an encoding issue
 
 1.12.0
 Add flag ACCEPT_NULL_DATES


=====================================
README.md
=====================================
@@ -281,7 +281,8 @@ aXMLRPC uses http with the java.net API. If you want to use another protocol or
 
 ```java
     boolean debug = false;
-    SerializerHandler serializerHandler = new SerializerHandler(); // or you may build it with flags
+    // or you may build it with flags and/or a custom datetime format
+    SerializerHandler serializerHandler = new SerializerHandler();
     String payload = new Call(serializerHandler, "add", 5, 10).getXML(debug);
 
     InputStream istream = sendPayloadWithMyTransport(payload); // use your implementation here


=====================================
pom.xml
=====================================
@@ -3,7 +3,7 @@
 	<modelVersion>4.0.0</modelVersion>
 	<groupId>fr.turri</groupId>
 	<artifactId>aXMLRPC</artifactId>
-	<version>1.12.1</version>
+	<version>1.13.0</version>
 	<packaging>jar</packaging>
 	<name>aXMLRPC</name>
 	<description>Lightweight Java XML-RPC working also on Android.</description>
@@ -34,7 +34,7 @@
 		<dependency>
 			<groupId>junit</groupId>
 			<artifactId>junit</artifactId>
-			<version>4.13.1</version>
+			<version>4.13.2</version>
 			<scope>test</scope>
 		</dependency>
 		<dependency>
@@ -45,7 +45,7 @@
         <dependency>
           <groupId>com.github.tomakehurst</groupId>
           <artifactId>wiremock-jre8</artifactId>
-          <version>2.27.2</version>
+          <version>2.28.0</version>
           <scope>test</scope>
         </dependency>
 	</dependencies>
@@ -53,7 +53,7 @@
         <connection>scm:git:https://github.com/gturri/aXMLRPC.git</connection>
         <developerConnection>scm:git:git at github.com:gturri/aXMLRPC.git</developerConnection>
         <url>https://github.com/gturri/aXMLRPC</url>
-        <tag>aXMLRPC-1.12.1</tag>
+        <tag>aXMLRPC-1.13.0</tag>
 	</scm>
     <build>
       <pluginManagement>
@@ -74,12 +74,12 @@
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-site-plugin</artifactId>
-          <version>3.9.1</version>
+          <version>3.12.1</version>
         </plugin>
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-jar-plugin</artifactId>
-          <version>3.2.0</version>
+          <version>3.3.0</version>
           <configuration>
             <archive>
               <manifest>
@@ -91,7 +91,7 @@
         <plugin>
           <groupId>org.sonatype.plugins</groupId>
           <artifactId>nexus-staging-maven-plugin</artifactId>
-          <version>1.6.8</version>
+          <version>1.6.13</version>
           <extensions>true</extensions>
           <configuration>
             <serverId>ossrh</serverId>
@@ -102,7 +102,7 @@
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-javadoc-plugin</artifactId>
-          <version>3.2.0</version>
+          <version>3.4.1</version>
           <executions>
             <execution>
               <id>attach-javadocs</id>
@@ -119,7 +119,7 @@
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-project-info-reports-plugin</artifactId>
-          <version>3.1.1</version>
+          <version>3.4.1</version>
         </plugin>
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
@@ -134,7 +134,7 @@
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-javadoc-plugin</artifactId>
-          <version>3.2.0</version>
+          <version>3.4.1</version>
           <reportSets>
             <reportSet>
               <reports>
@@ -174,7 +174,7 @@
             <plugin>
               <groupId>org.apache.maven.plugins</groupId>
               <artifactId>maven-javadoc-plugin</artifactId>
-              <version>3.2.0</version>
+              <version>3.4.1</version>
               <executions>
                 <execution>
                   <id>attach-javadocs</id>
@@ -187,7 +187,7 @@
             <plugin>
               <groupId>org.apache.maven.plugins</groupId>
               <artifactId>maven-gpg-plugin</artifactId>
-              <version>1.6</version>
+              <version>3.0.1</version>
               <executions>
                 <execution>
                   <id>sign-artifacts</id>


=====================================
src/main/java/de/timroes/axmlrpc/ResponseParser.java
=====================================
@@ -10,7 +10,6 @@ import java.util.Map;
 
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.transform.OutputKeys;
 import javax.xml.transform.Transformer;
 import javax.xml.transform.TransformerException;
@@ -46,17 +45,9 @@ public class ResponseParser {
 	public Object parse(SerializerHandler serializerHandler, InputStream response, boolean debugMode) throws XMLRPCException {
 
 		try {
-			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
 
-			// Ensure the xml parser won't allow exploitation of the vuln CWE-611
-			// (described on https://cwe.mitre.org/data/definitions/611.html )
-			factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
-			factory.setExpandEntityReferences(false);
+			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
 			factory.setNamespaceAware(true);
-			factory.setXIncludeAware(false);
-			factory.setExpandEntityReferences(false);
-			// End of the configuration of the parser for CWE-611
-
 			DocumentBuilder builder = factory.newDocumentBuilder();
 			Document dom = builder.parse(response);
 			if (debugMode ){


=====================================
src/main/java/de/timroes/axmlrpc/XMLRPCClient.java
=====================================
@@ -660,7 +660,7 @@ public class XMLRPCClient {
 				authManager.setAuthentication(http);
 				cookieManager.setCookies(http);
 
-				OutputStreamWriter stream = new OutputStreamWriter(http.getOutputStream());
+				OutputStreamWriter stream = new OutputStreamWriter(http.getOutputStream(), "UTF-8");
 				stream.write(c.getXML(isFlagSet(FLAGS_DEBUG)));
 				stream.flush();
 				stream.close();


=====================================
src/main/java/de/timroes/axmlrpc/serializer/DateTimeSerializer.java
=====================================
@@ -15,13 +15,19 @@ import fr.turri.jiso8601.Iso8601Deserializer;
  */
 public class DateTimeSerializer implements Serializer {
 
-	private static final String DATETIME_FORMAT = "yyyyMMdd'T'HHmmss";
-	private final SimpleDateFormat DATE_FORMATER = new SimpleDateFormat(DATETIME_FORMAT);
+	public static final String DEFAULT_DATETIME_FORMAT = "yyyyMMdd'T'HHmmss";
+	private final SimpleDateFormat dateFormatter;
 
 	private final boolean accepts_null_input;
 
 	public DateTimeSerializer(boolean accepts_null_input) {
 		this.accepts_null_input = accepts_null_input;
+		this.dateFormatter = new SimpleDateFormat(DEFAULT_DATETIME_FORMAT);
+	}
+
+	public DateTimeSerializer(boolean accepts_null_input, String datetimeFormat) {
+		this.accepts_null_input = accepts_null_input;
+		this.dateFormatter = new SimpleDateFormat(datetimeFormat);
 	}
 
 
@@ -45,7 +51,7 @@ public class DateTimeSerializer implements Serializer {
 	@Override
 	public XmlElement serialize(Object object) {
 		return XMLUtil.makeXmlTag(SerializerHandler.TYPE_DATETIME,
-				DATE_FORMATER.format(object));
+				dateFormatter.format(object));
 	}
 
 }


=====================================
src/main/java/de/timroes/axmlrpc/serializer/SerializerHandler.java
=====================================
@@ -48,7 +48,9 @@ public class SerializerHandler {
 		this(XMLRPCClient.FLAGS_DEBUG);
 	}
 
-	public SerializerHandler(int flags) {
+	public SerializerHandler(int flags) { this(flags, DateTimeSerializer.DEFAULT_DATETIME_FORMAT); }
+
+	public SerializerHandler(int flags, String datetimeFormat) {
 		this.flags = flags;
 		string = new StringSerializer(
 			(flags & XMLRPCClient.FLAGS_NO_STRING_ENCODE) == 0,
@@ -56,7 +58,8 @@ public class SerializerHandler {
 		);
 		struct = new StructSerializer(this);
 		array = new ArraySerializer(this);
-		datetime = new DateTimeSerializer((flags & XMLRPCClient.FLAGS_ACCEPT_NULL_DATES) != 0);
+		boolean accepts_null_input = (flags & XMLRPCClient.FLAGS_ACCEPT_NULL_DATES) != 0;
+		datetime = new DateTimeSerializer(accepts_null_input, datetimeFormat);
 	}
 
 	/**


=====================================
src/test/java/de/timroes/TestResponseParser.java
=====================================
@@ -0,0 +1,285 @@
+package de.timroes;
+
+import static org.junit.Assert.*;
+
+import de.timroes.axmlrpc.*;
+import de.timroes.axmlrpc.serializer.SerializerHandler;
+import org.junit.Test;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.Date;
+import java.util.Map;
+import java.util.TreeMap;
+
+public class TestResponseParser {
+    public final static String xmlDecl = "<?xml version=\"1.0\"?>";
+    public final static SerializerHandler sh = new SerializerHandler(XMLRPCClient.FLAGS_NONE);
+
+
+    @Test
+    public void testSimpleResponse() throws Exception {
+        ResponseParser sut = new ResponseParser();
+        Object actual = sut.parse(sh, strToStream(xmlDecl +
+                "<methodResponse>" +
+                "  <params>" +
+                "    <param>" +
+                "      <value><string>toto</string></value>" +
+                "    </param>" +
+                "  </params>" +
+                "</methodResponse>"), false);
+        assertEquals("toto", actual);
+    }
+
+    @Test
+    public void testWithTrailingWhitespaceInTags() throws Exception {
+        ResponseParser sut = new ResponseParser();
+        Object actual = sut.parse(sh, strToStream(xmlDecl +
+                "<methodResponse >" +
+                "  <params>" +
+                "    <param>" +
+                "      <value><string>toto</string></value>" +
+                "    </param >" +
+                "  </params>" +
+                "</methodResponse>"), false);
+        assertEquals("toto", actual);
+    }
+
+    @Test
+    public void testWithTrailingEndlineInTags() throws Exception {
+        ResponseParser sut = new ResponseParser();
+        Object actual = sut.parse(sh, strToStream(xmlDecl +
+                "<methodResponse\n>" +
+                "  <params>" +
+                "    <param>" +
+                "      <value><string>toto</string></value>" +
+                "    </param\n>" +
+                "  </params>" +
+                "</methodResponse>"), false);
+        assertEquals("toto", actual);
+    }
+
+    @Test
+    public void testWithTrailingTabInTags() throws Exception {
+        ResponseParser sut = new ResponseParser();
+        Object actual = sut.parse(sh, strToStream(xmlDecl +
+                "<methodResponse\t>" +
+                "  <params>" +
+                "    <param>" +
+                "      <value><string>toto</string></value>" +
+                "    </param\t>" +
+                "  </params>" +
+                "</methodResponse>"), false);
+        assertEquals("toto", actual);
+    }
+
+    @Test
+    public void testResponseWithNonAsciiCharacter() throws Exception {
+        ResponseParser sut = new ResponseParser();
+        Object actual = sut.parse(sh, strToStream(xmlDecl +
+                "<methodResponse>" +
+                "  <params>" +
+                "    <param>" +
+                "      <value><string>Aéris</string></value>" +
+                "    </param>" +
+                "  </params>" +
+                "</methodResponse>"), false);
+        assertEquals("Aéris", actual);
+    }
+
+    @Test
+    public void testUTF16Response() throws Exception {
+        ResponseParser sut = new ResponseParser();
+        Object actual = sut.parse(sh, bytesToStream((xmlDecl +
+                "<methodResponse>" +
+                "  <params>" +
+                "    <param>" +
+                "      <value><string>toto</string></value>" +
+                "    </param>" +
+                "  </params>" +
+                "</methodResponse>").getBytes(StandardCharsets.UTF_16)), false);
+        assertEquals("toto", actual);
+    }
+
+    @Test
+    public void testResponseWithComplexValue() throws Exception {
+        ResponseParser sut = new ResponseParser();
+        Object actual = sut.parse(sh, strToStream(xmlDecl +
+                "<methodResponse>" +
+                "  <params>" +
+                "    <param>" +
+                "      <value>" +
+                "        <struct>" +
+                "          <member><name>intValue</name><value><i4>12</i4></value></member>" +
+                "          <member><name>otherIntValue</name><value><int>13</int></value></member>" +
+                "          <member><name>boolValue</name><value><boolean>1</boolean></value></member>" +
+                "          <member><name>strValue</name><value><string>toto</string></value></member>" +
+                "          <member><name>doubleValue</name><value><double>12.4</double></value></member>" +
+                "          <member><name>dateValue</name><value><dateTime.iso8601>20200908T0440Z</dateTime.iso8601></value></member>" +
+                // Don't test base64 because it seems assertEqual will do a reference equals on arrray of bytes so it's not easily testable here
+                // so we test it in a test below
+                //"          <member><name>base64Value</name><value><base64>QWVyaXM=</base64></value></member>" +
+                "          <member><name>nestedValue</name><value><struct> " +
+                "            <member><name>innerStrValue</name><value><string>inner</string></value></member>" +
+                "          </struct></value></member>" +
+                "        </struct>" +
+                "      </value>" +
+                "    </param>" +
+                "  </params>" +
+                "</methodResponse>"), false);
+
+        Map<Object, Object> expected = new TreeMap<>();
+        expected.put("intValue", 12);
+        expected.put("otherIntValue", 13);
+        expected.put("boolValue", true);
+        expected.put("strValue", "toto");
+        expected.put("doubleValue", 12.4);
+        expected.put("dateValue", new Date(1599540000000L));
+        Map<Object, Object> innerStruct = new TreeMap<>();
+        innerStruct.put("innerStrValue", "inner");
+        expected.put("nestedValue", innerStruct);
+        assertEquals(expected, actual);
+    }
+
+    @Test
+    public void testResponseWithBase64Value() throws Exception {
+        ResponseParser sut = new ResponseParser();
+        Object actual = sut.parse(sh, strToStream(xmlDecl +
+                "<methodResponse>" +
+                "  <params>" +
+                "    <param>" +
+                "      <value>" +
+                "        <base64>QWVyaXM=</base64>" +
+                "      </value>" +
+                "    </param>" +
+                "  </params>" +
+                "</methodResponse>"), false);
+
+        String actualAsStr = new String((byte[]) actual, StandardCharsets.UTF_8);
+        assertEquals("Aeris", actualAsStr);
+    }
+
+    @Test
+    /**
+     * I'm not sure it really makes sense to support this case. But since I'm adding tests on code which existed
+     * for years, I guess it's better to avoid breaking retro compatibility.
+     */
+    public void testAcceptMissingHeader() throws Exception {
+        ResponseParser sut = new ResponseParser();
+        Object actual = sut.parse(sh, strToStream("<methodResponse>" +
+                "  <params>" +
+                "    <param>" +
+                "      <value><string>toto</string></value>" +
+                "    </param>" +
+                "  </params>" +
+                "</methodResponse>"), false);
+        assertEquals("toto", actual);
+    }
+
+    @Test
+    public void testXmlrpcError() throws Exception {
+        ResponseParser sut = new ResponseParser();
+        try {
+            sut.parse(sh, strToStream("<methodResponse>" +
+                    "  <fault>" +
+                    "    <value>" +
+                    "      <struct>" +
+                    "        <member>" +
+                    "          <name>faultCode</name>" +
+                    "          <value><int>4</int></value>" +
+                    "        </member>" +
+                    "        <member>" +
+                    "          <name>faultString</name>" +
+                    "          <value><string>error X occurred</string></value>" +
+                    "        </member>" +
+                    "      </struct>" +
+                    "    </value>" +
+                    "  </fault>" +
+                    "</methodResponse>"), false);
+            fail("The previous call should have thrown");
+        } catch (XMLRPCServerException e){
+            assertEquals("error X occurred [4]", e.getMessage());
+            assertEquals(4, e.getErrorNr());
+        }
+    }
+
+    @Test
+    public void testResponseWithXmlComment() throws Exception {
+        ResponseParser sut = new ResponseParser();
+        Object actual = sut.parse(sh, strToStream("<methodResponse>" +
+                "  <params>" +
+                "    <param>" +
+                "      <!--value><string>toto</string></value-->" +
+                "      <value><string>tata</string></value>" +
+                "    </param>" +
+                "  </params>" +
+                "</methodResponse>"), false);
+        assertEquals("tata", actual);
+    }
+
+    @Test
+    public void testResponseWithInlineXmlComment() throws Exception {
+        ResponseParser sut = new ResponseParser();
+        Object actual = sut.parse(sh, strToStream("<methodResponse>" +
+                "  <params>" +
+                "    <param>" +
+                "      <value><string>ti<!--blah-->ti</string></value>" +
+                "    </param>" +
+                "  </params>" +
+                "</methodResponse>"), false);
+        assertEquals("titi", actual);
+    }
+
+    @Test
+    public void testResponseWithSpecialChars() throws Exception {
+        ResponseParser sut = new ResponseParser();
+        Object actual = sut.parse(sh, strToStream("<methodResponse>" +
+                "  <params>" +
+                "    <param>" +
+                "      <value><string>to<to</string></value>" +
+                "    </param>" +
+                "  </params>" +
+                "</methodResponse>"), false);
+        assertEquals("to<to", actual);
+    }
+
+    @Test(expected = XMLRPCException.class)
+    public void testErrorMissingMethodResponseTag() throws Exception {
+        ResponseParser sut = new ResponseParser();
+        Object actual = sut.parse(sh, strToStream(
+                "  <params>" +
+                "    <param>" +
+                "      <value><string>toto</string></value>" +
+                "    </param>" +
+                "  </params>"), false);
+    }
+
+    @Test(expected = XMLRPCException.class)
+    public void testErrorMissingParamsTag() throws Exception {
+        ResponseParser sut = new ResponseParser();
+        Object actual = sut.parse(sh, strToStream("<methodResponse>" +
+                "    <param>" +
+                "      <value><string>toto</string></value>" +
+                "    </param>" +
+                "</methodResponse>"), false);
+    }
+
+    @Test(expected = XMLRPCException.class)
+    public void testErrorMissingParamTag() throws Exception {
+        ResponseParser sut = new ResponseParser();
+        Object actual = sut.parse(sh, strToStream("<methodResponse>" +
+                "  <params>" +
+                "      <value><string>toto</string></value>" +
+                "  </params>" +
+                "</methodResponse>"), false);
+    }
+
+    private static InputStream strToStream(String str){
+        return bytesToStream(str.getBytes(StandardCharsets.UTF_8));
+    }
+
+    private static InputStream bytesToStream(byte[] bytes){
+        return new ByteArrayInputStream(bytes);
+    }
+}


=====================================
src/test/java/de/timroes/axmlrpc/serializer/TestDateTimeSerializer.java
=====================================
@@ -120,6 +120,15 @@ public class TestDateTimeSerializer {
 		assertDeserializeEquals(new Date(81, 11, 31, 23, 59, 59), "1981-12-31T23:59:59Z");
 	}
 
+	@Test
+	public void canDoCustomDatetimeSerialization() {
+		String customDatetimeFormat = "yyyyMMdd'T'HH:mm:ss";
+		String expectedSerialization = "\n<dateTime.iso8601>19811231T23:58:59</dateTime.iso8601>\n";
+		Date date = new Date(81, 11, 31, 23, 58, 59);
+		String actualSerialization = new DateTimeSerializer(false, customDatetimeFormat).serialize(date).toString();
+		assertEquals(expectedSerialization, actualSerialization);
+	}
+
 	private void assertDeserializeEquals(Date expected, String toDeserialize) throws Exception {
 		Date date = (Date) new DateTimeSerializer(false).deserialize(toDeserialize);
 		assertEquals(expected, date);



View it on GitLab: https://salsa.debian.org/java-team/axmlrpc/-/commit/13ea0979f3cca92b14f06296a88954cf521aa102

-- 
View it on GitLab: https://salsa.debian.org/java-team/axmlrpc/-/commit/13ea0979f3cca92b14f06296a88954cf521aa102
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-java-commits/attachments/20221215/dc235657/attachment.htm>


More information about the pkg-java-commits mailing list