diff options
author | Jay Shrauner <shrauner@google.com> | 2014-05-10 23:27:20 -0700 |
---|---|---|
committer | Jay Shrauner <shrauner@google.com> | 2014-05-16 10:22:41 -0700 |
commit | 3d52ff729b82a20802bb6d5a8952040f4d961cef (patch) | |
tree | 8357c464bf40133e8a5a4fb4d90e75cd9c876c4c | |
parent | 0347367531674a83ff36a4fbc222319d5e1693d9 (diff) | |
download | android_packages_apps_Exchange-3d52ff729b82a20802bb6d5a8952040f4d961cef.tar.gz android_packages_apps_Exchange-3d52ff729b82a20802bb6d5a8952040f4d961cef.tar.bz2 android_packages_apps_Exchange-3d52ff729b82a20802bb6d5a8952040f4d961cef.zip |
Fix handling of encoded ints
Fix encoding of ints to handle ints with high bit set. Modify Parser to
detect when it is decoding a run-on badly encoded int (ie, >5 bytes).
Bug:14817987
Change-Id: I4a21b126d03e2e244b0fd4c4fb4821d165897ad6
-rw-r--r-- | src/com/android/exchange/EasOutboxService.java | 4 | ||||
-rw-r--r-- | src/com/android/exchange/adapter/Parser.java | 174 | ||||
-rw-r--r-- | src/com/android/exchange/adapter/Serializer.java | 162 | ||||
-rw-r--r-- | src/com/android/exchange/adapter/Tags.java | 20 | ||||
-rw-r--r-- | src/com/android/exchange/eas/EasOutboxSync.java | 4 | ||||
-rw-r--r-- | tests/src/com/android/exchange/TagsTests.java | 40 | ||||
-rw-r--r-- | tests/src/com/android/exchange/adapter/FolderSyncParserTests.java | 2 | ||||
-rw-r--r-- | tests/src/com/android/exchange/adapter/ParserTest.java | 22 | ||||
-rw-r--r-- | tests/src/com/android/exchange/adapter/SerializerTests.java | 11 |
9 files changed, 228 insertions, 211 deletions
diff --git a/src/com/android/exchange/EasOutboxService.java b/src/com/android/exchange/EasOutboxService.java index 8c8a43f6..84d6108d 100644 --- a/src/com/android/exchange/EasOutboxService.java +++ b/src/com/android/exchange/EasOutboxService.java @@ -182,9 +182,9 @@ public class EasOutboxService extends EasSyncService { s.start(Tags.COMPOSE_MIME); // Send opaque data from the file stream if (withData) { - s.opaque(mFileStream, (int)mFileLength); + s.opaque(mFileStream, (int) mFileLength); } else { - s.opaqueWithoutData((int)mFileLength); + s.writeOpaqueHeader((int) mFileLength); } // And we're done s.end().end().done(); diff --git a/src/com/android/exchange/adapter/Parser.java b/src/com/android/exchange/adapter/Parser.java index 960e9dd1..cc8f747f 100644 --- a/src/com/android/exchange/adapter/Parser.java +++ b/src/com/android/exchange/adapter/Parser.java @@ -68,9 +68,6 @@ public abstract class Parser { private static final int NOT_ENDED = Integer.MIN_VALUE; private static final int EOF_BYTE = -1; - // Where tags start in a page - private static final int TAG_BASE = 5; - private boolean logging = false; private boolean capture = false; @@ -82,50 +79,55 @@ public abstract class Parser { // The current tag depth private int depth; - // The current tag table (i.e. the tag table for the current page) - private String[] tagTable; - - // An array of tag tables, as defined in EasTags - static private String[][] tagTables = new String[Tags.pages.length + 1][]; - // The stack of names of tags being processed; used when debug = true private String[] nameArray = new String[32]; public class Tag { - public int index; + private final int mPage; + private final int mIndex; // Whether the tag is associated with content (a value) - public boolean noContent; - public String name; + public final boolean mNoContent; + private final String mName; - public Tag(int id) { + public Tag(final int page, final int id) { + mPage = page; // The tag is in the low 6 bits - index = id & Tags.PAGE_MASK; + mIndex = id & Tags.PAGE_MASK; // If the high bit is set, there is content (a value) to be read - noContent = (id & Wbxml.WITH_CONTENT) == 0; - if (index < TAG_BASE) { - name = "unsupported-WBXML"; - } else if (tagTable == null || index - TAG_BASE >= tagTable.length) { - name = "unknown"; + mNoContent = (id & Wbxml.WITH_CONTENT) == 0; + if (Tags.isGlobalTag(mIndex)) { + mName = "unsupported-WBXML"; + } else if (!Tags.isValidTag(mPage, mIndex)) { + mName = "unknown"; } else { - name = tagTable[index - TAG_BASE]; + mName = Tags.getTagName(mPage, mIndex); } } + + public int getTagNum() { + return (mPage << Tags.PAGE_SHIFT) | mIndex; + } + + @Override + public String toString() { + return mName; + } } // The stack of tags being processed - private Deque<Tag> startTagArray = new ArrayDeque<Tag>(); + private final Deque<Tag> startTagArray = new ArrayDeque<Tag>(); private Tag startTag; - private Tag endTag; - - // The type of the last token read + // The type of the last token read (eg, TEXT, OPAQUE, END, etc). private int type; - // The current page + // The current page. As of EAS 14.1, this is a value 0-24. private int page; - // The current tag + // The current tag. The low order 6 bits contain the tag index and the + // higher order bits the page number. The format matches that used for + // the tag enums defined in Tags.java. public int tag; // Whether the current tag is associated with content (a value) @@ -165,7 +167,7 @@ public abstract class Parser { super("WBXML format error"); } - EasParserException(String reason) { + EasParserException(final String reason) { super(reason); } } @@ -174,21 +176,7 @@ public abstract class Parser { return false; } - /** - * Initialize the tag tables; they are constant - * - */ - { - String[][] pages = Tags.pages; - for (int i = 0; i < pages.length; i++) { - String[] page = pages[i]; - if (page.length > 0) { - tagTables[i] = page; - } - } - } - - public Parser(InputStream in) throws IOException { + public Parser(final InputStream in) throws IOException { setInput(in, true); logging = Eas.PARSER_LOG; } @@ -198,7 +186,7 @@ public abstract class Parser { * @param parser an existing, initialized parser * @throws IOException */ - public Parser(Parser parser) throws IOException { + public Parser(final Parser parser) throws IOException { setInput(parser.in, false); logging = Eas.PARSER_LOG; } @@ -210,7 +198,7 @@ public abstract class Parser { * @param val the desired state for debug output */ @VisibleForTesting - public void setDebug(boolean val) { + public void setDebug(final boolean val) { logging = val; } @@ -230,9 +218,10 @@ public abstract class Parser { /** * Turns off data capture; writes the captured data to a specified file. */ - public void captureOff(Context context, String file) { + public void captureOff(final Context context, final String file) { try { - FileOutputStream out = context.openFileOutput(file, Context.MODE_WORLD_WRITEABLE); + final FileOutputStream out = context.openFileOutput(file, + Context.MODE_WORLD_WRITEABLE); out.write(captureArray.toString().getBytes()); out.close(); } catch (FileNotFoundException e) { @@ -251,7 +240,7 @@ public abstract class Parser { * @throws IOException */ public byte[] getValueBytes() throws IOException { - final String name = startTag.name; + final String name = startTag.toString(); getNext(); // This means there was no value given, just <Foo/>; we'll return empty array @@ -281,7 +270,7 @@ public abstract class Parser { * @throws IOException */ public String getValue() throws IOException { - final String name = startTag.name; + final String name = startTag.toString(); getNext(); // This means there was no value given, just <Foo/>; we'll return empty string for now @@ -312,17 +301,16 @@ public abstract class Parser { * @throws IOException */ public int getValueInt() throws IOException { - String val = getValue(); + final String val = getValue(); if (val.length() == 0) { return 0; } - final String name = startTag.name; int num; try { num = Integer.parseInt(val); } catch (NumberFormatException e) { - throw new EasParserException("Tag " + name + ": " + e.getMessage()); + throw new EasParserException("Tag " + startTag + ": " + e.getMessage()); } return num; } @@ -338,21 +326,19 @@ public abstract class Parser { * @return the next tag found * @throws IOException */ - public int nextTag(int endingTag) throws IOException { - // Lose the page information - final int endTagIndex = endingTag & Tags.PAGE_MASK; + public int nextTag(final int endingTag) throws IOException { while (getNext() != DONE) { // If we're a start, set tag to include the page and return it if (type == START) { - tag = page | startTag.index; + tag = startTag.getTagNum(); return tag; // If we're at the ending tag we're looking for, return the END signal - } else if (type == END && startTag.index == endTagIndex) { + } else if (type == END && startTag.getTagNum() == endingTag) { return END; } } // We're at end of document here. If we're looking for it, return END_DOCUMENT - if (endTagIndex == START_DOCUMENT) { + if (endingTag == START_DOCUMENT) { return END_DOCUMENT; } // Otherwise, we've prematurely hit end of document, so exception out @@ -368,10 +354,10 @@ public abstract class Parser { * @throws IOException */ public void skipTag() throws IOException { - int thisTag = startTag.index; + final int thisTag = startTag.getTagNum(); // Just loop until we hit the end of the current tag while (getNext() != DONE) { - if (type == END && startTag.index == thisTag) { + if (type == END && startTag.getTagNum() == thisTag) { return; } } @@ -388,15 +374,12 @@ public abstract class Parser { * @param in the InputStream associated with this parser * @throws IOException */ - public void setInput(InputStream in, boolean initialize) throws IOException { + public void setInput(final InputStream in, final boolean initialize) throws IOException { this.in = in; if ((in != null) && initialize) { // If we fail on the very first byte, report an empty stream try { final int version = readByte(); // version - if (version > 3) { - log("WBXML version " + version + " is newer than supported version 3"); - } } catch (EofException e) { throw new EmptyStreamException(); } @@ -407,11 +390,10 @@ public abstract class Parser { throw new EasParserException("WBXML string table unsupported"); } } - tagTable = tagTables[0]; } @VisibleForTesting - void resetInput(InputStream in) { + void resetInput(final InputStream in) { this.in = in; try { // Read leading zero @@ -420,20 +402,23 @@ public abstract class Parser { } } - void log(String str) { + void log(final String str) { if (!logging) { return; } + final String logStr; int cr = str.indexOf('\n'); if (cr > 0) { - str = str.substring(0, cr); + logStr = str.substring(0, cr); + } else { + logStr = str; } final char [] charArray = new char[startTagArray.size() * 2]; Arrays.fill(charArray, ' '); final String indent = new String(charArray); - LogUtils.v(LOG_TAG, indent + str); + LogUtils.v(LOG_TAG, "%s", indent + logStr); if (Eas.FILE_LOG) { - FileLogger.log(LOG_TAG, str); + FileLogger.log(LOG_TAG, logStr); } } @@ -443,22 +428,21 @@ public abstract class Parser { } } - protected void pushTag(int id) { - page = id >> Tags.PAGE_SHIFT; - tagTable = tagTables[page]; + protected void pushTag(final int id) { + page = id >>> Tags.PAGE_SHIFT; push(id); } private void pop() { // Retrieve the now-current startTag from our stack startTag = startTagArray.removeFirst(); - log("</" + startTag.name + '>'); + log("</" + startTag + '>'); } - private void push(int id) { - startTag = new Tag(id); - noContent = startTag.noContent; - log("<" + startTag.name + (startTag.noContent ? '/' : "") + '>'); + private void push(final int id) { + startTag = new Tag(page, id); + noContent = startTag.mNoContent; + log("<" + startTag + (noContent ? '/' : "") + '>'); // Save the startTag to our stack startTagArray.addFirst(startTag); } @@ -485,18 +469,14 @@ public abstract class Parser { int id = read(); while (id == Wbxml.SWITCH_PAGE) { // Get the new page number - int pg = readByte(); - // Save the shifted page to add into the startTag in nextTag - page = pg << Tags.PAGE_SHIFT; + page = readByte(); // Retrieve the current tag table - if (pg >= tagTables.length) { + if (!Tags.isValidPage(page)) { // Unknown code page. These seem to happen mostly because of // invalid data from the server so throw an exception here. - throw new EasParserException("Unknown code page " + pg); - } else { - tagTable = tagTables[pg]; + throw new EasParserException("Unknown code page " + page); } - logVerbose((tagTable == null ? "Unknown " : "") + "Page: " + page); + logVerbose("Page: " + page); id = read(); } @@ -515,22 +495,22 @@ public abstract class Parser { // Inline string type = TEXT; text = readInlineString(); - log(startTag.name + ": " + text); + log(startTag + ": " + text); break; case Wbxml.OPAQUE: // Integer length + opaque data type = OPAQUE; - int length = readInt(); + final int length = readInt(); bytes = new byte[length]; for (int i = 0; i < length; i++) { bytes[i] = (byte)readByte(); } - log(startTag.name + ": (opaque:" + length + ") "); + log(startTag + ": (opaque:" + length + ") "); break; default: - if ((id & Tags.PAGE_MASK) < TAG_BASE) { + if (Tags.isGlobalTag(id & Tags.PAGE_MASK)) { throw new EasParserException(String.format( "Unhandled WBXML global token 0x%02X", id)); } @@ -571,11 +551,21 @@ public abstract class Parser { return i; } + /** + * Throws EasParserException if detects integer encoded with more than 5 + * bytes. A uint_32 needs 5 bytes to fully encode 32 bits so if the high + * bit is set for more than 4 bytes, something is wrong with the data + * stream. + */ private int readInt() throws IOException { int result = 0; int i; + int numBytes = 0; do { + if (++numBytes > 5) { + throw new EasParserException("Invalid integer encoding, too many bytes"); + } i = readByte(); result = (result << 7) | (i & 0x7f); } while ((i & 0x80) != 0); @@ -590,9 +580,9 @@ public abstract class Parser { * @throws IOException */ private String readInlineString() throws IOException { - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(256); + final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(256); while (true) { - int i = read(); + final int i = read(); if (i == 0) { break; } else if (i == EOF_BYTE) { @@ -601,7 +591,7 @@ public abstract class Parser { outputStream.write(i); } outputStream.flush(); - String res = outputStream.toString("UTF-8"); + final String res = outputStream.toString("UTF-8"); outputStream.close(); return res; } diff --git a/src/com/android/exchange/adapter/Serializer.java b/src/com/android/exchange/adapter/Serializer.java index 4cd187ed..d28e4c2c 100644 --- a/src/com/android/exchange/adapter/Serializer.java +++ b/src/com/android/exchange/adapter/Serializer.java @@ -24,6 +24,7 @@ package com.android.exchange.adapter; import android.content.ContentValues; +import android.text.TextUtils; import com.android.exchange.Eas; import com.android.exchange.utility.FileLogger; @@ -34,6 +35,9 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.util.ArrayDeque; +import java.util.Arrays; +import java.util.Deque; public class Serializer { private static final String TAG = Eas.LOG_TAG; @@ -42,10 +46,9 @@ public class Serializer { private final OutputStream mOutput; private int mPendingTag = NOT_PENDING; - private int mDepth; - private String[] mNameStack = new String[20]; + private final Deque<String> mNameStack = new ArrayDeque<String>(); private int mTagPage = 0; - private boolean mLogging = LogUtils.isLoggable(TAG, LogUtils.VERBOSE); + private final boolean mLogging = LogUtils.isLoggable(TAG, LogUtils.VERBOSE); public Serializer() throws IOException { this(new ByteArrayOutputStream(), true); @@ -67,7 +70,8 @@ public class Serializer { * @param _logging whether or not to log our output * @throws IOException */ - public Serializer(OutputStream outputStream, boolean startDocument) throws IOException { + public Serializer(final OutputStream outputStream, final boolean startDocument) + throws IOException { super(); mOutput = outputStream; if (startDocument) { @@ -77,37 +81,47 @@ public class Serializer { } } - void log(String str) { - int cr = str.indexOf('\n'); + void log(final String str) { + if (!mLogging) { + return; + } + final String logStr; + final int cr = str.indexOf('\n'); if (cr > 0) { - str = str.substring(0, cr); + logStr = str.substring(0, cr); + } else { + logStr = str; } - LogUtils.v(TAG, "%s", str); + final char [] charArray = new char[mNameStack.size() * 2]; + Arrays.fill(charArray, ' '); + final String indent = new String(charArray); + LogUtils.v(TAG, "%s%s", indent, logStr); if (Eas.FILE_LOG) { - FileLogger.log(TAG, str); + FileLogger.log(TAG, logStr); } } public void done() throws IOException { - if (mDepth != 0) { + if (mNameStack.size() != 0 || mPendingTag != NOT_PENDING) { throw new IOException("Done received with unclosed tags"); } mOutput.flush(); } - public void startDocument() throws IOException{ + public void startDocument() throws IOException { mOutput.write(0x03); // version 1.3 mOutput.write(0x01); // unknown or missing public identifier mOutput.write(106); // UTF-8 mOutput.write(0); // 0 length string array } - public void checkPendingTag(boolean degenerated) throws IOException { - if (mPendingTag == NOT_PENDING) + private void checkPendingTag(final boolean degenerated) throws IOException { + if (mPendingTag == NOT_PENDING) { return; + } - int page = mPendingTag >> Tags.PAGE_SHIFT; - int tag = mPendingTag & Tags.PAGE_MASK; + final int page = mPendingTag >> Tags.PAGE_SHIFT; + final int tag = mPendingTag & Tags.PAGE_MASK; if (page != mTagPage) { mTagPage = page; mOutput.write(Wbxml.SWITCH_PAGE); @@ -115,18 +129,24 @@ public class Serializer { } mOutput.write(degenerated ? tag : tag | Wbxml.WITH_CONTENT); - if (mLogging) { - String name = Tags.pages[page][tag - 5]; - mNameStack[mDepth] = name; - log("<" + name + '>'); + String name = "unknown"; + if (!Tags.isValidPage(page)) { + log("Unrecognized page " + page); + } else if (!Tags.isValidTag(page, tag)) { + log("Unknown tag " + tag + " on page " + page); + } else { + name = Tags.getTagName(page, tag); + } + log("<" + name + (degenerated ? "/>" : ">")); + if (!degenerated) { + mNameStack.addFirst(name); } mPendingTag = NOT_PENDING; } - public Serializer start(int tag) throws IOException { + public Serializer start(final int tag) throws IOException { checkPendingTag(false); mPendingTag = tag; - mDepth++; return this; } @@ -135,97 +155,115 @@ public class Serializer { checkPendingTag(true); } else { mOutput.write(Wbxml.END); - if (mLogging) { - log("</" + mNameStack[mDepth] + '>'); - } + final String tagName = mNameStack.removeFirst(); + log("</" + tagName + '>'); } - mDepth--; return this; } - public Serializer tag(int t) throws IOException { - start(t); + public Serializer tag(final int tag) throws IOException { + start(tag); end(); return this; } - public Serializer data(int tag, String value) throws IOException { - if (value == null) { - LogUtils.e(TAG, "Writing null data for tag: " + tag); - } + /** + * Writes <tag>value</tag>. Throws IOException for null strings. + */ + public Serializer data(final int tag, final String value) throws IOException { start(tag); text(value); end(); return this; } - public Serializer text(String text) throws IOException { + /** + * Writes out inline string. Throws IOException for null strings. + */ + public Serializer text(final String text) throws IOException { if (text == null) { - LogUtils.e(TAG, "Writing null text for pending tag: " + mPendingTag); + throw new IOException("Null text write for pending tag: " + mPendingTag); } checkPendingTag(false); - mOutput.write(Wbxml.STR_I); - writeLiteralString(mOutput, text); - if (mLogging) { - log(text); - } + writeInlineString(mOutput, text); + log(text); return this; } - public Serializer opaque(InputStream is, int length) throws IOException { - checkPendingTag(false); - mOutput.write(Wbxml.OPAQUE); - writeInteger(mOutput, length); - if (mLogging) { - log("Opaque, length: " + length); - } + /** + * Writes out opaque data blocks. Throws IOException for negative buffer + * sizes or if is unable to read sufficient bytes from input stream. + */ + public Serializer opaque(final InputStream is, final int length) throws IOException { + writeOpaqueHeader(length); + log("opaque: " + length); // Now write out the opaque data in batches - byte[] buffer = new byte[BUFFER_SIZE]; - while (length > 0) { - int bytesRead = is.read(buffer, 0, Math.min(BUFFER_SIZE, length)); + final byte[] buffer = new byte[BUFFER_SIZE]; + int totalBytesRead = 0; + while (totalBytesRead < length) { + final int bytesRead = is.read(buffer, 0, Math.min(BUFFER_SIZE, length)); if (bytesRead == -1) { - break; + throw new IOException("Invalid opaque data block; read " + + totalBytesRead + " bytes but expected " + length); } mOutput.write(buffer, 0, bytesRead); - length -= bytesRead; + totalBytesRead += bytesRead; } return this; } - public Serializer opaqueWithoutData(int length) throws IOException { + /** + * Writes out opaque data header, without the actual opaque data bytes. + * Used internally by opaque(), and externally to calculate content length + * without having to allocate the memory for the data copy. + * Throws IOException if length is negative; is a no-op for length 0. + */ + public Serializer writeOpaqueHeader(final int length) throws IOException { + if (length < 0) { + throw new IOException("Invalid negative opaque data length " + length); + } + if (length == 0) { + return this; + } checkPendingTag(false); mOutput.write(Wbxml.OPAQUE); writeInteger(mOutput, length); return this; } - void writeInteger(OutputStream out, int i) throws IOException { - byte[] buf = new byte[5]; + @VisibleForTesting + static void writeInteger(final OutputStream out, int i) throws IOException { + final byte[] buf = new byte[5]; int idx = 0; do { buf[idx++] = (byte) (i & 0x7f); - i = i >> 7; + // Use >>> to shift in 0s so loop terminates + i = i >>> 7; } while (i != 0); while (idx > 1) { out.write(buf[--idx] | 0x80); } out.write(buf[0]); - if (mLogging) { - log(Integer.toString(i)); - } } - void writeLiteralString(OutputStream out, String s) throws IOException { - byte[] data = s.getBytes("UTF-8"); + private static void writeInlineString(final OutputStream out, final String s) + throws IOException { + out.write(Wbxml.STR_I); + final byte[] data = s.getBytes("UTF-8"); out.write(data); out.write(0); } - public void writeStringValue (ContentValues cv, String key, int tag) throws IOException { - String value = cv.getAsString(key); - if (value != null && value.length() > 0) { + /** + * Looks up key in cv; if absent or empty writes out <tag/> otherwise + * writes out <tag>value</tag>. + */ + public void writeStringValue (final ContentValues cv, final String key, + final int tag) throws IOException { + final String value = cv.getAsString(key); + if (!TextUtils.isEmpty(value)) { data(tag, value); } else { tag(tag); diff --git a/src/com/android/exchange/adapter/Tags.java b/src/com/android/exchange/adapter/Tags.java index dffa079e..f93f78f0 100644 --- a/src/com/android/exchange/adapter/Tags.java +++ b/src/com/android/exchange/adapter/Tags.java @@ -59,6 +59,7 @@ public class Tags { // Shift applied to page numbers to generate tag public static final int PAGE_SHIFT = 6; public static final int PAGE_MASK = 0x3F; // 6 bits + public static final int TAG_BASE = 5; // AirSync code page 0 public static final int SYNC_PAGE = 0 << PAGE_SHIFT; @@ -729,7 +730,24 @@ public class Tags { public static final int RIGHTS_CONTENT_OWNER = RIGHTS_PAGE + 0x17; public static final int RIGHTS_REMOVE_RM_DISTRIBUTION = RIGHTS_PAGE + 0x18; - static public String[][] pages = { + public static boolean isValidPage(final int page) { + return page >= 0 && page < mPages.length; + } + + public static boolean isValidTag(final int page, final int tag) { + final int tagIndex = tag - TAG_BASE; + return isValidPage(page) && tagIndex >= 0 && tagIndex < mPages[page].length; + } + + public static boolean isGlobalTag(final int tag) { + return tag >= 0 && tag < TAG_BASE; + } + + public static String getTagName(final int page, final int tag) { + return mPages[page][tag - TAG_BASE]; + } + + static final String[][] mPages = { { // 0x00 AirSync "Sync", "Responses", "Add", "Change", "Delete", "Fetch", "SyncKey", "ClientId", "ServerId", "Status", "Collection", "Class", "Version", "CollectionId", "GetChanges", diff --git a/src/com/android/exchange/eas/EasOutboxSync.java b/src/com/android/exchange/eas/EasOutboxSync.java index d93dae1c..ba259712 100644 --- a/src/com/android/exchange/eas/EasOutboxSync.java +++ b/src/com/android/exchange/eas/EasOutboxSync.java @@ -514,9 +514,9 @@ public class EasOutboxSync extends EasOperation { s.start(Tags.COMPOSE_MIME); // Send opaque data from the file stream if (withData) { - s.opaque(mFileStream, (int)mFileLength); + s.opaque(mFileStream, (int) mFileLength); } else { - s.opaqueWithoutData((int)mFileLength); + s.writeOpaqueHeader((int) mFileLength); } // And we're done s.end().end().done(); diff --git a/tests/src/com/android/exchange/TagsTests.java b/tests/src/com/android/exchange/TagsTests.java deleted file mode 100644 index 55b27c0d..00000000 --- a/tests/src/com/android/exchange/TagsTests.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.exchange; - -import com.android.exchange.adapter.Tags; - -import android.test.AndroidTestCase; -import android.test.suitebuilder.annotation.SmallTest; - -import java.util.HashMap; -@SmallTest -public class TagsTests extends AndroidTestCase { - - // Make sure there are no duplicates in the tags table - // This test is no longer required - tags can be duplicated - public void disable_testNoDuplicates() { - String[][] allTags = Tags.pages; - HashMap<String, Boolean> map = new HashMap<String, Boolean>(); - for (String[] page: allTags) { - for (String tag: page) { - assertTrue(tag, !map.containsKey(tag)); - map.put(tag, true); - } - } - } -} diff --git a/tests/src/com/android/exchange/adapter/FolderSyncParserTests.java b/tests/src/com/android/exchange/adapter/FolderSyncParserTests.java index 53fdc526..3eb59e7d 100644 --- a/tests/src/com/android/exchange/adapter/FolderSyncParserTests.java +++ b/tests/src/com/android/exchange/adapter/FolderSyncParserTests.java @@ -170,7 +170,7 @@ public class FolderSyncParserTests extends SyncAdapterTestCase<EmailSyncAdapter> private void initTagMap() { mTagMap = new HashMap<String, Integer>(); int pageNum = 0; - for (String[] page: Tags.pages) { + for (String[] page: Tags.mPages) { int tagNum = 5; for (String tag: page) { if (mTagMap.containsKey(tag)) { diff --git a/tests/src/com/android/exchange/adapter/ParserTest.java b/tests/src/com/android/exchange/adapter/ParserTest.java index b6436233..8b36433d 100644 --- a/tests/src/com/android/exchange/adapter/ParserTest.java +++ b/tests/src/com/android/exchange/adapter/ParserTest.java @@ -109,17 +109,6 @@ public class ParserTest extends AndroidTestCase { } @SmallTest - public void testParser() throws Exception { - // Test parser with sample valid data - final String wbxmlDataStr = - "03 01 6A 00 45 5C 4F 50 03 43 6F 6E 74 61 63 74 73 00 01 4B 03 32 00 01 52 03 32 00 01 4E 03 " + - "31 00 01 56 47 4D 03 32 3A 31 00 01 5D 00 11 4A 46 03 31 00 01 4C 03 30 00 01 4D 03 31 00 01 " + - "01 00 01 5E 03 46 75 6E 6B 2C 20 44 6F 6E 00 01 5F 03 44 6F 6E 00 01 69 03 46 75 6E 6B 00 01 " + - "00 11 56 03 31 00 01 01 01 01 01 01 01"; - testParserHelper(wbxmlDataStr); - } - - @SmallTest public void testUnsupportedWbxmlTag() throws Exception { // Test parser with unsupported Wbxml tag (EXT_2 = 0xC2) final String unsupportedWbxmlTag = "03 01 6A 00 45 5F C2 05 11 22 33 44 00 01 01"; @@ -229,6 +218,17 @@ public class ParserTest extends AndroidTestCase { } @SmallTest + public void testRunOnInteger() throws Exception { + final String runOnIntegerEncoding = "03 01 6A 00 45 4D C3 81 82 83 84 85 06 11 22 33 01 01"; + try { + testParserHelper(runOnIntegerEncoding); + fail("Expected EasParserException for improperly encoded integer"); + } catch (Parser.EasParserException e) { + // expected + } + } + + @SmallTest public void testAttributeTag() throws Exception { // Test parser with known tag with attributes final String tagWithAttributes = "03 01 6A 00 45 DF 06 01 03 31 00 01 01"; diff --git a/tests/src/com/android/exchange/adapter/SerializerTests.java b/tests/src/com/android/exchange/adapter/SerializerTests.java index 921c2261..75132dc9 100644 --- a/tests/src/com/android/exchange/adapter/SerializerTests.java +++ b/tests/src/com/android/exchange/adapter/SerializerTests.java @@ -22,7 +22,10 @@ import android.test.MoreAsserts; import android.test.suitebuilder.annotation.SmallTest; import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; /** You can run this entire test case with: * runtest -c com.android.exchange.adapter.SerializerTests exchange @@ -93,4 +96,12 @@ public class SerializerTests extends AndroidTestCase { // Make sure we get what's expected MoreAsserts.assertEquals("Serializer mismatch", bytes, expectedBytes); } + + @SmallTest + public void testWriteInteger() throws IOException { + OutputStream output = new ByteArrayOutputStream(); + Serializer.writeInteger(output, 384); + Serializer.writeInteger(output, 0); + Serializer.writeInteger(output, -1); + } } |