diff options
author | James.cf Lin <jamescflin@google.com> | 2021-06-02 21:42:28 +0800 |
---|---|---|
committer | James.cf Lin <jamescflin@google.com> | 2021-06-02 21:53:46 +0800 |
commit | 3808616ef55e642e440f27c90892c11f8e4f4f4b (patch) | |
tree | 4e4ff23315f8569c3c29cad3d811e6aa6be7ed71 | |
parent | ec617e6c7bf785debbcfc39368b162a25999ce89 (diff) | |
download | ims-3808616ef55e642e440f27c90892c11f8e4f4f4b.tar.gz |
Fix the PIDF parser may fail when the pidf xml contains the newline characters.
Bug: 186075898
Test: atest PidfParserTest; atest ImsServiceTest
Change-Id: Ie54f0d37a0118fa2ed96717942d0cae60254d3ff
-rw-r--r-- | src/java/com/android/ims/rcs/uce/presence/pidfparser/PidfParser.java | 15 | ||||
-rw-r--r-- | tests/src/com/android/ims/rcs/uce/presence/pidfparser/PidfParserTest.java | 144 |
2 files changed, 158 insertions, 1 deletions
diff --git a/src/java/com/android/ims/rcs/uce/presence/pidfparser/PidfParser.java b/src/java/com/android/ims/rcs/uce/presence/pidfparser/PidfParser.java index 774a48e6..2660f1d9 100644 --- a/src/java/com/android/ims/rcs/uce/presence/pidfparser/PidfParser.java +++ b/src/java/com/android/ims/rcs/uce/presence/pidfparser/PidfParser.java @@ -45,6 +45,8 @@ import java.time.Instant; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -58,6 +60,8 @@ public class PidfParser { private static final String LOG_TAG = UceUtils.getLogPrefix() + "PidfParser"; + private static final Pattern PIDF_PATTERN = Pattern.compile("\t|\r|\n"); + /** * Convert the RcsContactUceCapability to the string of pidf. */ @@ -98,6 +102,15 @@ public class PidfParser { */ public static @Nullable RcsContactUceCapability getRcsContactUceCapability(String pidf) { if (TextUtils.isEmpty(pidf)) { + Log.w(LOG_TAG, "getRcsContactUceCapability: The given pidf is empty"); + return null; + } + + // Filter the newline characters + Matcher matcher = PIDF_PATTERN.matcher(pidf); + String formattedPidf = matcher.replaceAll(""); + if (TextUtils.isEmpty(formattedPidf)) { + Log.w(LOG_TAG, "getRcsContactUceCapability: The formatted pidf is empty"); return null; } @@ -106,7 +119,7 @@ public class PidfParser { // Init the instance of the parser XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser(); parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true); - reader = new StringReader(pidf); + reader = new StringReader(formattedPidf); parser.setInput(reader); // Start parsing diff --git a/tests/src/com/android/ims/rcs/uce/presence/pidfparser/PidfParserTest.java b/tests/src/com/android/ims/rcs/uce/presence/pidfparser/PidfParserTest.java index 73581eea..41f0a3ad 100644 --- a/tests/src/com/android/ims/rcs/uce/presence/pidfparser/PidfParserTest.java +++ b/tests/src/com/android/ims/rcs/uce/presence/pidfparser/PidfParserTest.java @@ -21,6 +21,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import android.net.Uri; import android.telephony.ims.RcsContactPresenceTuple; @@ -34,6 +35,7 @@ import androidx.test.filters.SmallTest; import com.android.ims.ImsTestBase; import java.time.Instant; +import java.util.ArrayList; import java.util.List; import org.junit.After; @@ -109,6 +111,93 @@ public class PidfParserTest extends ImsTestBase { @Test @SmallTest + public void testConvertFromNewlineIncludedPidfToRcsContactUceCapability() throws Exception { + final String contact = "tel:+11234567890"; + + final RcsContactPresenceTuple.Builder tuple1Builder = new RcsContactPresenceTuple.Builder( + "open", + "org.3gpp.urn:urn-7:3gpp-application.ims.iari.rcse.dp", + "1.0"); + tuple1Builder.setServiceDescription("DiscoveryPresence") + .setContactUri(Uri.parse(contact)); + + final RcsContactPresenceTuple.Builder tuple2Builder = new RcsContactPresenceTuple.Builder( + "open", + "org.openmobilealliance:StandaloneMsg", + "2.0"); + tuple2Builder.setServiceDescription("StandaloneMsg") + .setContactUri(Uri.parse(contact)); + + final RcsContactPresenceTuple.Builder tuple3Builder = new RcsContactPresenceTuple.Builder( + "open", + "org.3gpp.urn:urn-7:3gpp-service.ims.icsi.mmtel", + "1.0"); + tuple3Builder.setServiceDescription("VoLTE service"); + ServiceCapabilities.Builder capBuilder = new ServiceCapabilities.Builder(true, true); + tuple3Builder.setServiceCapabilities(capBuilder.build()) + .setContactUri(Uri.parse(contact)); + + final List<RcsContactPresenceTuple> expectedTupleList = new ArrayList<>(3); + expectedTupleList.add(tuple1Builder.build()); + expectedTupleList.add(tuple2Builder.build()); + expectedTupleList.add(tuple3Builder.build()); + + // Create the newline included PIDF data + String pidfData = getPidfDataWithNewlineCharacters(contact); + + // Convert to the class RcsContactUceCapability + RcsContactUceCapability capabilities = PidfParser.getRcsContactUceCapability(pidfData); + + assertNotNull(capabilities); + assertEquals(Uri.parse(contact), capabilities.getContactUri()); + assertEquals(RcsContactUceCapability.SOURCE_TYPE_NETWORK, capabilities.getSourceType()); + assertEquals(RcsContactUceCapability.CAPABILITY_MECHANISM_PRESENCE, + capabilities.getCapabilityMechanism()); + + List<RcsContactPresenceTuple> presenceTupleList = capabilities.getCapabilityTuples(); + assertNotNull(presenceTupleList); + assertEquals(expectedTupleList.size(), presenceTupleList.size()); + + for(RcsContactPresenceTuple tuple : presenceTupleList) { + String serviceId = tuple.getServiceId(); + RcsContactPresenceTuple expectedTuple = findTuple(serviceId, expectedTupleList); + if (expectedTuple == null) { + fail("The service ID is invalid"); + } + + assertEquals(expectedTuple.getStatus(), tuple.getStatus()); + assertEquals(expectedTuple.getServiceVersion(), tuple.getServiceVersion()); + assertEquals(expectedTuple.getServiceDescription(), tuple.getServiceDescription()); + assertEquals(expectedTuple.getTime(), tuple.getTime()); + assertEquals(expectedTuple.getContactUri(), tuple.getContactUri()); + + ServiceCapabilities expectedCap = expectedTuple.getServiceCapabilities(); + ServiceCapabilities resultCap = tuple.getServiceCapabilities(); + if (expectedCap != null) { + assertNotNull(resultCap); + assertEquals(expectedCap.isAudioCapable(), resultCap.isAudioCapable()); + assertEquals(expectedCap.isVideoCapable(), resultCap.isVideoCapable()); + } else { + assertNull(resultCap); + } + } + } + + private RcsContactPresenceTuple findTuple(String serviceId, + List<RcsContactPresenceTuple> expectedTupleList) { + if (serviceId == null) { + return null; + } + for (RcsContactPresenceTuple tuple : expectedTupleList) { + if (serviceId.equalsIgnoreCase(tuple.getServiceId())) { + return tuple; + } + } + return null; + } + + @Test + @SmallTest public void testConvertToRcsContactUceCapabilityForMultipleTuples() throws Exception { final String contact = "sip:+11234567890@test"; final String serviceId1 = "org.3gpp.urn:urn-7:3gpp-application.ims.iari.rcse.dp"; @@ -241,6 +330,61 @@ public class PidfParserTest extends ImsTestBase { return pidfBuilder.toString(); } + private String getPidfDataWithNewlineCharacters(String contact) { + String pidf = "<presence xmlns=\"urn:ietf:params:xml:ns:pidf\" " + + "xmlns:op=\"urn:oma:xml:prs:pidf:oma-pres\" " + + "xmlns:b=\"urn:ietf:params:xml:ns:pidf:caps\" " + + "entity=\"" + contact + "\">\n" + // The first tuple + + "<tuple id=\"DiscoveryPres\">\n" + + "<status>\n" + + "<basic>open</basic>\n" + + "</status>\n" + + "<op:service-description>\n" + + "<op:service-id>" + + "org.3gpp.urn:urn-7:3gpp-application.ims.iari.rcse.dp</op:service-id>\n" + + "<op:version>1.0</op:version>\n" + + "<op:description>DiscoveryPresence</op:description>\n" + + "</op:service-description>\n" + + "<contact>tel:+11234567890</contact>\n" + + "</tuple>\n" + // The second tuple + + "<tuple id=\"VoLTE\">\n" + + "<status>\n" + + "<basic>open</basic>\n" + + "</status>\n" + + "<b:servcaps>\n" + + "<b:audio>true</b:audio>\n" + + "<b:video>true</b:video>\n" + + "<b:duplex>\n" + + "<b:supported>\n" + + "<b:full/>\n" + + "</b:supported>\n" + + "</b:duplex>\n" + + "</b:servcaps>\n" + + "<op:service-description>\n" + + "<op:service-id>org.3gpp.urn:urn-7:3gpp-service.ims.icsi.mmtel</op:service-id>\n" + + "<op:version>1.0</op:version>\n" + + "<op:description>VoLTE service</op:description>\n" + + "</op:service-description>\n" + + "<contact>tel:+11234567890</contact>\n" + + "</tuple>\n" + // The third tuple + + "<tuple id=\"StandaloneMsg\">\n" + + "<status>\n" + + "<basic>open</basic>\n" + + "</status>\n" + + "<op:service-description>\n" + + "<op:service-id>org.openmobilealliance:StandaloneMsg</op:service-id>\n" + + "<op:version>2.0</op:version>\n" + + "<op:description>StandaloneMsg</op:description>\n" + + "</op:service-description>\n" + + "<contact>tel:+11234567890</contact>\n" + + "</tuple>\n" + + "</presence>"; + return pidf; + } + private String getPidfDataWithMultiTuples(String contact, String serviceId1, String serviceDescription1, String serviceId2, String serviceDescription2, boolean audioSupported, boolean videoSupported) { |