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();