From 3d3db421d3f327a2a30bb75d7144f1835b626444 Mon Sep 17 00:00:00 2001 From: Moxie Marlinspike <moxie@thoughtcrime.org> Date: Sun, 9 Sep 2012 16:10:46 -0700 Subject: [PATCH] Lint warning changes. --- AndroidManifest.xml | 48 +++--- res/layout/change_passphrase_activity.xml | 125 +++++++++------ res/layout/conversation_activity.xml | 2 +- res/layout/conversation_fragment_cab.xml | 1 - res/layout/create_passphrase_activity.xml | 4 +- res/layout/save_identity_activity.xml | 90 ++++++----- .../verify_imported_identity_activity.xml | 2 +- res/layout/view_identity_activity.xml | 2 +- .../contacts/ContactAccessorNewApi.java | 2 +- .../database/CanonicalAddressDatabase.java | 2 +- .../securesms/database/SmsDatabase.java | 148 +++++++++--------- .../securesms/database/ThreadDatabase.java | 130 +++++++-------- .../sms/MultipartMessageHandler.java | 119 +++++++------- 13 files changed, 355 insertions(+), 320 deletions(-) diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 461d52b161..50b000bdd2 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -6,6 +6,28 @@ <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="14"/> + <permission android:name="org.thoughtcrime.securesms.ACCESS_SECRETS" + android:label="Access to TextSecure Secrets" + android:protectionLevel="signature" /> + + <uses-permission android:name="org.thoughtcrime.securesms.ACCESS_SECRETS"></uses-permission> + <uses-permission android:name="android.permission.BROADCAST_WAP_PUSH"></uses-permission> + <uses-permission android:name="android.permission.READ_CONTACTS"></uses-permission> + <uses-permission android:name="android.permission.WRITE_CONTACTS"></uses-permission> + <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> + <uses-permission android:name="android.permission.RECEIVE_SMS"></uses-permission> + <uses-permission android:name="android.permission.RECEIVE_MMS"></uses-permission> + <uses-permission android:name="android.permission.READ_SMS"></uses-permission> + <uses-permission android:name="android.permission.SEND_SMS"></uses-permission> + <uses-permission android:name="android.permission.WRITE_SMS"></uses-permission> + <uses-permission android:name="android.permission.VIBRATE"></uses-permission> + <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> + <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" /> + <uses-permission android:name="android.permission.READ_PHONE_STATE" /> + <uses-permission android:name="android.permission.WAKE_LOCK" /> + <uses-permission android:name="android.permission.INTERNET" /> + <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> + <application android:icon="@drawable/icon" android:label="@string/app_name" android:theme="@style/Theme.Sherlock.Light.DarkActionBar"> @@ -131,34 +153,12 @@ </intent-filter> </receiver> - <provider android:name=".providers.PartProvider" android:authorities="org.thoughtcrime.provider.securesms" /> + <provider android:name=".providers.PartProvider" + android:authorities="org.thoughtcrime.provider.securesms" /> <uses-library android:name="android.test.runner" /> </application> -<permission android:name="org.thoughtcrime.securesms.ACCESS_SECRETS" - android:label="Access to TextSecure Secrets" - android:protectionLevel="signature" /> - -<uses-permission android:name="org.thoughtcrime.securesms.ACCESS_SECRETS"></uses-permission> -<uses-permission android:name="android.permission.BROADCAST_WAP_PUSH"></uses-permission> -<uses-permission android:name="android.permission.READ_CONTACTS"></uses-permission> -<uses-permission android:name="android.permission.WRITE_CONTACTS"></uses-permission> -<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> -<uses-permission android:name="android.permission.RECEIVE_SMS"></uses-permission> -<uses-permission android:name="android.permission.RECEIVE_MMS"></uses-permission> -<uses-permission android:name="android.permission.READ_SMS"></uses-permission> -<uses-permission android:name="android.permission.SEND_SMS"></uses-permission> -<uses-permission android:name="android.permission.WRITE_SMS"></uses-permission> -<uses-permission android:name="android.permission.VIBRATE"></uses-permission> -<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> -<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" /> -<uses-permission android:name="android.permission.READ_PHONE_STATE" /> -<uses-permission android:name="android.permission.WAKE_LOCK" /> -<uses-permission android:name="android.permission.INTERNET" /> -<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> - - <instrumentation android:name="android.test.InstrumentationTestRunner" android:targetPackage="org.thoughtcrime.securesms.tests" android:label="Tests for My App" /> diff --git a/res/layout/change_passphrase_activity.xml b/res/layout/change_passphrase_activity.xml index b2c445eda4..7a1752148c 100644 --- a/res/layout/change_passphrase_activity.xml +++ b/res/layout/change_passphrase_activity.xml @@ -1,63 +1,90 @@ <?xml version="1.0" encoding="utf-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="fill_parent" - android:layout_height="fill_parent"> -<TableLayout + xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" - android:layout_height="fill_parent" - android:stretchColumns="1"> + android:layout_height="fill_parent" > + + <LinearLayout + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:layout_marginLeft="16dip" + android:layout_marginRight="16dip" + android:orientation="vertical" > - <TableRow> <TextView - android:textSize="12sp" + android:padding="3dip" android:text="@string/old_passphrase" - android:padding="3dip" /> + android:textAppearance="?android:attr/textAppearanceMedium" + android:layout_width="fill_parent" + android:layout_height="wrap_content"/> - <EditText android:id="@+id/old_passphrase" - android:layout_height="wrap_content" - android:layout_width="fill_parent" - android:password="true"/> - </TableRow> + <EditText + android:id="@+id/old_passphrase" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:inputType="textPassword" + android:layout_marginBottom="5dip" /> - <TableRow> <TextView + android:padding="3dip" android:text="@string/new_passphrase" - android:textSize="12sp" - android:padding="3dip" /> + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:textAppearance="?android:attr/textAppearanceMedium" /> - <EditText android:id="@+id/new_passphrase" - android:layout_height="wrap_content" - android:layout_width="fill_parent" - android:password="true" - /> - </TableRow> + <EditText + android:id="@+id/new_passphrase" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:inputType="textPassword" + android:layout_marginBottom="5dip" /> - <TableRow> <TextView + android:padding="3dip" + android:layout_width="fill_parent" + android:layout_height="wrap_content" android:text="@string/repeat_new_passphrase" - android:textSize="12sp" - android:padding="3dip" /> - - <EditText android:id="@+id/repeat_passphrase" - android:layout_height="wrap_content" - android:layout_width="fill_parent" - android:password="true" - /> - </TableRow> - - - <TableRow> - <Button android:id="@+id/cancel_button" - android:padding="10dip" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/cancel"/> - - <Button android:id="@+id/ok_button" - android:padding="10dip" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@android:string/ok"/> - </TableRow> - </TableLayout> -</ScrollView> + android:textAppearance="?android:attr/textAppearanceMedium" /> + + <EditText + android:id="@+id/repeat_passphrase" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:inputType="textPassword" + android:layout_marginBottom="5dip" /> + + <LinearLayout + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:layout_marginBottom="16dip" + android:gravity="right" + android:orientation="horizontal" > + + <TableLayout + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:stretchColumns="*" + tools:ignore="UselessParent" > + + <TableRow> + + <Button + android:id="@+id/cancel_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginLeft="16dip" + android:layout_marginRight="15dip" + android:text="@string/cancel" /> + + <Button + android:id="@+id/ok_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginRight="16dip" + android:text="@android:string/ok" /> + </TableRow> + </TableLayout> + </LinearLayout> + </LinearLayout> + +</ScrollView> \ No newline at end of file diff --git a/res/layout/conversation_activity.xml b/res/layout/conversation_activity.xml index 9bb5670dd2..79bf1a01e7 100644 --- a/res/layout/conversation_activity.xml +++ b/res/layout/conversation_activity.xml @@ -35,7 +35,7 @@ <LinearLayout android:layout_width="fill_parent" - android:layout_height="fill_parent" + android:layout_height="wrap_content" android:orientation="vertical" android:paddingBottom="5dip" android:background="#fff"> diff --git a/res/layout/conversation_fragment_cab.xml b/res/layout/conversation_fragment_cab.xml index 7b2eefb028..e98d55d57b 100644 --- a/res/layout/conversation_fragment_cab.xml +++ b/res/layout/conversation_fragment_cab.xml @@ -12,7 +12,6 @@ android:maxLines="1" android:singleLine="true" android:layout_gravity="center_vertical" - android:layout_centerVertical="true" android:textAppearance="?android:attr/textAppearanceMediumInverse" android:layout_weight="1" android:layout_width="wrap_content" diff --git a/res/layout/create_passphrase_activity.xml b/res/layout/create_passphrase_activity.xml index 9cf111e7dd..0d9e041534 100644 --- a/res/layout/create_passphrase_activity.xml +++ b/res/layout/create_passphrase_activity.xml @@ -28,7 +28,7 @@ <EditText android:id="@+id/passphrase_edit" android:layout_height="wrap_content" android:layout_width="fill_parent" - android:password="true"/> + android:inputType="textPassword"/> <TextView android:layout_width="fill_parent" @@ -42,7 +42,7 @@ <EditText android:layout_height="wrap_content" android:layout_width="fill_parent" - android:password="true" + android:inputType="textPassword" android:id="@+id/passphrase_edit_repeat"/> <LinearLayout android:layout_width="fill_parent" diff --git a/res/layout/save_identity_activity.xml b/res/layout/save_identity_activity.xml index 3d2dd745fd..30bdd34df0 100644 --- a/res/layout/save_identity_activity.xml +++ b/res/layout/save_identity_activity.xml @@ -1,46 +1,58 @@ <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:orientation="vertical"> - - <TextView android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:layout_marginLeft="16dip" - android:layout_marginRight="16dip" - android:layout_marginTop="5dip" - android:layout_marginBottom="5dip" - android:textAppearance="?android:attr/textAppearanceMedium" - android:text="@string/identity_name" /> - - <EditText android:layout_height="wrap_content" - android:layout_width="fill_parent" - android:id="@+id/identity_name" - android:layout_margin="16dip"/> - - <LinearLayout android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:orientation="horizontal" - android:layout_marginBottom="16dip" - android:gravity="right"> - - <TableLayout android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:stretchColumns="*"> + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:orientation="vertical" > + + <TextView + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:layout_marginBottom="5dip" + android:layout_marginLeft="16dip" + android:layout_marginRight="16dip" + android:layout_marginTop="5dip" + android:text="@string/identity_name" + android:textAppearance="?android:attr/textAppearanceMedium" /> + + <EditText + android:id="@+id/identity_name" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:layout_margin="16dip" + tools:ignore="TextFields" /> + + <LinearLayout + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:layout_marginBottom="16dip" + android:gravity="right" + android:orientation="horizontal" > + + <TableLayout + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:stretchColumns="*" + tools:ignore="UselessParent" > + <TableRow> - <Button android:layout_height="wrap_content" - android:layout_width="wrap_content" - android:text="@string/cancel" - android:id="@+id/cancel_button" - android:layout_marginRight="15dip" - android:layout_marginLeft="16dip"/> - - <Button android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@android:string/ok" - android:id="@+id/ok_button" - android:layout_marginRight="16dip"/> + + <Button + android:id="@+id/cancel_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginLeft="16dip" + android:layout_marginRight="15dip" + android:text="@string/cancel" /> + + <Button + android:id="@+id/ok_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginRight="16dip" + android:text="@android:string/ok" /> </TableRow> </TableLayout> </LinearLayout> + </LinearLayout> \ No newline at end of file diff --git a/res/layout/verify_imported_identity_activity.xml b/res/layout/verify_imported_identity_activity.xml index 6ab1bb34f7..b5b049dc0c 100644 --- a/res/layout/verify_imported_identity_activity.xml +++ b/res/layout/verify_imported_identity_activity.xml @@ -4,7 +4,7 @@ android:layout_height="fill_parent"> <TableLayout android:layout_width="fill_parent" - android:layout_height="fill_parent" + android:layout_height="wrap_content" android:shrinkColumns="1"> <TableRow> diff --git a/res/layout/view_identity_activity.xml b/res/layout/view_identity_activity.xml index 2780258b98..99289642ce 100644 --- a/res/layout/view_identity_activity.xml +++ b/res/layout/view_identity_activity.xml @@ -6,7 +6,7 @@ android:layout_marginRight="16dip"> <TableLayout android:layout_width="fill_parent" - android:layout_height="fill_parent" + android:layout_height="wrap_content" android:shrinkColumns="1"> <TableRow> diff --git a/src/org/thoughtcrime/securesms/contacts/ContactAccessorNewApi.java b/src/org/thoughtcrime/securesms/contacts/ContactAccessorNewApi.java index a8a36e3ab4..7aa331c07f 100644 --- a/src/org/thoughtcrime/securesms/contacts/ContactAccessorNewApi.java +++ b/src/org/thoughtcrime/securesms/contacts/ContactAccessorNewApi.java @@ -185,7 +185,7 @@ public class ContactAccessorNewApi extends ContactAccessor { return rawContactIds; while (cursor.moveToNext()) { - rawContactIds.add(new Long(cursor.getLong(0))); + rawContactIds.add(Long.valueOf(cursor.getLong(0))); } } finally { if (cursor != null) diff --git a/src/org/thoughtcrime/securesms/database/CanonicalAddressDatabase.java b/src/org/thoughtcrime/securesms/database/CanonicalAddressDatabase.java index 2df4542246..8293079287 100644 --- a/src/org/thoughtcrime/securesms/database/CanonicalAddressDatabase.java +++ b/src/org/thoughtcrime/securesms/database/CanonicalAddressDatabase.java @@ -119,7 +119,7 @@ public class CanonicalAddressDatabase { private long getCanonicalAddressFromCache(String address) { if (addressCache.containsKey(address)) - return new Long(addressCache.get(address)); + return Long.valueOf(addressCache.get(address)); return -1L; } diff --git a/src/org/thoughtcrime/securesms/database/SmsDatabase.java b/src/org/thoughtcrime/securesms/database/SmsDatabase.java index ca1d40f73f..2570cf25aa 100644 --- a/src/org/thoughtcrime/securesms/database/SmsDatabase.java +++ b/src/org/thoughtcrime/securesms/database/SmsDatabase.java @@ -1,6 +1,6 @@ -/** +/** * Copyright (C) 2011 Whisper Systems - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -10,19 +10,12 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.thoughtcrime.securesms.database; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; - -import org.thoughtcrime.securesms.recipients.Recipient; -import org.thoughtcrime.securesms.recipients.Recipients; - import android.content.ContentValues; import android.content.Context; import android.database.Cursor; @@ -32,15 +25,22 @@ import android.database.sqlite.SQLiteStatement; import android.telephony.SmsMessage; import android.util.Log; +import org.thoughtcrime.securesms.recipients.Recipient; +import org.thoughtcrime.securesms.recipients.Recipients; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + /** * Database for storage of SMS messages. - * + * * @author Moxie Marlinspike */ public class SmsDatabase extends Database { public static final String TRANSPORT = "transport_type"; - + public static final String TABLE_NAME = "sms"; public static final String ID = "_id"; public static final String THREAD_ID = "thread_id"; @@ -55,65 +55,65 @@ public class SmsDatabase extends Database { public static final String SUBJECT = "subject"; public static final String BODY = "body"; public static final String SERVICE_CENTER = "service_center"; - - public static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + " (" + ID + " integer PRIMARY KEY, " + - THREAD_ID + " INTEGER, " + ADDRESS + " TEXT, " + PERSON + " INTEGER, " + DATE + " INTEGER, " + - PROTOCOL + " INTEGER, " + READ + " INTEGER DEFAULT 0, " + STATUS + " INTEGER DEFAULT -1," + - TYPE + " INTEGER, " + REPLY_PATH_PRESENT + " INTEGER, " + SUBJECT + " TEXT, " + BODY + " TEXT, " + + + public static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + " (" + ID + " integer PRIMARY KEY, " + + THREAD_ID + " INTEGER, " + ADDRESS + " TEXT, " + PERSON + " INTEGER, " + DATE + " INTEGER, " + + PROTOCOL + " INTEGER, " + READ + " INTEGER DEFAULT 0, " + STATUS + " INTEGER DEFAULT -1," + + TYPE + " INTEGER, " + REPLY_PATH_PRESENT + " INTEGER, " + SUBJECT + " TEXT, " + BODY + " TEXT, " + SERVICE_CENTER + " TEXT);"; - + public SmsDatabase(Context context, SQLiteOpenHelper databaseHelper) { super(context, databaseHelper); } - + private void updateType(long id, long type) { Log.w("MessageDatabase", "Updating ID: " + id + " to type: " + type); ContentValues contentValues = new ContentValues(); contentValues.put(TYPE, type); - + SQLiteDatabase db = databaseHelper.getWritableDatabase(); db.update(TABLE_NAME, contentValues, ID_WHERE, new String[] {id+""}); notifyConversationListeners(getThreadIdForMessage(id)); } - + private long insertMessageReceived(SmsMessage message, String body, long type) { - List<Recipient> recipientList = new ArrayList<Recipient>(1); + List<Recipient> recipientList = new ArrayList<Recipient>(1); recipientList.add(new Recipient(null, message.getDisplayOriginatingAddress(), null)); Recipients recipients = new Recipients(recipientList); - + long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipients); - + ContentValues values = new ContentValues(6); values.put(ADDRESS, message.getDisplayOriginatingAddress()); - values.put(DATE, new Long(System.currentTimeMillis())); + values.put(DATE, Long.valueOf(System.currentTimeMillis())); values.put(PROTOCOL, message.getProtocolIdentifier()); values.put(READ, Integer.valueOf(0)); - + if (message.getPseudoSubject().length() > 0) values.put(SUBJECT, message.getPseudoSubject()); - + values.put(REPLY_PATH_PRESENT, message.isReplyPathPresent() ? 1 : 0); values.put(SERVICE_CENTER, message.getServiceCenterAddress()); values.put(BODY, body); values.put(TYPE, type); values.put(THREAD_ID, threadId); - + SQLiteDatabase db = databaseHelper.getWritableDatabase(); long messageId = db.insert(TABLE_NAME, null, values); - + DatabaseFactory.getThreadDatabase(context).setUnread(threadId); DatabaseFactory.getThreadDatabase(context).update(threadId); notifyConversationListeners(threadId); return messageId; } - + public long getThreadIdForMessage(long id) { String sql = "SELECT " + THREAD_ID + " FROM " + TABLE_NAME + " WHERE " + ID + " = ?"; String[] sqlArgs = new String[] {id+""}; SQLiteDatabase db = databaseHelper.getReadableDatabase(); - + Cursor cursor = null; - + try { cursor = db.rawQuery(sql, sqlArgs); if (cursor != null && cursor.moveToFirst()) @@ -125,14 +125,14 @@ public class SmsDatabase extends Database { cursor.close(); } } - + public int getMessageCountForThread(long threadId) { - SQLiteDatabase db = databaseHelper.getReadableDatabase(); + SQLiteDatabase db = databaseHelper.getReadableDatabase(); Cursor cursor = null; - + try { cursor = db.query(TABLE_NAME, new String[] {"COUNT(*)"}, THREAD_ID + " = ?", new String[] {threadId+""}, null, null, null); - + if (cursor != null && cursor.moveToFirst()) return cursor.getInt(0); } finally { @@ -142,42 +142,42 @@ public class SmsDatabase extends Database { return 0; } - + public void markAsDecryptFailed(long id) { updateType(id, Types.FAILED_DECRYPT_TYPE); } - + public void markAsNoSession(long id) { updateType(id, Types.NO_SESSION_TYPE); } - + public void markAsDecrypting(long id) { updateType(id, Types.DECRYPT_IN_PROGRESS_TYPE); } - + public void markAsSent(long id, long type) { if (type == Types.ENCRYPTING_TYPE) updateType(id, Types.SECURE_SENT_TYPE); else updateType(id, Types.SENT_TYPE); } - + public void markAsSentFailed(long id) { updateType(id, Types.FAILED_TYPE); } - + public void setMessagesRead(long threadId) { SQLiteDatabase database = databaseHelper.getWritableDatabase(); ContentValues contentValues = new ContentValues(); contentValues.put(READ, 1); - + long start = System.currentTimeMillis(); database.update(TABLE_NAME, contentValues, THREAD_ID + " = ? AND " + READ + " = 0", new String[] {threadId+""}); long end = System.currentTimeMillis(); - + Log.w("SmsDatabase", "setMessagesRead time: " + (end-start)); } - + public void updateMessageBodyAndType(long messageId, String body, long type) { ContentValues contentValues = new ContentValues(); contentValues.put(BODY, body); @@ -185,20 +185,20 @@ public class SmsDatabase extends Database { SQLiteDatabase db = databaseHelper.getWritableDatabase(); db.update(TABLE_NAME, contentValues, ID_WHERE, new String[] {messageId+""}); - + DatabaseFactory.getThreadDatabase(context).update(getThreadIdForMessage(messageId)); notifyConversationListeners(getThreadIdForMessage(messageId)); notifyConversationListListeners(); } - + public long insertSecureMessageReceived(SmsMessage message, String body) { return insertMessageReceived(message, body, Types.DECRYPT_IN_PROGRESS_TYPE); } - + public long insertMessageReceived(SmsMessage message, String body) { return insertMessageReceived(message, body, Types.INBOX_TYPE); } - + public long insertMessageSent(String address, long threadId, String body, long date, long type) { ContentValues contentValues = new ContentValues(6); // contentValues.put(ADDRESS, NumberUtil.filterNumber(address)); @@ -208,7 +208,7 @@ public class SmsDatabase extends Database { contentValues.put(DATE, date); contentValues.put(READ, 1); contentValues.put(TYPE, type); - + SQLiteDatabase db = databaseHelper.getWritableDatabase(); long messageId = db.insert(TABLE_NAME, ADDRESS, contentValues); @@ -223,25 +223,25 @@ public class SmsDatabase extends Database { SQLiteDatabase db = databaseHelper.getReadableDatabase(); return db.query(TABLE_NAME, null, outgoingSelection, null, null, null, null); } - + public Cursor getDecryptInProgressMessages() { String where = TYPE + " = " + Types.DECRYPT_IN_PROGRESS_TYPE; SQLiteDatabase db = databaseHelper.getReadableDatabase(); return db.query(TABLE_NAME, null, where, null, null, null, null); } - + public Cursor getEncryptedRogueMessages(Recipient recipient) { SQLiteDatabase db = databaseHelper.getReadableDatabase(); - String selection = TYPE + " = " + Types.NO_SESSION_TYPE + " AND PHONE_NUMBERS_EQUAL(" + ADDRESS + ", ?)"; + String selection = TYPE + " = " + Types.NO_SESSION_TYPE + " AND PHONE_NUMBERS_EQUAL(" + ADDRESS + ", ?)"; String[] args = {recipient.getNumber()}; - return db.query(TABLE_NAME, null, selection, args, null, null, null); + return db.query(TABLE_NAME, null, selection, args, null, null, null); } - + public Cursor getMessage(long messageId) { SQLiteDatabase db = databaseHelper.getReadableDatabase(); return db.query(TABLE_NAME, null, ID_WHERE, new String[] {messageId+""}, null, null, null); } - + public void deleteMessage(long messageId) { Log.w("MessageDatabase", "Deleting: " + messageId); SQLiteDatabase db = databaseHelper.getWritableDatabase(); @@ -250,31 +250,31 @@ public class SmsDatabase extends Database { DatabaseFactory.getThreadDatabase(context).update(threadId); notifyConversationListeners(threadId); } - + /*package */void deleteThread(long threadId) { SQLiteDatabase db = databaseHelper.getWritableDatabase(); db.delete(TABLE_NAME, THREAD_ID + " = ?", new String[] {threadId+""}); } - + /*package*/ void deleteThreads(Set<Long> threadIds) { SQLiteDatabase db = databaseHelper.getWritableDatabase(); String where = ""; - + for (long threadId : threadIds) { where += THREAD_ID + " = '" + threadId + "' OR "; } - + where = where.substring(0, where.length() - 4); - + db.delete(TABLE_NAME, where, null); } /*package */ void deleteAllThreads() { SQLiteDatabase db = databaseHelper.getWritableDatabase(); - db.delete(TABLE_NAME, null, null); + db.delete(TABLE_NAME, null, null); } - + /*package*/ SQLiteDatabase beginTransaction() { SQLiteDatabase database = databaseHelper.getWritableDatabase(); database.beginTransaction(); @@ -284,23 +284,23 @@ public class SmsDatabase extends Database { /*package*/ void endTransaction(SQLiteDatabase database) { database.setTransactionSuccessful(); database.endTransaction(); - } - + } + /*package*/ void insertRaw(SQLiteDatabase database, ContentValues contentValues) { database.insert(TABLE_NAME, null, contentValues); } - + /*package*/ SQLiteStatement createInsertStatement(SQLiteDatabase database) { return database.compileStatement("INSERT INTO " + TABLE_NAME + " (" + ADDRESS + ", " + PERSON + ", " + DATE + ", " + PROTOCOL + ", " + READ + ", " + STATUS + ", " + TYPE + ", " + REPLY_PATH_PRESENT + ", " + SUBJECT + ", " + BODY + ", " + SERVICE_CENTER + ", THREAD_ID) " + " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); } - + public static class Types { public static final int INBOX_TYPE = 1; public static final int SENT_TYPE = 2; public static final int SENT_PENDING = 4; public static final int FAILED_TYPE = 5; - + public static final int ENCRYPTING_TYPE = 42; // Messages are stored local encrypted and need async encryption and delivery. public static final int ENCRYPTED_OUTBOX_TYPE = 43; // Messages are stored local encrypted and need delivery. public static final int SECURE_SENT_TYPE = 44; // Messages were sent with async encryption. @@ -308,23 +308,23 @@ public class SmsDatabase extends Database { public static final int FAILED_DECRYPT_TYPE = 46; // Messages were received with async encryption and failed to decrypt. public static final int DECRYPT_IN_PROGRESS_TYPE = 47; // Messages are in the process of being asymmetricaly decrypted. public static final int NO_SESSION_TYPE = 48; // Messages were received with async encryption but there is no session yet. - + public static boolean isFailedMessageType(long type) { return type == FAILED_TYPE; } - + public static boolean isOutgoingMessageType(long type) { return type == SENT_TYPE || type == SENT_PENDING || type == ENCRYPTING_TYPE || type == ENCRYPTED_OUTBOX_TYPE || type == SECURE_SENT_TYPE || type == FAILED_TYPE; } - + public static boolean isPendingMessageType(long type) { return type == SENT_PENDING || type == ENCRYPTING_TYPE || type == ENCRYPTED_OUTBOX_TYPE; } - + public static boolean isSecureType(long type) { return type == SECURE_SENT_TYPE || type == ENCRYPTING_TYPE || type == SECURE_RECEIVED_TYPE; } - + } - + } diff --git a/src/org/thoughtcrime/securesms/database/ThreadDatabase.java b/src/org/thoughtcrime/securesms/database/ThreadDatabase.java index 26cb16888f..ed8063dcd6 100644 --- a/src/org/thoughtcrime/securesms/database/ThreadDatabase.java +++ b/src/org/thoughtcrime/securesms/database/ThreadDatabase.java @@ -1,6 +1,6 @@ -/** +/** * Copyright (C) 2011 Whisper Systems - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -10,26 +10,26 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.thoughtcrime.securesms.database; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import org.thoughtcrime.securesms.recipients.Recipient; -import org.thoughtcrime.securesms.recipients.Recipients; - import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; +import org.thoughtcrime.securesms.recipients.Recipient; +import org.thoughtcrime.securesms.recipients.Recipients; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + public class ThreadDatabase extends Database { private static final String TABLE_NAME = "thread"; @@ -48,7 +48,7 @@ public class ThreadDatabase extends Database { DATE + " INTEGER DEFAULT 0, " + MESSAGE_COUNT + " INTEGER DEFAULT 0, " + RECIPIENT_IDS + " TEXT, " + SNIPPET + " TEXT, " + SNIPPET_CHARSET + " INTEGER DEFAULT 0, " + READ + " INTEGER DEFAULT 1, " + TYPE + " INTEGER DEFAULT 0, " + ERROR + " INTEGER DEFAULT 0, " + - HAS_ATTACHMENT + " INTEGER DEFAULT 0);"; + HAS_ATTACHMENT + " INTEGER DEFAULT 0);"; public ThreadDatabase(Context context, SQLiteOpenHelper databaseHelper) { super(context, databaseHelper); @@ -62,41 +62,41 @@ public class ThreadDatabase extends Database { for (Recipient recipient : recipientList) { // String number = NumberUtil.filterNumber(recipient.getNumber()); String number = recipient.getNumber(); - recipientSet.add(new Long(DatabaseFactory.getAddressDatabase(context).getCanonicalAddress(number))); + recipientSet.add(Long.valueOf(DatabaseFactory.getAddressDatabase(context).getCanonicalAddress(number))); } - + long[] recipientArray = new long[recipientSet.size()]; int i = 0; - + for (Long recipientId : recipientSet) { recipientArray[i++] = recipientId; } - + Arrays.sort(recipientArray); - + return recipientArray; } - + private String getRecipientsAsString(long[] recipientIds) { StringBuilder sb = new StringBuilder(); for (int i=0;i<recipientIds.length;i++) { if (i != 0) sb.append(' '); sb.append(recipientIds[i]); } - + return sb.toString(); } - + private long createThreadForRecipients(String recipients, int recipientCount) { ContentValues contentValues = new ContentValues(4); long date = System.currentTimeMillis(); - + contentValues.put(DATE, date - date % 1000); contentValues.put(RECIPIENT_IDS, recipients); - + if (recipientCount > 1) contentValues.put(TYPE, 1); - + contentValues.put(MESSAGE_COUNT, 0); SQLiteDatabase db = databaseHelper.getWritableDatabase(); @@ -108,100 +108,100 @@ public class ThreadDatabase extends Database { contentValues.put(DATE, date - date % 1000); contentValues.put(MESSAGE_COUNT, count); contentValues.put(SNIPPET, body); - + SQLiteDatabase db = databaseHelper.getWritableDatabase(); db.update(TABLE_NAME, contentValues, ID + " = ?", new String[] {threadId+""}); notifyConversationListListeners(); } - + private void deleteThread(long threadId) { SQLiteDatabase db = databaseHelper.getWritableDatabase(); - db.delete(TABLE_NAME, ID_WHERE, new String[] {threadId+""}); + db.delete(TABLE_NAME, ID_WHERE, new String[] {threadId+""}); notifyConversationListListeners(); } - + private void deleteThreads(Set<Long> threadIds) { SQLiteDatabase db = databaseHelper.getWritableDatabase(); String where = ""; - + for (long threadId : threadIds) { where += ID + " = '" + threadId + "' OR "; } - + where = where.substring(0, where.length() - 4); - + db.delete(TABLE_NAME, where, null); notifyConversationListListeners(); } - + private void deleteAllThreads() { SQLiteDatabase db = databaseHelper.getWritableDatabase(); - db.delete(TABLE_NAME, null, null); - notifyConversationListListeners(); + db.delete(TABLE_NAME, null, null); + notifyConversationListListeners(); } - + public void setRead(long threadId) { ContentValues contentValues = new ContentValues(1); contentValues.put(READ, 1); SQLiteDatabase db = databaseHelper.getWritableDatabase(); db.update(TABLE_NAME, contentValues, ID_WHERE, new String[] {threadId+""}); - + DatabaseFactory.getSmsDatabase(context).setMessagesRead(threadId); DatabaseFactory.getMmsDatabase(context).setMessagesRead(threadId); notifyConversationListListeners(); } - + public void setUnread(long threadId) { ContentValues contentValues = new ContentValues(1); contentValues.put("read", 0); SQLiteDatabase db = databaseHelper.getWritableDatabase(); db.update(TABLE_NAME, contentValues, ID_WHERE, new String[] {threadId+""}); - notifyConversationListListeners(); + notifyConversationListListeners(); } - + public Cursor getFilteredConversationList(List<String> filter) { if (filter == null || filter.size() == 0) return null; - + List<Long> recipientIds = DatabaseFactory.getAddressDatabase(context).getCanonicalAddresses(filter); - + if (recipientIds == null || recipientIds.size() == 0) return null; - + String selection = RECIPIENT_IDS + " = ?"; String[] selectionArgs = new String[recipientIds.size()]; - + for (int i=0;i<recipientIds.size()-1;i++) selection += (" OR " + RECIPIENT_IDS + " = ?"); - - int i= 0; + + int i= 0; for (long id : recipientIds) { selectionArgs[i++] = id+""; } - + SQLiteDatabase db = databaseHelper.getReadableDatabase(); Cursor cursor = db.query(TABLE_NAME, null, selection, selectionArgs, null, null, DATE + " DESC"); - setNotifyConverationListListeners(cursor); + setNotifyConverationListListeners(cursor); return cursor; } - - public Cursor getConversationList() { + + public Cursor getConversationList() { SQLiteDatabase db = databaseHelper.getReadableDatabase(); Cursor cursor = db.query(TABLE_NAME, null, null, null, null, null, DATE + " DESC"); setNotifyConverationListListeners(cursor); return cursor; } - + public void deleteConversation(long threadId) { DatabaseFactory.getSmsDatabase(context).deleteThread(threadId); DatabaseFactory.getMmsDatabase(context).deleteThread(threadId); deleteThread(threadId); notifyConversationListeners(threadId); notifyConversationListListeners(); - } - + } + public void deleteConversations(Set<Long> selectedConversations) { DatabaseFactory.getSmsDatabase(context).deleteThreads(selectedConversations); @@ -210,11 +210,11 @@ public class ThreadDatabase extends Database { notifyConversationListeners(selectedConversations); notifyConversationListListeners(); } - + public void deleteAllConversations() { DatabaseFactory.getSmsDatabase(context).deleteAllThreads(); DatabaseFactory.getMmsDatabase(context).deleteAllThreads(); - deleteAllThreads(); + deleteAllThreads(); } public long getThreadIdIfExistsFor(Recipients recipients) { @@ -224,10 +224,10 @@ public class ThreadDatabase extends Database { String where = RECIPIENT_IDS + " = ?"; String[] recipientsArg = new String[] {recipientsList}; Cursor cursor = null; - + try { cursor = db.query(TABLE_NAME, new String[]{ID}, where, recipientsArg, null, null, null); - + if (cursor != null && cursor.moveToFirst()) return cursor.getLong(cursor.getColumnIndexOrThrow(ID)); else @@ -237,7 +237,7 @@ public class ThreadDatabase extends Database { cursor.close(); } } - + public long getThreadIdFor(Recipients recipients) { long[] recipientIds = getRecipientIds(recipients); String recipientsList = getRecipientsAsString(recipientIds); @@ -245,10 +245,10 @@ public class ThreadDatabase extends Database { String where = RECIPIENT_IDS + " = ?"; String[] recipientsArg = new String[] {recipientsList}; Cursor cursor = null; - + try { cursor = db.query(TABLE_NAME, new String[]{ID}, where, recipientsArg, null, null, null); - + if (cursor != null && cursor.moveToFirst()) return cursor.getLong(cursor.getColumnIndexOrThrow(ID)); else @@ -258,24 +258,24 @@ public class ThreadDatabase extends Database { cursor.close(); } } - + public void update(long threadId) { MmsSmsDatabase mmsSmsDatabase = DatabaseFactory.getMmsSmsDatabase(context); long count = mmsSmsDatabase.getConversationCount(threadId); - + if (count == 0) { deleteThread(threadId); notifyConversationListListeners(); return; } - + Cursor cursor = null; - + try { cursor = mmsSmsDatabase.getConversationSnippet(threadId); if (cursor != null && cursor.moveToFirst()) - updateThread(threadId, count, - cursor.getString(cursor.getColumnIndexOrThrow(SmsDatabase.BODY)), + updateThread(threadId, count, + cursor.getString(cursor.getColumnIndexOrThrow(SmsDatabase.BODY)), cursor.getLong(cursor.getColumnIndexOrThrow(SmsDatabase.DATE))); else deleteThread(threadId); @@ -283,7 +283,7 @@ public class ThreadDatabase extends Database { if (cursor != null) cursor.close(); } - + notifyConversationListListeners(); } diff --git a/src/org/thoughtcrime/securesms/sms/MultipartMessageHandler.java b/src/org/thoughtcrime/securesms/sms/MultipartMessageHandler.java index 4109903204..a908ef2880 100644 --- a/src/org/thoughtcrime/securesms/sms/MultipartMessageHandler.java +++ b/src/org/thoughtcrime/securesms/sms/MultipartMessageHandler.java @@ -1,6 +1,6 @@ -/** +/** * Copyright (C) 2011 Whisper Systems - * + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or @@ -10,48 +10,45 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.thoughtcrime.securesms.sms; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; +import android.util.Log; -import org.thoughtcrime.securesms.protocol.Message; -import org.thoughtcrime.securesms.protocol.Prefix; import org.thoughtcrime.securesms.protocol.WirePrefix; import org.thoughtcrime.securesms.util.Base64; import org.thoughtcrime.securesms.util.Conversions; import org.thoughtcrime.securesms.util.Hex; -import android.telephony.SmsManager; -import android.util.Log; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; public class MultipartMessageHandler { - + private static final int VERSION_OFFSET = 0; private static final int MULTIPART_OFFSET = 1; private static final int IDENTIFIER_OFFSET = 2; private static final int MULTIPART_SUPPORTED_AFTER_VERSION = 1; - + private final HashMap<String, byte[][]> partialMessages = new HashMap<String, byte[][]>(); private final HashMap<String, Integer> idMap = new HashMap<String, Integer>(); - + private String spliceMessage(String prefix, byte[][] messageParts) { Log.w("MultipartMessageHandler", "Have complete message fragments, splicing..."); int totalMessageLength = 0; - + for (int i=0;i<messageParts.length;i++) { totalMessageLength += messageParts[i].length; } - + byte[] totalMessage = new byte[totalMessageLength]; int totalMessageOffset = 0; - + for (int i=0;i<messageParts.length;i++) { System.arraycopy(messageParts[i], 0, totalMessage, totalMessageOffset, messageParts[i].length); totalMessageOffset += messageParts[i].length; @@ -59,21 +56,21 @@ public class MultipartMessageHandler { return prefix + Base64.encodeBytesWithoutPadding(totalMessage); } - + private boolean isComplete(byte[][] partialMessages) { for (int i=0;i<partialMessages.length;i++) if (partialMessages[i] == null) return false; - + Log.w("MultipartMessageHandler", "Buffer complete!"); - + return true; } - + private byte[][] findOrAllocateMultipartBuffer(String sender, int identifier, int count) { String key = sender + identifier; - + Log.w("MultipartMessageHandler", "Getting multipart buffer..."); - + if (partialMessages.containsKey(key)) { Log.w("MultipartMessageHandler", "Returning existing multipart buffer..."); return partialMessages.get(key); @@ -89,109 +86,109 @@ public class MultipartMessageHandler { byte[] strippedMessage = new byte[decodedMessage.length - (index == 0 ? 2 : 3)]; int copyDestinationIndex = 0; int copyDestinationLength = strippedMessage.length; - + if (index == 0) { strippedMessage[0] = decodedMessage[0]; copyDestinationIndex++; copyDestinationLength--; - } - + } + System.arraycopy(decodedMessage, 3, strippedMessage, copyDestinationIndex, copyDestinationLength); return strippedMessage; } - + private String processMultipartMessage(String prefix, int index, int count, String sender, int identifier, byte[] decodedMessage) { Log.w("MultipartMessageHandler", "Processing multipart message..."); decodedMessage = stripMultipartTransportLayer(index, decodedMessage); byte[][] messageParts = findOrAllocateMultipartBuffer(sender, identifier, count); messageParts[index] = decodedMessage; - + Log.w("MultipartMessageHandler", "Filled buffer at index: " + index); - + if (!isComplete(messageParts)) return null; - + partialMessages.remove(sender+identifier); return spliceMessage(prefix, messageParts); } - + private String processSinglePartMessage(String prefix, byte[] decodedMessage) { Log.w("MultipartMessageHandler", "Processing single part message..."); decodedMessage[MULTIPART_OFFSET] = decodedMessage[VERSION_OFFSET]; return prefix + Base64.encodeBytesWithoutPadding(decodedMessage, 1, decodedMessage.length-1); } - + public String processPotentialMultipartMessage(String prefix, String sender, String message) { try { byte[] decodedMessage = Base64.decodeWithoutPadding(message); int currentVersion = Conversions.highBitsToInt(decodedMessage[VERSION_OFFSET]); - + Log.w("MultipartMessageHandler", "Decoded message with version: " + currentVersion); Log.w("MultipartMessageHandler", "Decoded message: " + Hex.toString(decodedMessage)); - + if (currentVersion < MULTIPART_SUPPORTED_AFTER_VERSION) throw new AssertionError("Caller should have checked this."); - + int multipartIndex = Conversions.highBitsToInt(decodedMessage[MULTIPART_OFFSET]); int multipartCount = Conversions.lowBitsToInt(decodedMessage[MULTIPART_OFFSET]); int identifier = decodedMessage[IDENTIFIER_OFFSET] & 0xFF; - - Log.w("MultipartMessageHandler", "Multipart Info: (" + multipartIndex + "/" + multipartCount + ") ID: " + identifier); - + + Log.w("MultipartMessageHandler", "Multipart Info: (" + multipartIndex + "/" + multipartCount + ") ID: " + identifier); + if (multipartIndex >= multipartCount) return message; - + if (multipartCount == 1) return processSinglePartMessage(prefix, decodedMessage); else return processMultipartMessage(prefix, multipartIndex, multipartCount, sender, identifier, decodedMessage); - + } catch (IOException e) { return message; } } - + private ArrayList<String> buildSingleMessage(byte[] decodedMessage, WirePrefix prefix) { Log.w("MultipartMessageHandler", "Adding transport info to single-part message..."); - + ArrayList<String> list = new ArrayList<String>(); byte[] messageWithMultipartHeader = new byte[decodedMessage.length + 1]; - System.arraycopy(decodedMessage, 0, messageWithMultipartHeader, 1, decodedMessage.length); + System.arraycopy(decodedMessage, 0, messageWithMultipartHeader, 1, decodedMessage.length); messageWithMultipartHeader[0] = decodedMessage[0]; messageWithMultipartHeader[1] = Conversions.intsToByteHighAndLow(0, 1); String encodedMessage = Base64.encodeBytesWithoutPadding(messageWithMultipartHeader); - + list.add(prefix.calculatePrefix(encodedMessage) + encodedMessage); Log.w("MultipartMessageHandler", "Complete fragment size: " + list.get(list.size()-1).length()); return list; } - + private byte getIdForRecipient(String recipient) { Integer currentId; - + if (idMap.containsKey(recipient)) { currentId = idMap.get(recipient); idMap.remove(recipient); } else { - currentId = new Integer(0); + currentId = Integer.valueOf(0); } byte id = currentId.byteValue(); - idMap.put(recipient, new Integer((currentId.intValue() + 1) % 255)); - + idMap.put(recipient, Integer.valueOf((currentId.intValue() + 1) % 255)); + return id; } - + private ArrayList<String> buildMultipartMessage(String recipient, byte[] decodedMessage, WirePrefix prefix) { Log.w("MultipartMessageHandler", "Building multipart message..."); - + ArrayList<String> list = new ArrayList<String>(); byte versionByte = decodedMessage[0]; int messageOffset = 1; int segmentIndex = 0; int segmentCount = SmsTransportDetails.getMessageCountForBytes(decodedMessage.length); byte id = getIdForRecipient(recipient); - + while (messageOffset < decodedMessage.length-1) { int segmentSize = Math.min(SmsTransportDetails.BASE_MAX_BYTES, decodedMessage.length-messageOffset+3); byte[] segment = new byte[segmentSize]; @@ -200,35 +197,35 @@ public class MultipartMessageHandler { segment[2] = id; Log.w("MultipartMessageHandler", "Fragment: (" + segmentIndex + "/" + segmentCount +") -- ID: " + id); - + System.arraycopy(decodedMessage, messageOffset, segment, 3, segmentSize-3); messageOffset += segmentSize-3; - + String encodedSegment = Base64.encodeBytesWithoutPadding(segment); list.add(prefix.calculatePrefix(encodedSegment) + encodedSegment); - + Log.w("MultipartMessageHandler", "Complete fragment size: " + list.get(list.size()-1).length()); } - + return list; } - + public boolean isManualTransport(String message) { try { - byte[] decodedMessage = Base64.decodeWithoutPadding(message); + byte[] decodedMessage = Base64.decodeWithoutPadding(message); return Conversions.highBitsToInt(decodedMessage[0]) >= MULTIPART_SUPPORTED_AFTER_VERSION; } catch (IOException ioe) { throw new AssertionError(ioe); } } - + public ArrayList<String> divideMessage(String recipient, String message, WirePrefix prefix) { - try { + try { byte[] decodedMessage = Base64.decodeWithoutPadding(message); - if (decodedMessage.length <= SmsTransportDetails.SINGLE_MESSAGE_MAX_BYTES) + if (decodedMessage.length <= SmsTransportDetails.SINGLE_MESSAGE_MAX_BYTES) return buildSingleMessage(decodedMessage, prefix); - else + else return buildMultipartMessage(recipient, decodedMessage, prefix); } catch (IOException ioe) { throw new AssertionError(ioe);