diff options
author | Jay Shrauner <shrauner@google.com> | 2014-07-22 12:36:21 -0700 |
---|---|---|
committer | Jay Shrauner <shrauner@google.com> | 2014-07-23 14:21:39 -0700 |
commit | 210ebaab315e389ffc66278e28ecd6230e412b5f (patch) | |
tree | 1f1c4d9d5fcdf0ca48cf31498eb2ce0ef952535a | |
parent | 4950d922815e16a0724e2509a6d04ccef8bd810b (diff) | |
download | vcard-210ebaab315e389ffc66278e28ecd6230e412b5f.tar.gz |
Fix import of iOS vcardsandroid-wear-5.1.1_r1android-wear-5.1.0_r1android-wear-5.0.0_r1android-m-preview-2android-m-preview-1android-m-previewandroid-cts-5.1_r9android-cts-5.1_r8android-cts-5.1_r7android-cts-5.1_r6android-cts-5.1_r5android-cts-5.1_r4android-cts-5.1_r3android-cts-5.1_r28android-cts-5.1_r27android-cts-5.1_r26android-cts-5.1_r25android-cts-5.1_r24android-cts-5.1_r23android-cts-5.1_r22android-cts-5.1_r21android-cts-5.1_r20android-cts-5.1_r2android-cts-5.1_r19android-cts-5.1_r18android-cts-5.1_r17android-cts-5.1_r16android-cts-5.1_r15android-cts-5.1_r14android-cts-5.1_r13android-cts-5.1_r10android-cts-5.1_r1android-cts-5.0_r9android-cts-5.0_r8android-cts-5.0_r7android-cts-5.0_r6android-cts-5.0_r5android-cts-5.0_r4android-cts-5.0_r3android-5.1.1_r9android-5.1.1_r8android-5.1.1_r7android-5.1.1_r6android-5.1.1_r5android-5.1.1_r4android-5.1.1_r38android-5.1.1_r37android-5.1.1_r36android-5.1.1_r35android-5.1.1_r34android-5.1.1_r33android-5.1.1_r30android-5.1.1_r3android-5.1.1_r29android-5.1.1_r28android-5.1.1_r26android-5.1.1_r25android-5.1.1_r24android-5.1.1_r23android-5.1.1_r22android-5.1.1_r20android-5.1.1_r2android-5.1.1_r19android-5.1.1_r18android-5.1.1_r17android-5.1.1_r16android-5.1.1_r15android-5.1.1_r14android-5.1.1_r13android-5.1.1_r12android-5.1.1_r10android-5.1.1_r1android-5.1.0_r5android-5.1.0_r4android-5.1.0_r3android-5.1.0_r1android-5.0.2_r3android-5.0.2_r1android-5.0.1_r1android-5.0.0_r7android-5.0.0_r6android-5.0.0_r5.1android-5.0.0_r5android-5.0.0_r4android-5.0.0_r3android-5.0.0_r2android-5.0.0_r1master-soonglollipop-wear-releaselollipop-releaselollipop-mr1-wfc-releaselollipop-mr1-releaselollipop-mr1-fi-releaselollipop-mr1-devlollipop-mr1-cts-releaselollipop-devlollipop-cts-release
Fix handling of multiline data blocks in v3.0 vcards with \r\r\n line
terminators.
Bug:16433675
Change-Id: I77c7c94fa1b13e18e53459e94c3c73ad53b7d8e2
-rw-r--r-- | java/com/android/vcard/VCardParserImpl_V21.java | 7 | ||||
-rw-r--r-- | java/com/android/vcard/VCardParserImpl_V30.java | 101 | ||||
-rw-r--r-- | tests/res/raw/v30_ios_613_multiline.vcf | 104 | ||||
-rw-r--r-- | tests/src/com/android/vcard/tests/VCardParserTests.java | 35 |
4 files changed, 175 insertions, 72 deletions
diff --git a/java/com/android/vcard/VCardParserImpl_V21.java b/java/com/android/vcard/VCardParserImpl_V21.java index aaf442f..386d626 100644 --- a/java/com/android/vcard/VCardParserImpl_V21.java +++ b/java/com/android/vcard/VCardParserImpl_V21.java @@ -450,7 +450,7 @@ import java.util.Set; } else if (paramName.equals("VALUE")) { handleValue(propertyData, paramValue); } else if (paramName.equals("ENCODING")) { - handleEncoding(propertyData, paramValue); + handleEncoding(propertyData, paramValue.toUpperCase()); } else if (paramName.equals("CHARSET")) { handleCharset(propertyData, paramValue); } else if (paramName.equals("LANGUAGE")) { @@ -862,7 +862,10 @@ import java.util.Set; if (line.length() == 0) { break; } - builder.append(line); + // Trim off any extraneous whitespace to handle 2.1 implementations + // that use 3.0 style line continuations. This is safe because space + // isn't a Base64 encoding value. + builder.append(line.trim()); } return builder.toString(); diff --git a/java/com/android/vcard/VCardParserImpl_V30.java b/java/com/android/vcard/VCardParserImpl_V30.java index eb63010..357383b 100644 --- a/java/com/android/vcard/VCardParserImpl_V30.java +++ b/java/com/android/vcard/VCardParserImpl_V30.java @@ -78,64 +78,41 @@ import java.util.Set; protected String getNonEmptyLine() throws IOException, VCardException { String line; StringBuilder builder = null; - while (true) { - line = mReader.readLine(); - if (line == null) { - if (builder != null) { - return builder.toString(); - } else if (mPreviousLine != null) { - String ret = mPreviousLine; - mPreviousLine = null; - return ret; - } - throw new VCardException("Reached end of buffer."); - } else if (line.length() == 0) { - if (builder != null) { - return builder.toString(); - } else if (mPreviousLine != null) { - String ret = mPreviousLine; - mPreviousLine = null; - return ret; - } + while ((line = mReader.readLine()) != null) { + // Skip empty lines in order to accomodate implementations that + // send line termination variations such as \r\r\n. + if (line.length() == 0) { + continue; } else if (line.charAt(0) == ' ' || line.charAt(0) == '\t') { - if (builder != null) { - // See Section 5.8.1 of RFC 2425 (MIME-DIR document). - // Following is the excerpts from it. - // - // DESCRIPTION:This is a long description that exists on a long line. - // - // Can be represented as: - // - // DESCRIPTION:This is a long description - // that exists on a long line. - // - // It could also be represented as: - // - // DESCRIPTION:This is a long descrip - // tion that exists o - // n a long line. - builder.append(line.substring(1)); - } else if (mPreviousLine != null) { + // RFC 2425 describes line continuation as \r\n followed by + // a single ' ' or '\t' whitespace character. + if (builder == null) { builder = new StringBuilder(); + } + if (mPreviousLine != null) { builder.append(mPreviousLine); mPreviousLine = null; - builder.append(line.substring(1)); - } else { - throw new VCardException("Space exists at the beginning of the line"); } + builder.append(line.substring(1)); } else { - if (mPreviousLine == null) { - mPreviousLine = line; - if (builder != null) { - return builder.toString(); - } - } else { - String ret = mPreviousLine; - mPreviousLine = line; - return ret; + if (builder != null || mPreviousLine != null) { + break; } + mPreviousLine = line; } } + + String ret = null; + if (builder != null) { + ret = builder.toString(); + } else if (mPreviousLine != null) { + ret = mPreviousLine; + } + mPreviousLine = line; + if (ret == null) { + throw new VCardException("Reached end of buffer."); + } + return ret; } /* @@ -313,30 +290,16 @@ import java.util.Set; } /** - * vCard 3.0 does not require two CRLF at the last of BASE64 data. - * It only requires that data should be MIME-encoded. + * This is only called from handlePropertyValue(), which has already + * read the first line of this property. With v3.0, the getNonEmptyLine() + * routine has already concatenated all following continuation lines. + * The routine is implemented in the V21 parser to concatenate v2.1 style + * data blocks, but is unnecessary here. */ @Override protected String getBase64(final String firstString) throws IOException, VCardException { - final StringBuilder builder = new StringBuilder(); - builder.append(firstString); - - while (true) { - final String line = getLine(); - if (line == null) { - throw new VCardException("File ended during parsing BASE64 binary"); - } - if (line.length() == 0) { - break; - } else if (!line.startsWith(" ") && !line.startsWith("\t")) { - mPreviousLine = line; - break; - } - builder.append(line); - } - - return builder.toString(); + return firstString; } /** diff --git a/tests/res/raw/v30_ios_613_multiline.vcf b/tests/res/raw/v30_ios_613_multiline.vcf new file mode 100644 index 0000000..4e737bd --- /dev/null +++ b/tests/res/raw/v30_ios_613_multiline.vcf @@ -0,0 +1,104 @@ +BEGIN:VCARD
+VERSION:3.0
+N:Smith;Bob;;;
+FN:Bob Smith
+ORG:Smith Auto Repair;
+item1.EMAIL;type=INTERNET;type=pref:bob@smithauto.com
+TEL;type=CELL;type=VOICE;type=pref:(650) 555-1212
+item2.URL;type=pref:www.smithauto.com
+item2.X-ABLabel:_$!<HomePage>!$_
+PHOTO;ENCODING=b;TYPE=JPEG:/9j/4AAQSkZJRgABAQAAAQABAAD/4gxYSUNDX1BST0ZJTEUA
+ AQEAAAxITGlubwIQAABtbnRyUkdCIFhZWiAHzgACAAkABgAxAABhY3NwTVNGVAAAAABJRUMgc1
+ JHQgAAAAAAAAAAAAAAAAAA9tYAAQAAAADTLUhQICAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAABFjcHJ0AAABUAAAADNkZXNjAAABhAAAAGx3dHB0AAAB8A
+ AAABRia3B0AAACBAAAABRyWFlaAAACGAAAABRnWFlaAAACLAAAABRiWFlaAAACQAAAABRkbW5k
+ AAACVAAAAHBkbWRkAAACxAAAAIh2dWVkAAADTAAAAIZ2aWV3AAAD1AAAACRsdW1pAAAD+AAAAB
+ RtZWFzAAAEDAAAACR0ZWNoAAAEMAAAAAxyVFJDAAAEPAAACAxnVFJDAAAEPAAACAxiVFJDAAAE
+ PAAACAx0ZXh0AAAAAENvcHlyaWdodCAoYykgMTk5OCBIZXdsZXR0LVBhY2thcmQgQ29tcGFueQ
+ AAZGVzYwAAAAAAAAASc1JHQiBJRUM2MTk2Ni0yLjEAAAAAAAAAAAAAABJzUkdCIElFQzYxOTY2
+ LTIuMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWF
+ laIAAAAAAAAPNRAAEAAAABFsxYWVogAAAAAAAAAAAAAAAAAAAAAFhZWiAAAAAAAABvogAAOPUA
+ AAOQWFlaIAAAAAAAAGKZAAC3hQAAGNpYWVogAAAAAAAAJKAAAA+EAAC2z2Rlc2MAAAAAAAAAFk
+ lFQyBodHRwOi8vd3d3LmllYy5jaAAAAAAAAAAAAAAAFklFQyBodHRwOi8vd3d3LmllYy5jaAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABkZXNjAAAAAAAAAC
+ 5JRUMgNjE5NjYtMi4xIERlZmF1bHQgUkdCIGNvbG91ciBzcGFjZSAtIHNSR0IAAAAAAAAAAAAA
+ AC5JRUMgNjE5NjYtMi4xIERlZmF1bHQgUkdCIGNvbG91ciBzcGFjZSAtIHNSR0IAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAZGVzYwAAAAAAAAAsUmVmZXJlbmNlIFZpZXdpbmcgQ29uZGl0aW9uIGlu
+ IElFQzYxOTY2LTIuMQAAAAAAAAAAAAAALFJlZmVyZW5jZSBWaWV3aW5nIENvbmRpdGlvbiBpbi
+ BJRUM2MTk2Ni0yLjEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHZpZXcAAAAAABOk/gAUXy4A
+ EM8UAAPtzAAEEwsAA1yeAAAAAVhZWiAAAAAAAEwJVgBQAAAAVx/nbWVhcwAAAAAAAAABAAAAAA
+ AAAAAAAAAAAAAAAAAAAo8AAAACc2lnIAAAAABDUlQgY3VydgAAAAAAAAQAAAAABQAKAA8AFAAZ
+ AB4AIwAoAC0AMgA3ADsAQABFAEoATwBUAFkAXgBjAGgAbQByAHcAfACBAIYAiwCQAJUAmgCfAK
+ QAqQCuALIAtwC8AMEAxgDLANAA1QDbAOAA5QDrAPAA9gD7AQEBBwENARMBGQEfASUBKwEyATgB
+ PgFFAUwBUgFZAWABZwFuAXUBfAGDAYsBkgGaAaEBqQGxAbkBwQHJAdEB2QHhAekB8gH6AgMCDA
+ IUAh0CJgIvAjgCQQJLAlQCXQJnAnECegKEAo4CmAKiAqwCtgLBAssC1QLgAusC9QMAAwsDFgMh
+ Ay0DOANDA08DWgNmA3IDfgOKA5YDogOuA7oDxwPTA+AD7AP5BAYEEwQgBC0EOwRIBFUEYwRxBH
+ 4EjASaBKgEtgTEBNME4QTwBP4FDQUcBSsFOgVJBVgFZwV3BYYFlgWmBbUFxQXVBeUF9gYGBhYG
+ JwY3BkgGWQZqBnsGjAadBq8GwAbRBuMG9QcHBxkHKwc9B08HYQd0B4YHmQesB78H0gflB/gICw
+ gfCDIIRghaCG4IggiWCKoIvgjSCOcI+wkQCSUJOglPCWQJeQmPCaQJugnPCeUJ+woRCicKPQpU
+ CmoKgQqYCq4KxQrcCvMLCwsiCzkLUQtpC4ALmAuwC8gL4Qv5DBIMKgxDDFwMdQyODKcMwAzZDP
+ MNDQ0mDUANWg10DY4NqQ3DDd4N+A4TDi4OSQ5kDn8Omw62DtIO7g8JDyUPQQ9eD3oPlg+zD88P
+ 7BAJECYQQxBhEH4QmxC5ENcQ9RETETERTxFtEYwRqhHJEegSBxImEkUSZBKEEqMSwxLjEwMTIx
+ NDE2MTgxOkE8UT5RQGFCcUSRRqFIsUrRTOFPAVEhU0FVYVeBWbFb0V4BYDFiYWSRZsFo8WshbW
+ FvoXHRdBF2UXiReuF9IX9xgbGEAYZRiKGK8Y1Rj6GSAZRRlrGZEZtxndGgQaKhpRGncanhrFGu
+ wbFBs7G2MbihuyG9ocAhwqHFIcexyjHMwc9R0eHUcdcB2ZHcMd7B4WHkAeah6UHr4e6R8THz4f
+ aR+UH78f6iAVIEEgbCCYIMQg8CEcIUghdSGhIc4h+yInIlUigiKvIt0jCiM4I2YjlCPCI/AkHy
+ RNJHwkqyTaJQklOCVoJZclxyX3JicmVyaHJrcm6CcYJ0kneierJ9woDSg/KHEooijUKQYpOClr
+ KZ0p0CoCKjUqaCqbKs8rAis2K2krnSvRLAUsOSxuLKIs1y0MLUEtdi2rLeEuFi5MLoIuty7uLy
+ QvWi+RL8cv/jA1MGwwpDDbMRIxSjGCMbox8jIqMmMymzLUMw0zRjN/M7gz8TQrNGU0njTYNRM1
+ TTWHNcI1/TY3NnI2rjbpNyQ3YDecN9c4FDhQOIw4yDkFOUI5fzm8Ofk6Njp0OrI67zstO2s7qj
+ voPCc8ZTykPOM9Ij1hPaE94D4gPmA+oD7gPyE/YT+iP+JAI0BkQKZA50EpQWpBrEHuQjBCckK1
+ QvdDOkN9Q8BEA0RHRIpEzkUSRVVFmkXeRiJGZ0arRvBHNUd7R8BIBUhLSJFI10kdSWNJqUnwSj
+ dKfUrESwxLU0uaS+JMKkxyTLpNAk1KTZNN3E4lTm5Ot08AT0lPk0/dUCdQcVC7UQZRUFGbUeZS
+ MVJ8UsdTE1NfU6pT9lRCVI9U21UoVXVVwlYPVlxWqVb3V0RXklfgWC9YfVjLWRpZaVm4WgdaVl
+ qmWvVbRVuVW+VcNVyGXNZdJ114XcleGl5sXr1fD19hX7NgBWBXYKpg/GFPYaJh9WJJYpxi8GND
+ Y5dj62RAZJRk6WU9ZZJl52Y9ZpJm6Gc9Z5Nn6Wg/aJZo7GlDaZpp8WpIap9q92tPa6dr/2xXbK
+ 9tCG1gbbluEm5rbsRvHm94b9FwK3CGcOBxOnGVcfByS3KmcwFzXXO4dBR0cHTMdSh1hXXhdj52
+ m3b4d1Z3s3gReG54zHkqeYl553pGeqV7BHtje8J8IXyBfOF9QX2hfgF+Yn7CfyN/hH/lgEeAqI
+ EKgWuBzYIwgpKC9INXg7qEHYSAhOOFR4Wrhg6GcobXhzuHn4gEiGmIzokziZmJ/opkisqLMIuW
+ i/yMY4zKjTGNmI3/jmaOzo82j56QBpBukNaRP5GokhGSepLjk02TtpQglIqU9JVflcmWNJaflw
+ qXdZfgmEyYuJkkmZCZ/JpomtWbQpuvnByciZz3nWSd0p5Anq6fHZ+Ln/qgaaDYoUehtqImopaj
+ BqN2o+akVqTHpTilqaYapoum/adup+CoUqjEqTepqaocqo+rAqt1q+msXKzQrUStuK4trqGvFq
+ +LsACwdbDqsWCx1rJLssKzOLOutCW0nLUTtYq2AbZ5tvC3aLfguFm40blKucK6O7q1uy67p7wh
+ vJu9Fb2Pvgq+hL7/v3q/9cBwwOzBZ8Hjwl/C28NYw9TEUcTOxUvFyMZGxsPHQce/yD3IvMk6yb
+ nKOMq3yzbLtsw1zLXNNc21zjbOts83z7jQOdC60TzRvtI/0sHTRNPG1EnUy9VO1dHWVdbY11zX
+ 4Nhk2OjZbNnx2nba+9uA3AXcit0Q3ZbeHN6i3ynfr+A24L3hROHM4lPi2+Nj4+vkc+T85YTmDe
+ aW5x/nqegy6LzpRunQ6lvq5etw6/vshu0R7ZzuKO6070DvzPBY8OXxcvH/8ozzGfOn9DT0wvVQ
+ 9d72bfb794r4Gfio+Tj5x/pX+uf7d/wH/Jj9Kf26/kv+3P9t////4QBMRXhpZgAATU0AKgAAAA
+ gAAYdpAAQAAAABAAAAGgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAAMqADAAQAAAABAAAA
+ MgAAAAD/2wBDAAIBAQIBAQICAQICAgICAwUDAwMDAwYEBAMFBwYHBwcGBgYHCAsJBwgKCAYGCQ
+ 0JCgsLDAwMBwkNDg0MDgsMDAv/2wBDAQICAgMCAwUDAwULCAYICwsLCwsLCwsLCwsLCwsLCwsL
+ CwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwv/wAARCAAyADIDASIAAhEBAxEB/8QAHw
+ AAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQR
+ BRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRk
+ 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
+ L/8ArzT/APSUejR/hx9Aooor6k0P/9k=
+END:VCARD
diff --git a/tests/src/com/android/vcard/tests/VCardParserTests.java b/tests/src/com/android/vcard/tests/VCardParserTests.java index 9b65593..2b63103 100644 --- a/tests/src/com/android/vcard/tests/VCardParserTests.java +++ b/tests/src/com/android/vcard/tests/VCardParserTests.java @@ -18,6 +18,7 @@ package com.android.vcard.tests; import com.android.vcard.VCardInterpreter; import com.android.vcard.VCardParser; import com.android.vcard.VCardParser_V21; +import com.android.vcard.VCardParser_V30; import com.android.vcard.VCardProperty; import com.android.vcard.exception.VCardException; @@ -136,6 +137,38 @@ public class VCardParserTests extends AndroidTestCase { } /** + * Test vCard containing v3.0 line continuations and with non-standard + * line terminators \r\r\n coming from iOS 6.1.3. Tests to make sure the + * parser correctly skips the extra line terminators and still + * successfully concatenates the multi-line block. + */ + public void testIosMultiline() throws IOException, VCardException { + InputStream inputStream = getContext().getResources().openRawResource(R.raw.v30_ios_613_multiline); + try { + VCardParser parser = new VCardParser_V30(); + MockVCardInterpreter interpreter = new MockVCardInterpreter(); + interpreter.addExpectedOrder(Order.START) + .addExpectedOrder(Order.START_ENTRY) + .addExpectedOrder(Order.PROPERTY_CREATED) // For VERSION + .addExpectedOrder(Order.PROPERTY_CREATED) // For N + .addExpectedOrder(Order.PROPERTY_CREATED) // For FN + .addExpectedOrder(Order.PROPERTY_CREATED) // For ORG + .addExpectedOrder(Order.PROPERTY_CREATED) // For item1 + .addExpectedOrder(Order.PROPERTY_CREATED) // For TEL + .addExpectedOrder(Order.PROPERTY_CREATED) // For item2 + .addExpectedOrder(Order.PROPERTY_CREATED) // For item3 + .addExpectedOrder(Order.PROPERTY_CREATED) // For PHOTO + .addExpectedOrder(Order.END_ENTRY) + .addExpectedOrder(Order.END); + parser.addInterpreter(interpreter); + parser.parse(inputStream); + interpreter.verify(); + } finally { + inputStream.close(); + } + } + + /** * Tests if {@link VCardParser#parse(InputStream)} parses the whole vCard file and * {@link VCardParser#parseOne(InputStream)} parses just first entry of a vCard file * with multiple vCard entries. @@ -206,4 +239,4 @@ public class VCardParserTests extends AndroidTestCase { } } -}
\ No newline at end of file +} |