/** * Copyright (C) 2013 Open 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 * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * 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 . */ package org.thoughtcrime.securesms.transport; import android.content.Context; import android.telephony.TelephonyManager; import android.util.Log; import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.crypto.MmsCipher; import org.thoughtcrime.securesms.crypto.storage.TextSecureAxolotlStore; import org.thoughtcrime.securesms.database.MmsDatabase; import org.thoughtcrime.securesms.mms.ApnUnavailableException; import org.thoughtcrime.securesms.mms.MmsRadio; import org.thoughtcrime.securesms.mms.MmsRadioException; import org.thoughtcrime.securesms.mms.MmsSendResult; import org.thoughtcrime.securesms.mms.OutgoingMmsConnection; import org.thoughtcrime.securesms.recipients.RecipientFormattingException; import org.thoughtcrime.securesms.util.NumberUtil; import org.whispersystems.libaxolotl.NoSessionException; import org.whispersystems.textsecure.util.Hex; import java.io.IOException; import java.util.Arrays; import ws.com.google.android.mms.pdu.EncodedStringValue; import ws.com.google.android.mms.pdu.PduComposer; import ws.com.google.android.mms.pdu.PduHeaders; import ws.com.google.android.mms.pdu.SendConf; import ws.com.google.android.mms.pdu.SendReq; public class MmsTransport { private static final String TAG = MmsTransport.class.getSimpleName(); private final Context context; private final MasterSecret masterSecret; private final MmsRadio radio; public MmsTransport(Context context, MasterSecret masterSecret) { this.context = context; this.masterSecret = masterSecret; this.radio = MmsRadio.getInstance(context); } public MmsSendResult deliver(SendReq message) throws UndeliverableMessageException, InsecureFallbackApprovalException { validateDestinations(message); try { if (isCdmaDevice()) { Log.w(TAG, "Sending MMS directly without radio change..."); try { return sendMms(message, false, false); } catch (IOException e) { Log.w(TAG, e); } } Log.w(TAG, "Sending MMS with radio change and proxy..."); radio.connect(); try { MmsSendResult result = sendMms(message, true, true); radio.disconnect(); return result; } catch (IOException e) { Log.w(TAG, e); } Log.w(TAG, "Sending MMS with radio change and without proxy..."); try { MmsSendResult result = sendMms(message, true, false); radio.disconnect(); return result; } catch (IOException ioe) { Log.w(TAG, ioe); radio.disconnect(); throw new UndeliverableMessageException(ioe); } } catch (MmsRadioException mre) { Log.w(TAG, mre); throw new UndeliverableMessageException(mre); } } private MmsSendResult sendMms(SendReq message, boolean usingMmsRadio, boolean useProxy) throws IOException, UndeliverableMessageException, InsecureFallbackApprovalException { String number = ((TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE)).getLine1Number(); boolean upgradedSecure = false; if (MmsDatabase.Types.isSecureType(message.getDatabaseMessageBox())) { message = getEncryptedMessage(message); upgradedSecure = true; } if (number != null && number.trim().length() != 0) { message.setFrom(new EncodedStringValue(number)); } try { OutgoingMmsConnection connection = new OutgoingMmsConnection(context, radio.getApnInformation(), new PduComposer(context, message).make()); SendConf conf = connection.send(usingMmsRadio, useProxy); for (int i=0;i