Search in sources :

Example 1 with RetrieveConf

use of com.google.android.mms.pdu_alt.RetrieveConf in project Signal-Android by signalapp.

the class IncomingLegacyMmsConnection method retrieve.

public RetrieveConf retrieve(Apn contentApn, byte[] transactionId, boolean usingMmsRadio, boolean useProxyIfAvailable) throws IOException, ApnUnavailableException {
    byte[] pdu = null;
    final boolean useProxy = useProxyIfAvailable && contentApn.hasProxy();
    final String targetHost = useProxy ? contentApn.getProxy() : Uri.parse(contentApn.getMmsc()).getHost();
    if (checkRouteToHost(context, targetHost, usingMmsRadio)) {
        Log.w(TAG, "got successful route to host " + targetHost);
        pdu = execute(constructRequest(contentApn, useProxy));
    }
    if (pdu == null) {
        throw new IOException("Connection manager could not obtain route to host.");
    }
    RetrieveConf retrieved = (RetrieveConf) new PduParser(pdu).parse();
    if (retrieved == null) {
        Log.w(TAG, "Couldn't parse PDU, byte response: " + Arrays.toString(pdu));
        Log.w(TAG, "Couldn't parse PDU, ASCII:         " + new String(pdu));
        throw new IOException("Bad retrieved PDU");
    }
    sendRetrievedAcknowledgement(transactionId, usingMmsRadio, useProxy);
    return retrieved;
}
Also used : PduParser(com.google.android.mms.pdu_alt.PduParser) IOException(java.io.IOException) RetrieveConf(com.google.android.mms.pdu_alt.RetrieveConf)

Example 2 with RetrieveConf

use of com.google.android.mms.pdu_alt.RetrieveConf in project Signal-Android by signalapp.

the class IncomingLollipopMmsConnection method retrieve.

