Add ability to specify APN information in TextSecure settings.

1) Add configuration options for APN information in TextSecure settings.

2) Fall back to TextSecure settings if system settings are unavailable
while sending/receiving MMS.

3) Catch sqlite exception when devices randomly don't have the same
APN db or table structure.
This commit is contained in:
Moxie Marlinspike 2012-12-08 16:46:38 -08:00
parent 10885fa8db
commit 54fad30f9f
7 changed files with 126 additions and 19 deletions

View File

@ -249,6 +249,14 @@
<string name="conversation_activity__send">Send</string> <string name="conversation_activity__send">Send</string>
<string name="conversation_activity__remove">Remove</string> <string name="conversation_activity__remove">Remove</string>
<!-- conversation_item_sent -->
<string name="conversation_item_sent__download">Download</string>
<string name="conversation_item_sent__downloading">Downloading</string>
<!-- conversation_item_received -->
<string name="conversation_item_received__download">Download</string>
<string name="conversation_item_received__downloading">Downloading</string>
<!-- conversation_fragment_cab --> <!-- conversation_fragment_cab -->
<string name="conversation_fragment_cab__batch_selection_mode">Batch Selection Mode</string> <string name="conversation_fragment_cab__batch_selection_mode">Batch Selection Mode</string>
@ -362,6 +370,12 @@
<string name="preferences__normal">Normal</string> <string name="preferences__normal">Normal</string>
<string name="preferences__slow">Slow</string> <string name="preferences__slow">Slow</string>
<string name="preferences__custom">Custom</string> <string name="preferences__custom">Custom</string>
<string name="preferences__advanced_mms_access_point_names">Advanced: MMS Access Point Names</string>
<string name="preferences__enable_local_apns">Enable local APNs</string>
<string name="preferences__use_apn_information_configured_here_when_system_apn_information_is_unavailable">Use APN information configured here when system APN information is unavailable.</string>
<string name="preferences__mmsc_url_required">MMSC URL (Required)</string>
<string name="preferences__mms_proxy_optional">MMS Proxy (Optional)</string>
<!-- **************************************** --> <!-- **************************************** -->
<!-- menus --> <!-- menus -->
@ -434,9 +448,5 @@
<string name="PlayStoreListing">TextSecure is a security enhanced text messaging application that serves as a full replacement for the default text messaging application. Messages to other TextSecure users are encrypted over the air, and all text messages are stored in an encrypted database on the device. If your phone is lost or stolen, your messages will be safe, and communication with other TextSecure users can\'t be monitored over the air.</string> <string name="PlayStoreListing">TextSecure is a security enhanced text messaging application that serves as a full replacement for the default text messaging application. Messages to other TextSecure users are encrypted over the air, and all text messages are stored in an encrypted database on the device. If your phone is lost or stolen, your messages will be safe, and communication with other TextSecure users can\'t be monitored over the air.</string>
<!-- EOF --> <!-- EOF -->
<string name="conversation_item_sent__download">Download</string>
<string name="conversation_item_sent__downloading">Downloading</string>
<string name="conversation_item_received__download">Download</string>
<string name="conversation_item_received__downloading">Downloading</string>
</resources> </resources>

View File

@ -140,4 +140,20 @@
android:title="@string/preferences__vibrate" android:title="@string/preferences__vibrate"
android:summary="@string/preferences__also_vibrate_when_notified" /> android:summary="@string/preferences__also_vibrate_when_notified" />
</PreferenceCategory> </PreferenceCategory>
<PreferenceCategory android:title="@string/preferences__advanced_mms_access_point_names">
<CheckBoxPreference android:key="pref_use_local_apns"
android:defaultValue="false"
android:title="@string/preferences__enable_local_apns"
android:summary="@string/preferences__use_apn_information_configured_here_when_system_apn_information_is_unavailable"/>
<EditTextPreference android:key="pref_apn_mmsc_host"
android:title="@string/preferences__mmsc_url_required"
android:dependency="pref_use_local_apns" />
<EditTextPreference android:key="pref_apn_mms_proxy"
android:title="@string/preferences__mms_proxy_optional"
android:dependency="pref_use_local_apns" />
</PreferenceCategory>
</PreferenceScreen> </PreferenceScreen>

View File

