summaryrefslogtreecommitdiff
path: root/android/bluetooth/client/map/BluetoothMapBmessageParser.java
diff options
context:
space:
mode:
Diffstat (limited to 'android/bluetooth/client/map/BluetoothMapBmessageParser.java')
-rw-r--r--android/bluetooth/client/map/BluetoothMapBmessageParser.java459
1 files changed, 0 insertions, 459 deletions
diff --git a/android/bluetooth/client/map/BluetoothMapBmessageParser.java b/android/bluetooth/client/map/BluetoothMapBmessageParser.java
deleted file mode 100644
index ea9bc7f8..00000000
--- a/android/bluetooth/client/map/BluetoothMapBmessageParser.java
+++ /dev/null
@@ -1,459 +0,0 @@
-/*
- * Copyright (C) 2014 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 android.bluetooth.client.map;
-
-import android.util.Log;
-
-import com.android.vcard.VCardEntry;
-import com.android.vcard.VCardEntryConstructor;
-import com.android.vcard.VCardEntryHandler;
-import com.android.vcard.VCardParser;
-import com.android.vcard.VCardParser_V21;
-import com.android.vcard.VCardParser_V30;
-import com.android.vcard.exception.VCardException;
-import com.android.vcard.exception.VCardVersionException;
-import android.bluetooth.client.map.BluetoothMapBmessage.Status;
-import android.bluetooth.client.map.BluetoothMapBmessage.Type;
-import android.bluetooth.client.map.utils.BmsgTokenizer;
-import android.bluetooth.client.map.utils.BmsgTokenizer.Property;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.text.ParseException;
-
-class BluetoothMapBmessageParser {
-
- private final static String TAG = "BluetoothMapBmessageParser";
- private final static boolean DBG = false;
-
- private final static String CRLF = "\r\n";
-
- private final static Property BEGIN_BMSG = new Property("BEGIN", "BMSG");
- private final static Property END_BMSG = new Property("END", "BMSG");
-
- private final static Property BEGIN_VCARD = new Property("BEGIN", "VCARD");
- private final static Property END_VCARD = new Property("END", "VCARD");
-
- private final static Property BEGIN_BENV = new Property("BEGIN", "BENV");
- private final static Property END_BENV = new Property("END", "BENV");
-
- private final static Property BEGIN_BBODY = new Property("BEGIN", "BBODY");
- private final static Property END_BBODY = new Property("END", "BBODY");
-
- private final static Property BEGIN_MSG = new Property("BEGIN", "MSG");
- private final static Property END_MSG = new Property("END", "MSG");
-
- private final static int CRLF_LEN = 2;
-
- /*
- * length of "container" for 'message' in bmessage-body-content:
- * BEGIN:MSG<CRLF> + <CRLF> + END:MSG<CRFL>
- */
- private final static int MSG_CONTAINER_LEN = 22;
-
- private BmsgTokenizer mParser;
-
- private final BluetoothMapBmessage mBmsg;
-
- private BluetoothMapBmessageParser() {
- mBmsg = new BluetoothMapBmessage();
- }
-
- static public BluetoothMapBmessage createBmessage(String str) {
- BluetoothMapBmessageParser p = new BluetoothMapBmessageParser();
-
- if (DBG) {
- Log.d(TAG, "actual wired contents: " + str);
- }
-
- try {
- p.parse(str);
- } catch (IOException e) {
- Log.e(TAG, "I/O exception when parsing bMessage", e);
- return null;
- } catch (ParseException e) {
- Log.e(TAG, "Cannot parse bMessage", e);
- return null;
- }
-
- return p.mBmsg;
- }
-
- private ParseException expected(Property... props) {
- boolean first = true;
- StringBuilder sb = new StringBuilder();
-
- for (Property prop : props) {
- if (!first) {
- sb.append(" or ");
- }
- sb.append(prop);
- first = false;
- }
-
- return new ParseException("Expected: " + sb.toString(), mParser.pos());
- }
-
- private void parse(String str) throws IOException, ParseException {
-
- Property prop;
-
- /*
- * <bmessage-object>::= { "BEGIN:BMSG" <CRLF> <bmessage-property>
- * [<bmessage-originator>]* <bmessage-envelope> "END:BMSG" <CRLF> }
- */
-
- mParser = new BmsgTokenizer(str + CRLF);
-
- prop = mParser.next();
- if (!prop.equals(BEGIN_BMSG)) {
- throw expected(BEGIN_BMSG);
- }
-
- prop = parseProperties();
-
- while (prop.equals(BEGIN_VCARD)) {
-
- /* <bmessage-originator>::= <vcard> <CRLF> */
-
- StringBuilder vcard = new StringBuilder();
- prop = extractVcard(vcard);
-
- VCardEntry entry = parseVcard(vcard.toString());
- mBmsg.mOriginators.add(entry);
- }
-
- if (!prop.equals(BEGIN_BENV)) {
- throw expected(BEGIN_BENV);
- }
-
- prop = parseEnvelope(1);
-
- if (!prop.equals(END_BMSG)) {
- throw expected(END_BENV);
- }
-
- /*
- * there should be no meaningful data left in stream here so we just
- * ignore whatever is left
- */
-
- mParser = null;
- }
-
- private Property parseProperties() throws ParseException {
-
- Property prop;
-
- /*
- * <bmessage-property>::=<bmessage-version-property>
- * <bmessage-readstatus-property> <bmessage-type-property>
- * <bmessage-folder-property> <bmessage-version-property>::="VERSION:"
- * <common-digit>*"."<common-digit>* <CRLF>
- * <bmessage-readstatus-property>::="STATUS:" 'readstatus' <CRLF>
- * <bmessage-type-property>::="TYPE:" 'type' <CRLF>
- * <bmessage-folder-property>::="FOLDER:" 'foldername' <CRLF>
- */
-
- do {
- prop = mParser.next();
-
- if (prop.name.equals("VERSION")) {
- mBmsg.mBmsgVersion = prop.value;
-
- } else if (prop.name.equals("STATUS")) {
- for (Status s : Status.values()) {
- if (prop.value.equals(s.toString())) {
- mBmsg.mBmsgStatus = s;
- break;
- }
- }
-
- } else if (prop.name.equals("TYPE")) {
- for (Type t : Type.values()) {
- if (prop.value.equals(t.toString())) {
- mBmsg.mBmsgType = t;
- break;
- }
- }
-
- } else if (prop.name.equals("FOLDER")) {
- mBmsg.mBmsgFolder = prop.value;
-
- }
-
- } while (!prop.equals(BEGIN_VCARD) && !prop.equals(BEGIN_BENV));
-
- return prop;
- }
-
- private Property parseEnvelope(int level) throws IOException, ParseException {
-
- Property prop;
-
- /*
- * we can support as many nesting level as we want, but MAP spec clearly
- * defines that there should be no more than 3 levels. so we verify it
- * here.
- */
-
- if (level > 3) {
- throw new ParseException("bEnvelope is nested more than 3 times", mParser.pos());
- }
-
- /*
- * <bmessage-envelope> ::= { "BEGIN:BENV" <CRLF> [<bmessage-recipient>]*
- * <bmessage-envelope> | <bmessage-content> "END:BENV" <CRLF> }
- */
-
- prop = mParser.next();
-
- while (prop.equals(BEGIN_VCARD)) {
-
- /* <bmessage-originator>::= <vcard> <CRLF> */
-
- StringBuilder vcard = new StringBuilder();
- prop = extractVcard(vcard);
-
- if (level == 1) {
- VCardEntry entry = parseVcard(vcard.toString());
- mBmsg.mRecipients.add(entry);
- }
- }
-
- if (prop.equals(BEGIN_BENV)) {
- prop = parseEnvelope(level + 1);
-
- } else if (prop.equals(BEGIN_BBODY)) {
- prop = parseBody();
-
- } else {
- throw expected(BEGIN_BENV, BEGIN_BBODY);
- }
-
- if (!prop.equals(END_BENV)) {
- throw expected(END_BENV);
- }
-
- return mParser.next();
- }
-
- private Property parseBody() throws IOException, ParseException {
-
- Property prop;
-
- /*
- * <bmessage-content>::= { "BEGIN:BBODY"<CRLF> [<bmessage-body-part-ID>
- * <CRLF>] <bmessage-body-property> <bmessage-body-content>* <CRLF>
- * "END:BBODY"<CRLF> } <bmessage-body-part-ID>::="PARTID:" 'Part-ID'
- * <bmessage-body-property>::=[<bmessage-body-encoding-property>]
- * [<bmessage-body-charset-property>]
- * [<bmessage-body-language-property>]
- * <bmessage-body-content-length-property>
- * <bmessage-body-encoding-property>::="ENCODING:"'encoding' <CRLF>
- * <bmessage-body-charset-property>::="CHARSET:"'charset' <CRLF>
- * <bmessage-body-language-property>::="LANGUAGE:"'language' <CRLF>
- * <bmessage-body-content-length-property>::= "LENGTH:" <common-digit>*
- * <CRLF>
- */
-
- do {
- prop = mParser.next();
-
- if (prop.name.equals("PARTID")) {
- } else if (prop.name.equals("ENCODING")) {
- mBmsg.mBbodyEncoding = prop.value;
-
- } else if (prop.name.equals("CHARSET")) {
- mBmsg.mBbodyCharset = prop.value;
-
- } else if (prop.name.equals("LANGUAGE")) {
- mBmsg.mBbodyLanguage = prop.value;
-
- } else if (prop.name.equals("LENGTH")) {
- try {
- mBmsg.mBbodyLength = Integer.parseInt(prop.value);
- } catch (NumberFormatException e) {
- throw new ParseException("Invalid LENGTH value", mParser.pos());
- }
-
- }
-
- } while (!prop.equals(BEGIN_MSG));
-
- /*
- * check that the charset is always set to UTF-8. We expect only text transfer (in lieu with
- * the MAPv12 specifying only RFC2822 (text only) for MMS/EMAIL and SMS do not support
- * non-text content. If the charset is not set to UTF-8, it is safe to set the message as
- * empty. We force the getMessage (see BluetoothMasClient) to only call getMessage with
- * UTF-8 as the MCE is not obliged to support native charset.
- */
- if (!mBmsg.mBbodyCharset.equals("UTF-8")) {
- Log.e(TAG, "The charset was not set to charset UTF-8: " + mBmsg.mBbodyCharset);
- }
-
- /*
- * <bmessage-body-content>::={ "BEGIN:MSG"<CRLF> 'message'<CRLF>
- * "END:MSG"<CRLF> }
- */
-
- int messageLen = mBmsg.mBbodyLength - MSG_CONTAINER_LEN;
- int offset = messageLen + CRLF_LEN;
- int restartPos = mParser.pos() + offset;
-
- /*
- * length is specified in bytes so we need to convert from unicode
- * string back to bytes array
- */
-
- String remng = mParser.remaining();
- byte[] data = remng.getBytes();
-
- /* restart parsing from after 'message'<CRLF> */
- mParser = new BmsgTokenizer(new String(data, offset, data.length - offset), restartPos);
-
- prop = mParser.next(true);
-
- if (prop != null) {
- if (prop.equals(END_MSG)) {
- if (mBmsg.mBbodyCharset.equals("UTF-8")) {
- mBmsg.mMessage = new String(data, 0, messageLen, StandardCharsets.UTF_8);
- } else {
- mBmsg.mMessage = null;
- }
- } else {
- /* Handle possible exception for incorrect LENGTH value
- * from MSE while parsing GET Message response */
- Log.e(TAG, "Prop Invalid: "+ prop.toString());
- Log.e(TAG, "Possible Invalid LENGTH value");
- throw expected(END_MSG);
- }
- } else {
-
- data = null;
-
- /*
- * now we check if bMessage can be parsed if LENGTH is handled as
- * number of characters instead of number of bytes
- */
- if (offset < 0 || offset > remng.length()) {
- /* Handle possible exception for incorrect LENGTH value
- * from MSE while parsing GET Message response */
- throw new ParseException("Invalid LENGTH value", mParser.pos());
- }
-
- Log.w(TAG, "byte LENGTH seems to be invalid, trying with char length");
-
- mParser = new BmsgTokenizer(remng.substring(offset));
-
- prop = mParser.next();
-
- if (!prop.equals(END_MSG)) {
- throw expected(END_MSG);
- }
-
- if (mBmsg.mBbodyCharset.equals("UTF-8")) {
- mBmsg.mMessage = remng.substring(0, messageLen);
- } else {
- mBmsg.mMessage = null;
- }
- }
-
- prop = mParser.next();
-
- if (!prop.equals(END_BBODY)) {
- throw expected(END_BBODY);
- }
-
- return mParser.next();
- }
-
- private Property extractVcard(StringBuilder out) throws IOException, ParseException {
- Property prop;
-
- out.append(BEGIN_VCARD).append(CRLF);
-
- do {
- prop = mParser.next();
- out.append(prop).append(CRLF);
- } while (!prop.equals(END_VCARD));
-
- return mParser.next();
- }
-
- private class VcardHandler implements VCardEntryHandler {
-
- VCardEntry vcard;
-
- @Override
- public void onStart() {
- }
-
- @Override
- public void onEntryCreated(VCardEntry entry) {
- vcard = entry;
- }
-
- @Override
- public void onEnd() {
- }
- };
-
- private VCardEntry parseVcard(String str) throws IOException, ParseException {
- VCardEntry vcard = null;
-
- try {
- VCardParser p = new VCardParser_V21();
- VCardEntryConstructor c = new VCardEntryConstructor();
- VcardHandler handler = new VcardHandler();
- c.addEntryHandler(handler);
- p.addInterpreter(c);
- p.parse(new ByteArrayInputStream(str.getBytes()));
-
- vcard = handler.vcard;
-
- } catch (VCardVersionException e1) {
-
- try {
- VCardParser p = new VCardParser_V30();
- VCardEntryConstructor c = new VCardEntryConstructor();
- VcardHandler handler = new VcardHandler();
- c.addEntryHandler(handler);
- p.addInterpreter(c);
- p.parse(new ByteArrayInputStream(str.getBytes()));
-
- vcard = handler.vcard;
-
- } catch (VCardVersionException e2) {
- // will throw below
- } catch (VCardException e2) {
- // will throw below
- }
-
- } catch (VCardException e1) {
- // will throw below
- }
-
- if (vcard == null) {
- throw new ParseException("Cannot parse vCard object (neither 2.1 nor 3.0?)",
- mParser.pos());
- }
-
- return vcard;
- }
-}