Initial fixes for MMS retrieval.

1) Parse the APN information based on what the ConnectionManager
tells us.

2) Accept email addresses as a valid Recipient format.
This commit is contained in:
Moxie Marlinspike 2012-09-30 11:46:45 -07:00
parent 59e7226183
commit cf9dc51f31
9 changed files with 224 additions and 217 deletions

View File

@ -421,9 +421,9 @@ public class MmsDatabase extends Database {
database.delete(TABLE_NAME, null, null);
}
public Cursor getCarrierMmsInformation() {
public Cursor getCarrierMmsInformation(String apn) {
Uri uri = Uri.withAppendedPath(Uri.parse("content://telephony/carriers"), "current");
String selection = "type = 'mms'";
String selection = (apn == null || apn.trim().length() == 0) ? null : String.format("apn = '%s'", apn.trim());
return context.getContentResolver().query(uri, null, selection, null, null);
}

View File

@ -16,9 +16,10 @@
*/
package org.thoughtcrime.securesms.mms;
import java.io.DataInputStream;
import java.io.IOException;
import java.net.InetAddress;
import android.content.Context;
import android.database.Cursor;
import android.net.ConnectivityManager;
import android.net.Uri;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
@ -42,19 +43,20 @@ import org.thoughtcrime.securesms.util.Conversions;
import ws.com.google.android.mms.MmsException;
import android.content.Context;
import android.database.Cursor;
import android.net.ConnectivityManager;
import android.net.Uri;
import java.io.DataInputStream;
import java.io.IOException;
import java.net.InetAddress;
public class MmsCommunication {
protected static MmsConnectionParameters getMmsConnectionParameters(Context context) throws MmsException {
Cursor cursor = DatabaseFactory.getMmsDatabase(context).getCarrierMmsInformation();
protected static MmsConnectionParameters getMmsConnectionParameters(Context context, String apn)
throws MmsException
{
Cursor cursor = DatabaseFactory.getMmsDatabase(context).getCarrierMmsInformation(apn);
try {
if (cursor == null || !cursor.moveToFirst())
throw new MmsException("No carrier MMS information available.");
throw new MmsException("No carrier MMS information available.");
do {
String mmsc = cursor.getString(cursor.getColumnIndexOrThrow("mmsc"));

View File

@ -16,9 +16,8 @@
*/
package org.thoughtcrime.securesms.mms;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import android.content.Context;
import android.util.Log;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
@ -30,12 +29,15 @@ import org.apache.http.client.methods.HttpGet;
import ws.com.google.android.mms.MmsException;
import android.content.Context;
import android.util.Log;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
public class MmsDownloadHelper extends MmsCommunication {
private static byte[] makeRequest(MmsConnectionParameters connectionParameters, String url) throws ClientProtocolException, IOException {
private static byte[] makeRequest(MmsConnectionParameters connectionParameters, String url)
throws ClientProtocolException, IOException
{
try {
HttpClient client = constructHttpClient(connectionParameters);
URI hostUrl = new URI(url);
@ -58,9 +60,9 @@ public class MmsDownloadHelper extends MmsCommunication {
}
}
public static byte[] retrieveMms(Context context, String url) throws IOException {
public static byte[] retrieveMms(Context context, String url, String apn) throws IOException {
try {
MmsConnectionParameters connectionParameters = getMmsConnectionParameters(context);
MmsConnectionParameters connectionParameters = getMmsConnectionParameters(context, apn);
checkRouteToHost(context, connectionParameters, url);
return makeRequest(connectionParameters, url);

View File

@ -16,9 +16,8 @@
*/
package org.thoughtcrime.securesms.mms;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import android.content.Context;
import android.util.Log;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
@ -27,11 +26,12 @@ import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ByteArrayEntity;
import org.thoughtcrime.securesms.util.Hex;
import ws.com.google.android.mms.MmsException;
import android.content.Context;
import android.util.Log;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
public class MmsSendHelper extends MmsCommunication {
@ -63,10 +63,10 @@ public class MmsSendHelper extends MmsCommunication {
}
}
public static byte[] sendMms(Context context, byte[] mms) throws IOException {
public static byte[] sendMms(Context context, byte[] mms, String apn) throws IOException {
Log.w("MmsSender", "Sending MMS of length: " + mms.length);
try {
MmsConnectionParameters parameters = getMmsConnectionParameters(context);
MmsConnectionParameters parameters = getMmsConnectionParameters(context, apn);
checkRouteToHost(context, parameters, parameters.getMmsc());
return makePost(parameters, mms);
} catch (MmsException me) {

View File

@ -19,7 +19,6 @@ package org.thoughtcrime.securesms.recipients;
import android.content.Context;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.telephony.PhoneNumberUtils;
import android.util.Log;
import org.thoughtcrime.securesms.R;
@ -146,7 +145,7 @@ public class RecipientFactory {
int end = recipient.indexOf('>');
String value = recipient.substring(begin + 1, end);
if (PhoneNumberUtils.isWellFormedSmsAddress(value))
if (NumberUtil.isValidSmsOrEmail(value))
return value;
else
throw new RecipientFormattingException("Bracketed value: " + value + " is not valid.");

View File

@ -16,8 +16,9 @@
*/
package org.thoughtcrime.securesms.service;
import java.io.IOException;
import java.util.LinkedList;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import org.thoughtcrime.securesms.crypto.DecryptingQueue;
import org.thoughtcrime.securesms.crypto.MasterSecret;
@ -29,9 +30,9 @@ import org.thoughtcrime.securesms.protocol.WirePrefix;
import ws.com.google.android.mms.MmsException;
import ws.com.google.android.mms.pdu.PduParser;
import ws.com.google.android.mms.pdu.RetrieveConf;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import java.io.IOException;
import java.util.LinkedList;
public class MmsDownloader extends MmscProcessor {
@ -66,7 +67,8 @@ public class MmsDownloader extends MmscProcessor {
try {
byte[] pdu = MmsDownloadHelper.retrieveMms(context, item.getContentLocation());
byte[] pdu = MmsDownloadHelper.retrieveMms(context, item.getContentLocation(),
getApnInformation());
RetrieveConf retrieved = (RetrieveConf)new PduParser(pdu).parse();
for (int i=0;i<retrieved.getBody().getPartsNum();i++) {

View File

@ -16,6 +16,10 @@
*/
package org.thoughtcrime.securesms.service;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MmsDatabase;
@ -24,9 +28,6 @@ import ws.com.google.android.mms.pdu.GenericPdu;
import ws.com.google.android.mms.pdu.NotificationInd;
import ws.com.google.android.mms.pdu.PduHeaders;
import ws.com.google.android.mms.pdu.PduParser;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class MmsReceiver {
@ -55,9 +56,9 @@ public class MmsReceiver {
MmsDatabase database;
if (masterSecret != null)
database = DatabaseFactory.getEncryptingMmsDatabase(context, masterSecret);
database = DatabaseFactory.getEncryptingMmsDatabase(context, masterSecret);
else
database = DatabaseFactory.getMmsDatabase(context);
database = DatabaseFactory.getMmsDatabase(context);
long messageId = database.insertMessageReceived((NotificationInd)pdu);
MessageNotifier.updateNotification(context, true);

View File

@ -16,16 +16,16 @@
*/
package org.thoughtcrime.securesms.service;
import java.io.IOException;
import java.util.Arrays;
import java.util.LinkedList;
import android.content.Context;
import android.content.Intent;
import android.telephony.TelephonyManager;
import android.util.Log;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.crypto.SessionCipher;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MmsDatabase;
import org.thoughtcrime.securesms.mms.MmsSendHelper;
import org.thoughtcrime.securesms.mms.PngTransport;
import org.thoughtcrime.securesms.mms.TextTransport;
import org.thoughtcrime.securesms.protocol.WirePrefix;
import org.thoughtcrime.securesms.recipients.Recipient;
@ -33,7 +33,6 @@ import org.thoughtcrime.securesms.util.Hex;
import ws.com.google.android.mms.ContentType;
import ws.com.google.android.mms.MmsException;
import ws.com.google.android.mms.pdu.CharacterSets;
import ws.com.google.android.mms.pdu.EncodedStringValue;
import ws.com.google.android.mms.pdu.PduBody;
import ws.com.google.android.mms.pdu.PduComposer;
@ -42,10 +41,10 @@ import ws.com.google.android.mms.pdu.PduParser;
import ws.com.google.android.mms.pdu.PduPart;
import ws.com.google.android.mms.pdu.SendConf;
import ws.com.google.android.mms.pdu.SendReq;
import android.content.Context;
import android.content.Intent;
import android.telephony.TelephonyManager;
import android.util.Log;
import java.io.IOException;
import java.util.Arrays;
import java.util.LinkedList;
public class MmsSender extends MmscProcessor {
@ -61,23 +60,23 @@ public class MmsSender extends MmscProcessor {
MmsDatabase database = DatabaseFactory.getEncryptingMmsDatabase(context, masterSecret);
try {
SendReq[] sendRequests;
SendReq[] sendRequests;
if (messageId == -1) {
sendRequests = database.getOutgoingMessages();
} else {
sendRequests = new SendReq[1];
sendRequests[0] = database.getSendRequest(messageId);
}
if (messageId == -1) {
sendRequests = database.getOutgoingMessages();
} else {
sendRequests = new SendReq[1];
sendRequests[0] = database.getSendRequest(messageId);
}
if (sendRequests.length > 0)
handleSendMms(sendRequests);
if (sendRequests.length > 0)
handleSendMms(sendRequests);
} catch (MmsException me) {
Log.w("MmsSender", me);
if (messageId != -1)
database.markAsSentFailed(messageId);
}
Log.w("MmsSender", me);
if (messageId != -1)
database.markAsSentFailed(messageId);
}
} else if (intent.getAction().equals(SendReceiveService.SEND_MMS_CONNECTIVITY_ACTION)) {
handleConnectivityChange(masterSecret);
}
@ -94,7 +93,7 @@ public class MmsSender extends MmscProcessor {
private void handleSendMms(SendReq[] sendRequests) {
if (!isConnectivityPossible()) {
for (int i=0;i<sendRequests.length;i++)
DatabaseFactory.getMmsDatabase(context).markAsSentFailed(sendRequests[i].getDatabaseMessageId());
DatabaseFactory.getMmsDatabase(context).markAsSentFailed(sendRequests[i].getDatabaseMessageId());
} else {
pendingMessages.add(sendRequests);
issueConnectivityRequest();
@ -138,35 +137,35 @@ public class MmsSender extends MmscProcessor {
private void sendMms(MmsDatabase db, SendReq pdu, String number, long messageId, boolean secure) {
try {
if (number != null && number.trim().length() != 0)
pdu.setFrom(new EncodedStringValue(number));
pdu.setFrom(new EncodedStringValue(number));
byte[] response = MmsSendHelper.sendMms(context, new PduComposer(context, pdu).make());
byte[] response = MmsSendHelper.sendMms(context, new PduComposer(context, pdu).make(), getApnInformation());
SendConf conf = (SendConf) new PduParser(response).parse();
for (int i=0;i<pdu.getBody().getPartsNum();i++) {
Log.w("MmsSender", "Sent MMS part of content-type: " + new String(pdu.getBody().getPart(i).getContentType()));
Log.w("MmsSender", "Sent MMS part of content-type: " + new String(pdu.getBody().getPart(i).getContentType()));
}
if (conf == null) {
db.markAsSentFailed(messageId);
Log.w("MmsSender", "No M-Send.conf received in response to send.");
return;
db.markAsSentFailed(messageId);
Log.w("MmsSender", "No M-Send.conf received in response to send.");
return;
} else if (conf.getResponseStatus() != PduHeaders.RESPONSE_STATUS_OK) {
Log.w("MmsSender", "Got bad response: " + conf.getResponseStatus());
db.updateResponseStatus(messageId, conf.getResponseStatus());
db.markAsSentFailed(messageId);
return;
Log.w("MmsSender", "Got bad response: " + conf.getResponseStatus());
db.updateResponseStatus(messageId, conf.getResponseStatus());
db.markAsSentFailed(messageId);
return;
} else if (isInconsistentResponse(pdu, conf)) {
db.markAsSentFailed(messageId);
Log.w("MmsSender", "Got a response for the wrong transaction?");
return;
db.markAsSentFailed(messageId);
Log.w("MmsSender", "Got a response for the wrong transaction?");
return;
} else {
Log.w("MmsSender", "Successful send! " + messageId);
if (!secure)
db.markAsSent(messageId, conf.getMessageId(), conf.getResponseStatus());
else
db.markAsSecureSent(messageId, conf.getMessageId(), conf.getResponseStatus());
}
Log.w("MmsSender", "Successful send! " + messageId);
if (!secure)
db.markAsSent(messageId, conf.getMessageId(), conf.getResponseStatus());
else
db.markAsSecureSent(messageId, conf.getMessageId(), conf.getResponseStatus());
}
} catch (IOException ioe) {
Log.w("MmsSender", ioe);
db.markAsSentFailed(messageId);
@ -185,7 +184,7 @@ public class MmsSender extends MmscProcessor {
long messageBox = request.getDatabaseMessageBox();
if (MmsDatabase.Types.isSecureMmsBox(messageBox))
request = getEncryptedMms(masterSecret, request, messageId);
request = getEncryptedMms(masterSecret, request, messageId);
sendMms(db, request, number, messageId, MmsDatabase.Types.isSecureMmsBox(messageBox));
}
@ -195,7 +194,7 @@ public class MmsSender extends MmscProcessor {
}
@Override
protected String getConnectivityAction() {
protected String getConnectivityAction() {
return SendReceiveService.SEND_MMS_CONNECTIVITY_ACTION;
}

View File

@ -16,8 +16,6 @@
*/
package org.thoughtcrime.securesms.service;
import java.util.LinkedList;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@ -48,6 +46,10 @@ public abstract class MmscProcessor {
this.wakeLock.setReferenceCounted(false);
}
protected String getApnInformation() {
return connectivityManager.getNetworkInfo(TYPE_MOBILE_MMS).getExtraInfo();
}
protected boolean isConnected() {
NetworkInfo info = connectivityManager.getNetworkInfo(TYPE_MOBILE_MMS);
@ -102,7 +104,7 @@ public abstract class MmscProcessor {
private class ConnectivityListener extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
public void onReceive(Context context, Intent intent) {
Log.w("MmsService", "Dispatching connectivity change...");
issueConnectivityChange();
Log.w("MmsService", "Dispatched...");