@ -21,6 +21,7 @@ import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.preference.EditTextPreference;
import android.preference.Preference; import android.preference.Preference;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.provider.ContactsContract; import android.provider.ContactsContract;
@ -74,6 +75,10 @@ public class ApplicationPreferencesActivity extends SherlockPreferenceActivity {
private static final String MANAGE_IDENTITIES_PREF = "pref_manage_identity"; private static final String MANAGE_IDENTITIES_PREF = "pref_manage_identity";
private static final String CHANGE_PASSPHRASE_PREF = "pref_change_passphrase"; private static final String CHANGE_PASSPHRASE_PREF = "pref_change_passphrase";
public static final String USE_LOCAL_MMS_APNS_PREF = "pref_use_local_apns";
public static final String MMSC_HOST_PREF = "pref_apn_mmsc_host";
public static final String MMSC_PROXY_PREF = "pref_apn_mms_proxy";
@Override @Override
protected void onCreate(Bundle icicle) { protected void onCreate(Bundle icicle) {
super.onCreate(icicle); super.onCreate(icicle);
@ -83,6 +88,7 @@ public class ApplicationPreferencesActivity extends SherlockPreferenceActivity {
addPreferencesFromResource(R.xml.preferences); addPreferencesFromResource(R.xml.preferences);
initializeIdentitySelection(); initializeIdentitySelection();
initializeEditTextSummaries();
this.findPreference(VIEW_MY_IDENTITY_PREF) this.findPreference(VIEW_MY_IDENTITY_PREF)
.setOnPreferenceClickListener(new ViewMyIdentityClickListener()); .setOnPreferenceClickListener(new ViewMyIdentityClickListener());
@ -139,6 +145,39 @@ public class ApplicationPreferencesActivity extends SherlockPreferenceActivity {
return false; return false;
} }
private void initializeEditTextSummaries() {
final EditTextPreference mmscUrlPreference = (EditTextPreference)this.findPreference(MMSC_HOST_PREF);
final EditTextPreference mmsProxyPreference = (EditTextPreference)this.findPreference(MMSC_PROXY_PREF);
if (mmscUrlPreference.getText() == null) {
mmscUrlPreference.setSummary("Not set");
} else {
mmscUrlPreference.setSummary(mmscUrlPreference.getText());
}
if (mmsProxyPreference.getText() == null) {
mmsProxyPreference.setSummary("Not set");
} else {
mmsProxyPreference.setSummary(mmsProxyPreference.getText());
}
mmscUrlPreference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
mmscUrlPreference.setSummary(newValue == null ? "Not set" : (String)newValue);
return true;
}
});
mmsProxyPreference.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
mmsProxyPreference.setSummary(newValue == null ? "Not set" : (String)newValue);
return true;
}
});
}
private void initializeIdentitySelection() { private void initializeIdentitySelection() {
ContactIdentityManager identity = ContactIdentityManager.getInstance(this); ContactIdentityManager identity = ContactIdentityManager.getInstance(this);

View File

@ -0,0 +1,19 @@
package org.thoughtcrime.securesms.mms;
public class ApnUnavailableException extends Exception {
public ApnUnavailableException() {
}
public ApnUnavailableException(String detailMessage) {
super(detailMessage);
}
public ApnUnavailableException(Throwable throwable) {
super(throwable);
}
public ApnUnavailableException(String detailMessage, Throwable throwable) {
super(detailMessage, throwable);
}
}

View File

@ -17,9 +17,13 @@
package org.thoughtcrime.securesms.mms; package org.thoughtcrime.securesms.mms;
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences;
import android.database.Cursor; import android.database.Cursor;
import android.database.sqlite.SQLiteException;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.net.Uri; import android.net.Uri;
import android.preference.PreferenceManager;
import android.util.Log;
import org.apache.http.HttpEntity; import org.apache.http.HttpEntity;
import org.apache.http.HttpHost; import org.apache.http.HttpHost;
@ -37,26 +41,46 @@ import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams; import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams; import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams; import org.apache.http.params.HttpProtocolParams;
import org.thoughtcrime.securesms.ApplicationPreferencesActivity;
import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.service.MmsDownloader; import org.thoughtcrime.securesms.service.MmsDownloader;
import org.thoughtcrime.securesms.util.Conversions; import org.thoughtcrime.securesms.util.Conversions;
import ws.com.google.android.mms.MmsException;
import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.IOException; import java.io.IOException;
import java.net.InetAddress; import java.net.InetAddress;
public class MmsCommunication { public class MmsCommunication {
protected static MmsConnectionParameters getMmsConnectionParameters(Context context, String apn) protected static MmsConnectionParameters getLocallyConfiguredMmsConnectionParameters(Context context)
throws MmsException throws ApnUnavailableException
{ {
Cursor cursor = DatabaseFactory.getMmsDatabase(context).getCarrierMmsInformation(apn); SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
if (preferences.getBoolean(ApplicationPreferencesActivity.USE_LOCAL_MMS_APNS_PREF, false)) {
String mmsc = preferences.getString(ApplicationPreferencesActivity.MMSC_HOST_PREF, null);
if (mmsc == null || !mmsc.startsWith("http"))
throw new ApnUnavailableException("Malformed locally configured MMSC: " + mmsc);
String proxy = preferences.getString(ApplicationPreferencesActivity.MMSC_PROXY_PREF, null);
return new MmsConnectionParameters(mmsc, proxy, null);
}
throw new ApnUnavailableException("No locally configured parameters available");
}
protected static MmsConnectionParameters getMmsConnectionParameters(Context context, String apn)
throws ApnUnavailableException
{
Cursor cursor = null;
try { try {
cursor = DatabaseFactory.getMmsDatabase(context).getCarrierMmsInformation(apn);
if (cursor == null || !cursor.moveToFirst()) if (cursor == null || !cursor.moveToFirst())
throw new MmsException("No carrier MMS information available."); return getLocallyConfiguredMmsConnectionParameters(context);
do { do {
String mmsc = cursor.getString(cursor.getColumnIndexOrThrow("mmsc")); String mmsc = cursor.getString(cursor.getColumnIndexOrThrow("mmsc"));
@ -68,7 +92,10 @@ public class MmsCommunication {
} while (cursor.moveToNext()); } while (cursor.moveToNext());
throw new MmsException("No carrier MMS information available."); return getLocallyConfiguredMmsConnectionParameters(context);
} catch (SQLiteException sqe) {
Log.w("MmsCommunication", sqe);
return getLocallyConfiguredMmsConnectionParameters(context);
} finally { } finally {
if (cursor != null) if (cursor != null)
cursor.close(); cursor.close();

View File

@ -25,8 +25,6 @@ import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient; import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpGet;
import ws.com.google.android.mms.MmsException;
import java.io.IOException; import java.io.IOException;
public class MmsDownloadHelper extends MmsCommunication { public class MmsDownloadHelper extends MmsCommunication {
@ -54,8 +52,8 @@ public class MmsDownloadHelper extends MmsCommunication {
try { try {
connectionParameters = getMmsConnectionParameters(context, apn); connectionParameters = getMmsConnectionParameters(context, apn);
} catch (MmsException me) { } catch (ApnUnavailableException aue) {
Log.w("MmsDownloadHelper", me); Log.w("MmsDownloadHelper", aue);
connectionParameters = new MmsConnectionParameters(null, null, null); connectionParameters = new MmsConnectionParameters(null, null, null);
} }

View File

@ -26,8 +26,6 @@ import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ByteArrayEntity; import org.apache.http.entity.ByteArrayEntity;
import ws.com.google.android.mms.MmsException;
import java.io.IOException; import java.io.IOException;
public class MmsSendHelper extends MmsCommunication { public class MmsSendHelper extends MmsCommunication {
@ -59,8 +57,8 @@ public class MmsSendHelper extends MmsCommunication {
MmsConnectionParameters parameters = getMmsConnectionParameters(context, apn); MmsConnectionParameters parameters = getMmsConnectionParameters(context, apn);
checkRouteToHost(context, parameters, parameters.getMmsc()); checkRouteToHost(context, parameters, parameters.getMmsc());
return makePost(parameters, mms); return makePost(parameters, mms);
} catch (MmsException me) { } catch (ApnUnavailableException aue) {
Log.w("MmsSender", me); Log.w("MmsSender", aue);
throw new IOException("Failed to get MMSC information..."); throw new IOException("Failed to get MMSC information...");
} }
} }