@Override
@TargetApi(VERSION_CODES.LOLLIPOP)
@Nullable
public synchronized RetrieveConf retrieve(@NonNull String contentLocation, byte[] transactionId, int subscriptionId) throws MmsException {
    beginTransaction();
    try {
        MmsBodyProvider.Pointer pointer = MmsBodyProvider.makeTemporaryPointer(getContext());
        Log.w(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();
        // + Hex.dump(baos.toByteArray()));
        Log.w(TAG, baos.size() + "-byte response: ");
        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();
    }
}
Also used : MmsBodyProvider(org.thoughtcrime.securesms.providers.MmsBodyProvider) PduParser(com.google.android.mms.pdu_alt.PduParser) ByteArrayOutputStream(java.io.ByteArrayOutputStream) IOException(java.io.IOException) RetrieveConf(com.google.android.mms.pdu_alt.RetrieveConf) SmsManager(android.telephony.SmsManager) TimeoutException(java.util.concurrent.TimeoutException) TargetApi(android.annotation.TargetApi) Nullable(android.support.annotation.Nullable)

Example 3 with RetrieveConf

use of com.google.android.mms.pdu_alt.RetrieveConf in project Signal-Android by signalapp.

the class MmsDownloadJob method onRun.

@Override
public void onRun(MasterSecret masterSecret) {
    MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
    Optional<MmsDatabase.MmsNotificationInfo> notification = database.getNotification(messageId);
    if (!notification.isPresent()) {
        Log.w(TAG, "No notification for ID: " + messageId);
        return;
    }
    try {
        if (notification.get().getContentLocation() == null) {
            throw new MmsException("Notification content location was null.");
        }
        if (!TextSecurePreferences.isPushRegistered(context)) {
            throw new MmsException("Not registered");
        }
        database.markDownloadState(messageId, MmsDatabase.Status.DOWNLOAD_CONNECTING);
        String contentLocation = notification.get().getContentLocation();
        byte[] transactionId = new byte[0];
        try {
            if (notification.get().getTransactionId() != null) {
                transactionId = notification.get().getTransactionId().getBytes(CharacterSets.MIMENAME_ISO_8859_1);
            } else {
                Log.w(TAG, "No transaction ID!");
            }
        } catch (UnsupportedEncodingException e) {
            Log.w(TAG, e);
        }
        Log.w(TAG, "Downloading mms at " + Uri.parse(contentLocation).getHost() + ", subscription ID: " + notification.get().getSubscriptionId());
        RetrieveConf retrieveConf = new CompatMmsConnection(context).retrieve(contentLocation, transactionId, notification.get().getSubscriptionId());
        if (retrieveConf == null) {
            throw new MmsException("RetrieveConf was null");
        }
        storeRetrievedMms(contentLocation, messageId, threadId, retrieveConf, notification.get().getSubscriptionId(), notification.get().getFrom());
    } catch (ApnUnavailableException e) {
        Log.w(TAG, e);
        handleDownloadError(messageId, threadId, MmsDatabase.Status.DOWNLOAD_APN_UNAVAILABLE, automatic);
    } catch (MmsException e) {
        Log.w(TAG, e);
        handleDownloadError(messageId, threadId, MmsDatabase.Status.DOWNLOAD_HARD_FAILURE, automatic);
    } catch (MmsRadioException | IOException e) {
        Log.w(TAG, e);
        handleDownloadError(messageId, threadId, MmsDatabase.Status.DOWNLOAD_SOFT_FAILURE, automatic);
    } catch (DuplicateMessageException e) {
        Log.w(TAG, e);
        database.markAsDecryptDuplicate(messageId, threadId);
    } catch (LegacyMessageException e) {
        Log.w(TAG, e);
        database.markAsLegacyVersion(messageId, threadId);
    } catch (NoSessionException e) {
        Log.w(TAG, e);
        database.markAsNoSession(messageId, threadId);
    } catch (InvalidMessageException e) {
        Log.w(TAG, e);
        database.markAsDecryptFailed(messageId, threadId);
    }
}
Also used : InvalidMessageException(org.whispersystems.libsignal.InvalidMessageException) UnsupportedEncodingException(java.io.UnsupportedEncodingException) IOException(java.io.IOException) NoSessionException(org.whispersystems.libsignal.NoSessionException) CompatMmsConnection(org.thoughtcrime.securesms.mms.CompatMmsConnection) MmsException(org.thoughtcrime.securesms.mms.MmsException) ApnUnavailableException(org.thoughtcrime.securesms.mms.ApnUnavailableException) DuplicateMessageException(org.whispersystems.libsignal.DuplicateMessageException) MmsRadioException(org.thoughtcrime.securesms.mms.MmsRadioException) LegacyMessageException(org.whispersystems.libsignal.LegacyMessageException) MmsDatabase(org.thoughtcrime.securesms.database.MmsDatabase) RetrieveConf(com.google.android.mms.pdu_alt.RetrieveConf)

Example 4 with RetrieveConf

use of com.google.android.mms.pdu_alt.RetrieveConf in project Signal-Android by WhisperSystems.

the class IncomingLollipopMmsConnection method retrieve.

@Override
@TargetApi(VERSION_CODES.LOLLIPOP)
@Nullable
public synchronized RetrieveConf retrieve(@NonNull String contentLocation, byte[] transactionId, int subscriptionId) throws MmsException {
    beginTransaction();
    try {
        MmsBodyProvider.Pointer pointer = MmsBodyProvider.makeTemporaryPointer(getContext());
        final String transactionIdString = Util.toIsoString(transactionId);
        Log.i(TAG, String.format(Locale.ENGLISH, "Downloading subscriptionId=%s multimedia from '%s' [transactionId='%s'] to '%s'", subscriptionId, contentLocation, transactionIdString, pointer.getUri()));
        SmsManager smsManager;
        if (VERSION.SDK_INT >= 22 && subscriptionId != -1) {
            smsManager = SmsManager.getSmsManagerForSubscriptionId(subscriptionId);
        } else {
            smsManager = SmsManager.getDefault();
        }
        final Bundle configOverrides = smsManager.getCarrierConfigValues();
        if (configOverrides.getBoolean(SmsManager.MMS_CONFIG_APPEND_TRANSACTION_ID)) {
            if (!contentLocation.contains(transactionIdString)) {
                Log.i(TAG, "Appending transactionId to contentLocation at the direction of CarrierConfigValues. New location: " + contentLocation);
                contentLocation += transactionIdString;
            } else {
                Log.i(TAG, "Skipping 'append transaction id' as contentLocation already contains it");
            }
        }
        if (TextUtils.isEmpty(configOverrides.getString(SmsManager.MMS_CONFIG_USER_AGENT))) {
            configOverrides.remove(SmsManager.MMS_CONFIG_USER_AGENT);
        }
        if (TextUtils.isEmpty(configOverrides.getString(SmsManager.MMS_CONFIG_UA_PROF_URL))) {
            configOverrides.remove(SmsManager.MMS_CONFIG_UA_PROF_URL);
        }
        smsManager.downloadMultimediaMessage(getContext(), contentLocation, pointer.getUri(), configOverrides, getPendingIntent());
        waitForResult();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        StreamUtil.copy(pointer.getInputStream(), baos);
        pointer.close();
        // + Hex.dump(baos.toByteArray()));
        Log.i(TAG, baos.size() + "-byte response: ");
        Bundle configValues = smsManager.getCarrierConfigValues();
        boolean parseContentDisposition = configValues.getBoolean(SmsManager.MMS_CONFIG_SUPPORT_MMS_CONTENT_DISPOSITION);
        RetrieveConf retrieved;
        try {
            retrieved = (RetrieveConf) new PduParser(baos.toByteArray(), parseContentDisposition).parse();
        } catch (NullPointerException e) {
            Log.w(TAG, "Badly formatted MMS message caused the parser to fail.", e);
            throw new MmsException(e);
        }
        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();
    }
}
Also used : MmsBodyProvider(org.thoughtcrime.securesms.providers.MmsBodyProvider) PduParser(com.google.android.mms.pdu_alt.PduParser) Bundle(android.os.Bundle) ByteArrayOutputStream(java.io.ByteArrayOutputStream) IOException(java.io.IOException) SmsManager(android.telephony.SmsManager) RetrieveConf(com.google.android.mms.pdu_alt.RetrieveConf) TimeoutException(java.util.concurrent.TimeoutException) TargetApi(android.annotation.TargetApi) Nullable(androidx.annotation.Nullable)

Example 5 with RetrieveConf

use of com.google.android.mms.pdu_alt.RetrieveConf in project qksms by moezbhatti.

the class RetrieveTransaction method run.

public void run() {
    // } else {
    try {
        // Change the downloading state of the M-Notification.ind.
        DownloadManager.init(mContext.getApplicationContext());
        DownloadManager.getInstance().markState(mUri, DownloadManager.STATE_DOWNLOADING);
        // Send GET request to MMSC and retrieve the response data.
        byte[] resp = getPdu(mContentLocation);
        // Parse M-Retrieve.conf
        RetrieveConf retrieveConf = (RetrieveConf) new PduParser(resp).parse();
        if (null == retrieveConf) {
            throw new MmsException("Invalid M-Retrieve.conf PDU.");
        }
        Uri msgUri = null;
        if (isDuplicateMessage(mContext, retrieveConf)) {
            // Mark this transaction as failed to prevent duplicate
            // notification to user.
            mTransactionState.setState(TransactionState.FAILED);
            mTransactionState.setContentUri(mUri);
        } else {
            // Store M-Retrieve.conf into Inbox
            PduPersister persister = PduPersister.getPduPersister(mContext);
            msgUri = persister.persist(retrieveConf, Inbox.CONTENT_URI, PduPersister.DUMMY_THREAD_ID, true, true, null);
            // Use local time instead of PDU time
            ContentValues values = new ContentValues(3);
            values.put(Mms.DATE, System.currentTimeMillis() / 1000L);
            try {
                values.put(Mms.DATE_SENT, retrieveConf.getDate());
            } catch (Exception ignored) {
            }
            values.put(Mms.MESSAGE_SIZE, resp.length);
            SqliteWrapper.update(mContext, mContext.getContentResolver(), msgUri, values, null, null);
            // The M-Retrieve.conf has been successfully downloaded.
            mTransactionState.setState(TransactionState.SUCCESS);
            mTransactionState.setContentUri(msgUri);
            // Remember the location the message was downloaded from.
            // Since it's not critical, it won't fail the transaction.
            // Copy over the locked flag from the M-Notification.ind in case
            // the user locked the message before activating the download.
            updateContentLocation(mContext, msgUri, mContentLocation, mLocked);
        }
        // Delete the corresponding M-Notification.ind.
        SqliteWrapper.delete(mContext, mContext.getContentResolver(), mUri, null, null);
        // Send ACK to the Proxy-Relay to indicate we have fetched the
        // MM successfully.
        // Don't mark the transaction as failed if we failed to send it.
        sendAcknowledgeInd(retrieveConf);
    } catch (Throwable t) {
        Timber.e(t, "error");
        if ("HTTP error: Not Found".equals(t.getMessage())) {
            // Delete the expired M-Notification.ind.
            SqliteWrapper.delete(mContext, mContext.getContentResolver(), mUri, null, null);
        }
    } finally {
        if (mTransactionState.getState() != TransactionState.SUCCESS) {
            mTransactionState.setState(TransactionState.FAILED);
            mTransactionState.setContentUri(mUri);
            Timber.e("Retrieval failed.");
        }
        notifyObservers();
    }
// }
}
Also used : ContentValues(android.content.ContentValues) PduParser(com.google.android.mms.pdu_alt.PduParser) MmsException(com.google.android.mms.MmsException) PduPersister(com.google.android.mms.pdu_alt.PduPersister) Uri(android.net.Uri) RetrieveConf(com.google.android.mms.pdu_alt.RetrieveConf) MmsException(com.google.android.mms.MmsException) IOException(java.io.IOException)

Aggregations

RetrieveConf (com.google.android.mms.pdu_alt.RetrieveConf)11 PduParser (com.google.android.mms.pdu_alt.PduParser)8 IOException (java.io.IOException)8 MmsException (com.google.android.mms.MmsException)5 Uri (android.net.Uri)4 ContentValues (android.content.ContentValues)3 GenericPdu (com.google.android.mms.pdu_alt.GenericPdu)3 PduPersister (com.google.android.mms.pdu_alt.PduPersister)3 TargetApi (android.annotation.TargetApi)2 SmsManager (android.telephony.SmsManager)2 ByteArrayOutputStream (java.io.ByteArrayOutputStream)2 UnsupportedEncodingException (java.io.UnsupportedEncodingException)2 TimeoutException (java.util.concurrent.TimeoutException)2 ApnUnavailableException (org.thoughtcrime.securesms.mms.ApnUnavailableException)2 CompatMmsConnection (org.thoughtcrime.securesms.mms.CompatMmsConnection)2 MmsException (org.thoughtcrime.securesms.mms.MmsException)2 MmsRadioException (org.thoughtcrime.securesms.mms.MmsRadioException)2 MmsBodyProvider (org.thoughtcrime.securesms.providers.MmsBodyProvider)2 Intent (android.content.Intent)1 Resources (android.content.res.Resources)1