Fix for malformed photo entry.
Blackberry vcard photo entry is not terminated with standard vcard 2.1
terminator. The vcard code is suppose to handle this irregularity already
but there was a bug where it would not work unless the next entry contained
a ':' right after the property name (i.e. "END:VCARD"). Cases with next
entries such as "TEL;TYPE=CELL:" was missed. Note the ":" is not right after
TEL.
Bug: 6979337
Change-Id: Ifa3dbb377b9da97ef7570c0f8eca8a1cb5e727a9
diff --git a/java/com/android/vcard/VCardParserImpl_V21.java b/java/com/android/vcard/VCardParserImpl_V21.java
index 7a24928..378b1c8 100644
--- a/java/com/android/vcard/VCardParserImpl_V21.java
+++ b/java/com/android/vcard/VCardParserImpl_V21.java
@@ -15,16 +15,16 @@
*/
package com.android.vcard;
+import android.text.TextUtils;
+import android.util.Base64;
+import android.util.Log;
+
import com.android.vcard.exception.VCardAgentNotSupportedException;
import com.android.vcard.exception.VCardException;
import com.android.vcard.exception.VCardInvalidCommentLineException;
import com.android.vcard.exception.VCardInvalidLineException;
import com.android.vcard.exception.VCardVersionException;
-import android.text.TextUtils;
-import android.util.Base64;
-import android.util.Log;
-
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
@@ -789,14 +789,29 @@
}
// vCard 2.1 requires two spaces at the end of BASE64 strings, but some vCard doesn't
- // have them. We try to detect those cases using semi-colon, given BASE64 doesn't
- // contain it. Specifically BASE64 doesn't have semi-colon in it, so we should be able
- // to detect the case safely.
- if (line.contains(":")) {
- if (getKnownPropertyNameSet().contains(
- line.substring(0, line.indexOf(":")).toUpperCase())) {
+ // have them. We try to detect those cases using colon and semi-colon, given BASE64
+ // does not contain it.
+ // E.g.
+ // TEL;TYPE=WORK:+5555555
+ // or
+ // END:VCARD
+ int colonIndex = line.indexOf(":");
+ int semiColonIndex = line.indexOf(";");
+ if (colonIndex > -1 || semiColonIndex > -1) {
+ // Find the minimum index that is greater than -1.
+ final int minIndex;
+ if (colonIndex == -1) {
+ minIndex = semiColonIndex;
+ } else if (semiColonIndex == -1) {
+ minIndex = colonIndex;
+ } else {
+ minIndex = Math.min(colonIndex, semiColonIndex);
+ }
+
+ if (getKnownPropertyNameSet().contains(line.substring(0, minIndex).toUpperCase())) {
Log.w(LOG_TAG, "Found a next property during parsing a BASE64 string, " +
- "which must not contain semi-colon. Treat the line as next property.");
+ "which must not contain semi-colon or colon. Treat the line as next "
+ + "property.");
Log.w(LOG_TAG, "Problematic line: " + line.trim());
break;
}
diff --git a/tests/res/raw/v21_blackberry_photo.vcf b/tests/res/raw/v21_blackberry_photo.vcf
new file mode 100644
index 0000000..04b37fa
--- /dev/null
+++ b/tests/res/raw/v21_blackberry_photo.vcf
@@ -0,0 +1,44 @@
+BEGIN:VCARD
+VERSION:2.1
+FN:boogie
+N:boogie
+PHOTO;ENCODING=BASE64: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
+ fGh4i/V4q4YNEfoiwAAAABJRU5ErkJggg==
+TEL;TYPE=WORK:+5555555
+TEL;TYPE=CELL:+5555556
+EMAIL;TYPE=INTERNET:forrestgump@walladalla.com
+END:VCARD
diff --git a/tests/src/com/android/vcard/tests/VCardImporterTests.java b/tests/src/com/android/vcard/tests/VCardImporterTests.java
index 3e5cb88..8c7bd68 100644
--- a/tests/src/com/android/vcard/tests/VCardImporterTests.java
+++ b/tests/src/com/android/vcard/tests/VCardImporterTests.java
@@ -15,12 +15,6 @@
*/
package com.android.vcard.tests;
-import com.android.vcard.VCardConfig;
-import com.android.vcard.tests.testutils.ContentValuesVerifier;
-import com.android.vcard.tests.testutils.ContentValuesVerifierElem;
-import com.android.vcard.tests.testutils.PropertyNodesVerifierElem.TypeSet;
-import com.android.vcard.tests.testutils.VCardTestsBase;
-
import android.content.ContentValues;
import android.provider.ContactsContract.CommonDataKinds.Email;
import android.provider.ContactsContract.CommonDataKinds.Event;
@@ -36,6 +30,12 @@
import android.provider.ContactsContract.CommonDataKinds.Website;
import android.provider.ContactsContract.Data;
+import com.android.vcard.VCardConfig;
+import com.android.vcard.tests.testutils.ContentValuesVerifier;
+import com.android.vcard.tests.testutils.ContentValuesVerifierElem;
+import com.android.vcard.tests.testutils.PropertyNodesVerifierElem.TypeSet;
+import com.android.vcard.tests.testutils.VCardTestsBase;
+
import java.util.Arrays;
public class VCardImporterTests extends VCardTestsBase {
@@ -1217,6 +1217,20 @@
new TypeSet("JPEG"), null);
}
+ public void testBase64Without2CrLfForBlackBerry_Parse() {
+ mVerifier.initForImportTest(V21, R.raw.v21_blackberry_photo);
+ mVerifier.addPropertyNodesVerifierElem()
+ .addExpectedNodeWithOrder("FN", "fullname")
+ .addExpectedNodeWithOrder("N", "name")
+ .addExpectedNodeWithOrder("PHOTO", null,
+ null, sPhotoByteArrayForComplicatedCase, mContentValuesForBase64V21,
+ null, null)
+ .addExpectedNodeWithOrder("TEL", "+5555555", new TypeSet("WORK"))
+ .addExpectedNodeWithOrder("TEL", "+5555556", new TypeSet("CELL"))
+ .addExpectedNodeWithOrder("EMAIL", "forrestgump@walladalla.com",
+ new TypeSet("INTERNET"));
+ }
+
public void testAndroidCustomPropertyV21() {
mVerifier.initForImportTest(V21, R.raw.v21_android_custom_prop);
final ContentValuesVerifierElem elem = mVerifier.addContentValuesVerifierElem();