diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/ApnDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/ApnDatabase.java deleted file mode 100644 index 94c2e4c0d0..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/database/ApnDatabase.java +++ /dev/null @@ -1,174 +0,0 @@ -/** - * Copyright (C) 2014 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.database; - -import android.content.Context; -import android.content.res.AssetManager; -import android.database.Cursor; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteException; -import android.text.TextUtils; -import org.session.libsignal.utilities.logging.Log; - -import org.thoughtcrime.securesms.mms.LegacyMmsConnection.Apn; -import org.session.libsession.utilities.TextSecurePreferences; -import org.session.libsession.utilities.Util; -import org.session.libsignal.libsignal.util.guava.Optional; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; - -/** - * Database to query APN and MMSC information - */ -public class ApnDatabase { - private static final String TAG = ApnDatabase.class.getSimpleName(); - - private final SQLiteDatabase db; - private final Context context; - - private static final String DATABASE_NAME = "apns.db"; - private static final String ASSET_PATH = "databases" + File.separator + DATABASE_NAME; - - private static final String TABLE_NAME = "apns"; - private static final String ID_COLUMN = "_id"; - private static final String MCC_MNC_COLUMN = "mccmnc"; - private static final String MCC_COLUMN = "mcc"; - private static final String MNC_COLUMN = "mnc"; - private static final String CARRIER_COLUMN = "carrier"; - private static final String APN_COLUMN = "apn"; - private static final String MMSC_COLUMN = "mmsc"; - private static final String PORT_COLUMN = "port"; - private static final String TYPE_COLUMN = "type"; - private static final String PROTOCOL_COLUMN = "protocol"; - private static final String BEARER_COLUMN = "bearer"; - private static final String ROAMING_PROTOCOL_COLUMN = "roaming_protocol"; - private static final String CARRIER_ENABLED_COLUMN = "carrier_enabled"; - private static final String MMS_PROXY_COLUMN = "mmsproxy"; - private static final String MMS_PORT_COLUMN = "mmsport"; - private static final String PROXY_COLUMN = "proxy"; - private static final String MVNO_MATCH_DATA_COLUMN = "mvno_match_data"; - private static final String MVNO_TYPE_COLUMN = "mvno"; - private static final String AUTH_TYPE_COLUMN = "authtype"; - private static final String USER_COLUMN = "user"; - private static final String PASSWORD_COLUMN = "password"; - private static final String SERVER_COLUMN = "server"; - - private static final String BASE_SELECTION = MCC_MNC_COLUMN + " = ?"; - - private static ApnDatabase instance = null; - - public synchronized static ApnDatabase getInstance(Context context) throws IOException { - if (instance == null) instance = new ApnDatabase(context.getApplicationContext()); - return instance; - } - - private ApnDatabase(final Context context) throws IOException { - this.context = context; - - File dbFile = context.getDatabasePath(DATABASE_NAME); - - if (!dbFile.getParentFile().exists() && !dbFile.getParentFile().mkdir()) { - throw new IOException("couldn't make databases directory"); - } - - Util.copy(context.getAssets().open(ASSET_PATH, AssetManager.ACCESS_STREAMING), - new FileOutputStream(dbFile)); - - try { - this.db = SQLiteDatabase.openDatabase(context.getDatabasePath(DATABASE_NAME).getPath(), - null, - SQLiteDatabase.OPEN_READONLY | SQLiteDatabase.NO_LOCALIZED_COLLATORS); - } catch (SQLiteException e) { - throw new IOException(e); - } - } - - private Apn getCustomApnParameters() { - String mmsc = TextSecurePreferences.getMmscUrl(context).trim(); - - if (!TextUtils.isEmpty(mmsc) && !mmsc.startsWith("http")) - mmsc = "http://" + mmsc; - - String proxy = TextSecurePreferences.getMmscProxy(context); - String port = TextSecurePreferences.getMmscProxyPort(context); - String user = TextSecurePreferences.getMmscUsername(context); - String pass = TextSecurePreferences.getMmscPassword(context); - - return new Apn(mmsc, proxy, port, user, pass); - } - - public Apn getDefaultApnParameters(String mccmnc, String apn) { - if (mccmnc == null) { - Log.w(TAG, "mccmnc was null, returning null"); - return Apn.EMPTY; - } - - Cursor cursor = null; - - try { - if (apn != null) { - Log.d(TAG, "Querying table for MCC+MNC " + mccmnc + " and APN name " + apn); - cursor = db.query(TABLE_NAME, null, - BASE_SELECTION + " AND " + APN_COLUMN + " = ?", - new String[] {mccmnc, apn}, - null, null, null); - } - - if (cursor == null || !cursor.moveToFirst()) { - if (cursor != null) cursor.close(); - Log.d(TAG, "Querying table for MCC+MNC " + mccmnc + " without APN name"); - cursor = db.query(TABLE_NAME, null, - BASE_SELECTION, - new String[] {mccmnc}, - null, null, null); - } - - if (cursor != null && cursor.moveToFirst()) { - Apn params = new Apn(cursor.getString(cursor.getColumnIndexOrThrow(MMSC_COLUMN)), - cursor.getString(cursor.getColumnIndexOrThrow(MMS_PROXY_COLUMN)), - cursor.getString(cursor.getColumnIndexOrThrow(MMS_PORT_COLUMN)), - cursor.getString(cursor.getColumnIndexOrThrow(USER_COLUMN)), - cursor.getString(cursor.getColumnIndexOrThrow(PASSWORD_COLUMN))); - Log.d(TAG, "Returning preferred APN " + params); - return params; - } - - Log.w(TAG, "No matching APNs found, returning null"); - - return Apn.EMPTY; - } finally { - if (cursor != null) cursor.close(); - } - - } - - public Optional getMmsConnectionParameters(String mccmnc, String apn) { - Apn customApn = getCustomApnParameters(); - Apn defaultApn = getDefaultApnParameters(mccmnc, apn); - Apn result = new Apn(customApn, defaultApn, - TextSecurePreferences.getUseCustomMmsc(context), - TextSecurePreferences.getUseCustomMmscProxy(context), - TextSecurePreferences.getUseCustomMmscProxyPort(context), - TextSecurePreferences.getUseCustomMmscUsername(context), - TextSecurePreferences.getUseCustomMmscPassword(context)); - - if (TextUtils.isEmpty(result.getMmsc())) return Optional.absent(); - else return Optional.of(result); - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/mms/IncomingLollipopMmsConnection.java b/app/src/main/java/org/thoughtcrime/securesms/mms/IncomingLollipopMmsConnection.java deleted file mode 100644 index 2159c38ecc..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/mms/IncomingLollipopMmsConnection.java +++ /dev/null @@ -1,121 +0,0 @@ -/** - * Copyright (C) 2015 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.mms; - -import android.annotation.TargetApi; -import android.content.Context; -import android.content.Intent; -import android.os.Build.VERSION; -import android.os.Build.VERSION_CODES; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import android.telephony.SmsManager; -import org.session.libsignal.utilities.logging.Log; - -import com.google.android.mms.InvalidHeaderValueException; -import com.google.android.mms.pdu_alt.NotifyRespInd; -import com.google.android.mms.pdu_alt.PduComposer; -import com.google.android.mms.pdu_alt.PduHeaders; -import com.google.android.mms.pdu_alt.PduParser; -import com.google.android.mms.pdu_alt.RetrieveConf; - -import org.thoughtcrime.securesms.providers.MmsBodyProvider; -import org.thoughtcrime.securesms.transport.UndeliverableMessageException; -import org.session.libsession.utilities.Util; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.util.concurrent.TimeoutException; - -public class IncomingLollipopMmsConnection extends LollipopMmsConnection implements IncomingMmsConnection { - - public static final String ACTION = IncomingLollipopMmsConnection.class.getCanonicalName() + "MMS_DOWNLOADED_ACTION"; - private static final String TAG = IncomingLollipopMmsConnection.class.getSimpleName(); - - public IncomingLollipopMmsConnection(Context context) { - super(context, ACTION); - } - - @TargetApi(VERSION_CODES.LOLLIPOP) - @Override - public synchronized void onResult(Context context, Intent intent) { - if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP_MR1) { - Log.i(TAG, "HTTP status: " + intent.getIntExtra(SmsManager.EXTRA_MMS_HTTP_STATUS, -1)); - } - Log.i(TAG, "code: " + getResultCode() + ", result string: " + getResultData()); - } - - @Override - @TargetApi(VERSION_CODES.LOLLIPOP) - public synchronized @Nullable RetrieveConf retrieve(@NonNull String contentLocation, - byte[] transactionId, - int subscriptionId) throws MmsException - { - beginTransaction(); - - try { - MmsBodyProvider.Pointer pointer = MmsBodyProvider.makeTemporaryPointer(getContext()); - - Log.i(TAG, "downloading multimedia from " + contentLocation + " to " + pointer.getUri()); - - SmsManager smsManager; - - if (VERSION.SDK_INT >= 22 && subscriptionId != -1) { - smsManager = SmsManager.getSmsManagerForSubscriptionId(subscriptionId); - } else { - smsManager = SmsManager.getDefault(); - } - - smsManager.downloadMultimediaMessage(getContext(), - contentLocation, - pointer.getUri(), - null, - getPendingIntent()); - - waitForResult(); - - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - Util.copy(pointer.getInputStream(), baos); - pointer.close(); - - Log.i(TAG, baos.size() + "-byte response: ");// + Hex.dump(baos.toByteArray())); - - RetrieveConf retrieved = (RetrieveConf) new PduParser(baos.toByteArray()).parse(); - - if (retrieved == null) return null; - - sendRetrievedAcknowledgement(transactionId, retrieved.getMmsVersion(), subscriptionId); - return retrieved; - } catch (IOException | TimeoutException e) { - Log.w(TAG, e); - throw new MmsException(e); - } finally { - endTransaction(); - } - } - - private void sendRetrievedAcknowledgement(byte[] transactionId, int mmsVersion, int subscriptionId) { - try { - NotifyRespInd retrieveResponse = new NotifyRespInd(mmsVersion, transactionId, PduHeaders.STATUS_RETRIEVED); - new OutgoingLollipopMmsConnection(getContext()).send(new PduComposer(getContext(), retrieveResponse).make(), subscriptionId); - } catch (UndeliverableMessageException e) { - Log.w(TAG, e); - } catch (InvalidHeaderValueException e) { - Log.w(TAG, e); - } - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/mms/IncomingMmsConnection.java b/app/src/main/java/org/thoughtcrime/securesms/mms/IncomingMmsConnection.java deleted file mode 100644 index 44827068fd..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/mms/IncomingMmsConnection.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.thoughtcrime.securesms.mms; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import com.google.android.mms.pdu_alt.RetrieveConf; - -import java.io.IOException; - -public interface IncomingMmsConnection { - @Nullable - RetrieveConf retrieve(@NonNull String contentLocation, byte[] transactionId, int subscriptionId) throws MmsException, MmsRadioException, ApnUnavailableException, IOException; -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/mms/LegacyMmsConnection.java b/app/src/main/java/org/thoughtcrime/securesms/mms/LegacyMmsConnection.java deleted file mode 100644 index 359c4ef8ba..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/mms/LegacyMmsConnection.java +++ /dev/null @@ -1,314 +0,0 @@ -/** - * 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 - * (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.mms; - -import android.Manifest; -import android.annotation.SuppressLint; -import android.content.Context; -import android.content.pm.PackageManager; -import android.net.ConnectivityManager; -import androidx.annotation.NonNull; -import androidx.core.app.ActivityCompat; -import android.telephony.TelephonyManager; -import android.text.TextUtils; - -import org.session.libsignal.utilities.logging.Log; - -import org.apache.http.Header; -import org.apache.http.auth.AuthScope; -import org.apache.http.auth.UsernamePasswordCredentials; -import org.apache.http.client.CredentialsProvider; -import org.apache.http.client.config.RequestConfig; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.client.methods.HttpUriRequest; -import org.apache.http.impl.NoConnectionReuseStrategyHC4; -import org.apache.http.impl.client.BasicCredentialsProvider; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClients; -import org.apache.http.impl.client.LaxRedirectStrategy; -import org.apache.http.impl.conn.BasicHttpClientConnectionManager; -import org.apache.http.message.BasicHeader; -import org.thoughtcrime.securesms.database.ApnDatabase; -import org.session.libsession.utilities.ServiceUtil; -import org.thoughtcrime.securesms.util.TelephonyUtil; -import org.session.libsignal.libsignal.util.guava.Optional; - -import org.session.libsession.utilities.TextSecurePreferences; -import org.session.libsession.utilities.Util; - -import java.io.BufferedInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.net.InetAddress; -import java.net.URL; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; - -@SuppressWarnings("deprecation") -public abstract class LegacyMmsConnection { - - public static final String USER_AGENT = "Android-Mms/2.0"; - - private static final String TAG = LegacyMmsConnection.class.getSimpleName(); - - protected final Context context; - protected final Apn apn; - - protected LegacyMmsConnection(Context context) throws ApnUnavailableException { - this.context = context; - this.apn = getApn(context); - } - - public static Apn getApn(Context context) throws ApnUnavailableException { - - try { - Optional params = ApnDatabase.getInstance(context) - .getMmsConnectionParameters(TelephonyUtil.getMccMnc(context), - TelephonyUtil.getApn(context)); - - if (!params.isPresent()) { - throw new ApnUnavailableException("No parameters available from ApnDefaults."); - } - - return params.get(); - } catch (IOException ioe) { - throw new ApnUnavailableException("ApnDatabase threw an IOException", ioe); - } - } - - protected boolean isDirectConnect() { - // We think Sprint supports direct connection over wifi/data, but not Verizon - Set sprintMccMncs = new HashSet() {{ - add("312530"); - add("311880"); - add("311870"); - add("311490"); - add("310120"); - add("316010"); - add("312190"); - }}; - - return ServiceUtil.getTelephonyManager(context).getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA && - sprintMccMncs.contains(TelephonyUtil.getMccMnc(context)); - } - - @SuppressWarnings("TryWithIdenticalCatches") - protected static boolean checkRouteToHost(Context context, String host, boolean usingMmsRadio) - throws IOException - { - InetAddress inetAddress = InetAddress.getByName(host); - if (!usingMmsRadio) { - if (inetAddress.isSiteLocalAddress()) { - throw new IOException("RFC1918 address in non-MMS radio situation!"); - } - Log.w(TAG, "returning vacuous success since MMS radio is not in use"); - return true; - } - - if (inetAddress == null) { - throw new IOException("Unable to lookup host: InetAddress.getByName() returned null."); - } - - byte[] ipAddressBytes = inetAddress.getAddress(); - if (ipAddressBytes == null) { - Log.w(TAG, "resolved IP address bytes are null, returning true to attempt a connection anyway."); - return true; - } - - Log.i(TAG, "Checking route to address: " + host + ", " + inetAddress.getHostAddress()); - ConnectivityManager manager = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE); - - try { - final Method requestRouteMethod = manager.getClass().getMethod("requestRouteToHostAddress", Integer.TYPE, InetAddress.class); - final boolean routeToHostObtained = (Boolean) requestRouteMethod.invoke(manager, MmsRadio.TYPE_MOBILE_MMS, inetAddress); - Log.i(TAG, "requestRouteToHostAddress(" + inetAddress + ") -> " + routeToHostObtained); - return routeToHostObtained; - } catch (NoSuchMethodException nsme) { - Log.w(TAG, nsme); - } catch (IllegalAccessException iae) { - Log.w(TAG, iae); - } catch (InvocationTargetException ite) { - Log.w(TAG, ite); - } - - return false; - } - - protected static byte[] parseResponse(InputStream is) throws IOException { - InputStream in = new BufferedInputStream(is); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - Util.copy(in, baos); - - Log.i(TAG, "Received full server response, " + baos.size() + " bytes"); - - return baos.toByteArray(); - } - - protected CloseableHttpClient constructHttpClient() throws IOException { - RequestConfig config = RequestConfig.custom() - .setConnectTimeout(20 * 1000) - .setConnectionRequestTimeout(20 * 1000) - .setSocketTimeout(20 * 1000) - .setMaxRedirects(20) - .build(); - - URL mmsc = new URL(apn.getMmsc()); - CredentialsProvider credsProvider = new BasicCredentialsProvider(); - - if (apn.hasAuthentication()) { - credsProvider.setCredentials(new AuthScope(mmsc.getHost(), mmsc.getPort() > -1 ? mmsc.getPort() : mmsc.getDefaultPort()), - new UsernamePasswordCredentials(apn.getUsername(), apn.getPassword())); - } - - return HttpClients.custom() - .setConnectionReuseStrategy(new NoConnectionReuseStrategyHC4()) - .setRedirectStrategy(new LaxRedirectStrategy()) - .setUserAgent(TextSecurePreferences.getMmsUserAgent(context, USER_AGENT)) - .setConnectionManager(new BasicHttpClientConnectionManager()) - .setDefaultRequestConfig(config) - .setDefaultCredentialsProvider(credsProvider) - .build(); - } - - protected byte[] execute(HttpUriRequest request) throws IOException { - Log.i(TAG, "connecting to " + apn.getMmsc()); - - CloseableHttpClient client = null; - CloseableHttpResponse response = null; - try { - client = constructHttpClient(); - response = client.execute(request); - - Log.i(TAG, "* response code: " + response.getStatusLine()); - - if (response.getStatusLine().getStatusCode() == 200) { - return parseResponse(response.getEntity().getContent()); - } - } catch (NullPointerException npe) { - // TODO determine root cause - // see: https://github.com/signalapp/Signal-Android/issues/4379 - throw new IOException(npe); - } finally { - if (response != null) response.close(); - if (client != null) client.close(); - } - - throw new IOException("unhandled response code"); - } - - protected List
getBaseHeaders() { - final String number = getLine1Number(context); - - return new LinkedList
() {{ - add(new BasicHeader("Accept", "*/*, application/vnd.wap.mms-message, application/vnd.wap.sic")); - add(new BasicHeader("x-wap-profile", "http://www.google.com/oha/rdf/ua-profile-kila.xml")); - add(new BasicHeader("Content-Type", "application/vnd.wap.mms-message")); - add(new BasicHeader("x-carrier-magic", "http://magic.google.com")); - if (!TextUtils.isEmpty(number)) { - add(new BasicHeader("x-up-calling-line-id", number)); - add(new BasicHeader("X-MDN", number)); - } - }}; - } - - @SuppressLint("HardwareIds") - private static String getLine1Number(@NonNull Context context) { - if (ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_SMS) == PackageManager.PERMISSION_GRANTED || - ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_NUMBERS) == PackageManager.PERMISSION_GRANTED || - ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) { - return TelephonyUtil.getManager(context).getLine1Number(); - } else { - return ""; - } - } - - public static class Apn { - - public static Apn EMPTY = new Apn("", "", "", "", ""); - - private final String mmsc; - private final String proxy; - private final String port; - private final String username; - private final String password; - - public Apn(String mmsc, String proxy, String port, String username, String password) { - this.mmsc = mmsc; - this.proxy = proxy; - this.port = port; - this.username = username; - this.password = password; - } - - public Apn(Apn customApn, Apn defaultApn, - boolean useCustomMmsc, - boolean useCustomProxy, - boolean useCustomProxyPort, - boolean useCustomUsername, - boolean useCustomPassword) - { - this.mmsc = useCustomMmsc ? customApn.mmsc : defaultApn.mmsc; - this.proxy = useCustomProxy ? customApn.proxy : defaultApn.proxy; - this.port = useCustomProxyPort ? customApn.port : defaultApn.port; - this.username = useCustomUsername ? customApn.username : defaultApn.username; - this.password = useCustomPassword ? customApn.password : defaultApn.password; - } - - public boolean hasProxy() { - return !TextUtils.isEmpty(proxy); - } - - public String getMmsc() { - return mmsc; - } - - public String getProxy() { - return hasProxy() ? proxy : null; - } - - public int getPort() { - return TextUtils.isEmpty(port) ? 80 : Integer.parseInt(port); - } - - public boolean hasAuthentication() { - return !TextUtils.isEmpty(username); - } - - public String getUsername() { - return username; - } - - public String getPassword() { - return password; - } - - @Override - public @NonNull String toString() { - return Apn.class.getSimpleName() + - "{ mmsc: \"" + mmsc + "\"" + - ", proxy: " + (proxy == null ? "none" : '"' + proxy + '"') + - ", port: " + (port == null ? "(none)" : port) + - ", user: " + (username == null ? "none" : '"' + username + '"') + - ", pass: " + (password == null ? "none" : '"' + password + '"') + " }"; - } - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/mms/LollipopMmsConnection.java b/app/src/main/java/org/thoughtcrime/securesms/mms/LollipopMmsConnection.java deleted file mode 100644 index bf9456782b..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/mms/LollipopMmsConnection.java +++ /dev/null @@ -1,86 +0,0 @@ -/** - * Copyright (C) 2015 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.mms; - -import android.app.PendingIntent; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; - -import org.session.libsignal.utilities.logging.Log; -import org.session.libsession.utilities.Util; - -import java.util.concurrent.TimeoutException; - -public abstract class LollipopMmsConnection extends BroadcastReceiver { - private static final String TAG = LollipopMmsConnection.class.getSimpleName(); - - private final Context context; - private final String action; - - private boolean resultAvailable; - - public abstract void onResult(Context context, Intent intent); - - protected LollipopMmsConnection(Context context, String action) { - super(); - this.context = context; - this.action = action; - } - - @Override - public synchronized void onReceive(Context context, Intent intent) { - Log.i(TAG, "onReceive()"); - if (!action.equals(intent.getAction())) { - Log.w(TAG, "received broadcast with unexpected action " + intent.getAction()); - return; - } - - onResult(context, intent); - - resultAvailable = true; - notifyAll(); - } - - protected void beginTransaction() { - getContext().getApplicationContext().registerReceiver(this, new IntentFilter(action)); - } - - protected void endTransaction() { - getContext().getApplicationContext().unregisterReceiver(this); - resultAvailable = false; - } - - protected void waitForResult() throws TimeoutException { - long timeoutExpiration = System.currentTimeMillis() + 60000; - while (!resultAvailable) { - Util.wait(this, Math.max(1, timeoutExpiration - System.currentTimeMillis())); - if (System.currentTimeMillis() >= timeoutExpiration) { - throw new TimeoutException("timeout when waiting for MMS"); - } - } - } - - protected PendingIntent getPendingIntent() { - return PendingIntent.getBroadcast(getContext(), 1, new Intent(action), PendingIntent.FLAG_ONE_SHOT); - } - - protected Context getContext() { - return context; - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/mms/OutgoingLollipopMmsConnection.java b/app/src/main/java/org/thoughtcrime/securesms/mms/OutgoingLollipopMmsConnection.java deleted file mode 100644 index fa851c2a09..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/mms/OutgoingLollipopMmsConnection.java +++ /dev/null @@ -1,115 +0,0 @@ -/** - * Copyright (C) 2015 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.mms; - -import android.annotation.TargetApi; -import android.content.Context; -import android.content.Intent; -import android.os.Build.VERSION; -import android.os.Build.VERSION_CODES; -import android.os.Bundle; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import android.telephony.SmsManager; -import org.session.libsignal.utilities.logging.Log; - -import com.android.mms.service_alt.MmsConfig; -import com.google.android.mms.pdu_alt.PduParser; -import com.google.android.mms.pdu_alt.SendConf; - -import org.thoughtcrime.securesms.providers.MmsBodyProvider; -import org.thoughtcrime.securesms.transport.UndeliverableMessageException; - -import org.session.libsession.utilities.Util; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.util.concurrent.TimeoutException; - -public class OutgoingLollipopMmsConnection extends LollipopMmsConnection implements OutgoingMmsConnection { - private static final String TAG = OutgoingLollipopMmsConnection.class.getSimpleName(); - private static final String ACTION = OutgoingLollipopMmsConnection.class.getCanonicalName() + "MMS_SENT_ACTION"; - - private byte[] response; - - public OutgoingLollipopMmsConnection(Context context) { - super(context, ACTION); - } - - @TargetApi(VERSION_CODES.LOLLIPOP_MR1) - @Override - public synchronized void onResult(Context context, Intent intent) { - if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP_MR1) { - Log.i(TAG, "HTTP status: " + intent.getIntExtra(SmsManager.EXTRA_MMS_HTTP_STATUS, -1)); - } - - response = intent.getByteArrayExtra(SmsManager.EXTRA_MMS_DATA); - } - - @Override - @TargetApi(VERSION_CODES.LOLLIPOP) - public @Nullable synchronized SendConf send(@NonNull byte[] pduBytes, int subscriptionId) - throws UndeliverableMessageException - { - beginTransaction(); - try { - MmsBodyProvider.Pointer pointer = MmsBodyProvider.makeTemporaryPointer(getContext()); - Util.copy(new ByteArrayInputStream(pduBytes), pointer.getOutputStream()); - - SmsManager smsManager; - - if (VERSION.SDK_INT >= 22 && subscriptionId != -1) { - smsManager = SmsManager.getSmsManagerForSubscriptionId(subscriptionId); - } else { - smsManager = SmsManager.getDefault(); - } - - Bundle configOverrides = new Bundle(); - configOverrides.putBoolean(SmsManager.MMS_CONFIG_GROUP_MMS_ENABLED, true); - - MmsConfig mmsConfig = MmsConfigManager.getMmsConfig(getContext(), subscriptionId); - - if (mmsConfig != null) { - MmsConfig.Overridden overridden = new MmsConfig.Overridden(mmsConfig, new Bundle()); - configOverrides.putString(SmsManager.MMS_CONFIG_HTTP_PARAMS, overridden.getHttpParams()); - configOverrides.putInt(SmsManager.MMS_CONFIG_MAX_MESSAGE_SIZE, overridden.getMaxMessageSize()); - } - - smsManager.sendMultimediaMessage(getContext(), - pointer.getUri(), - null, - configOverrides, - getPendingIntent()); - - waitForResult(); - - Log.i(TAG, "MMS broadcast received and processed."); - pointer.close(); - - if (response == null) { - throw new UndeliverableMessageException("Null response."); - } - - return (SendConf) new PduParser(response).parse(); - } catch (IOException | TimeoutException e) { - throw new UndeliverableMessageException(e); - } finally { - endTransaction(); - } - } -} - diff --git a/app/src/main/java/org/thoughtcrime/securesms/mms/OutgoingMmsConnection.java b/app/src/main/java/org/thoughtcrime/securesms/mms/OutgoingMmsConnection.java deleted file mode 100644 index 6f4b0cea89..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/mms/OutgoingMmsConnection.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.thoughtcrime.securesms.mms; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import com.google.android.mms.pdu_alt.SendConf; - -import org.thoughtcrime.securesms.transport.UndeliverableMessageException; - - -public interface OutgoingMmsConnection { - @Nullable - SendConf send(@NonNull byte[] pduBytes, int subscriptionId) throws UndeliverableMessageException; -}