예제 #1
0
 private void deliver(MasterSecret masterSecret, SmsMessageRecord message)
     throws UndeliverableMessageException, InsecureFallbackApprovalException {
   if (message.isSecure() || message.isKeyExchange() || message.isEndSession()) {
     deliverSecureMessage(masterSecret, message);
   } else {
     deliverPlaintextMessage(message);
   }
 }
예제 #2
0
  private void deliverPlaintextMessage(SmsMessageRecord message)
      throws UndeliverableMessageException {
    String recipient = message.getIndividualRecipient().getNumber();

    // See issue #1516 for bug report, and discussion on commits related to #4833 for problems
    // related to the original fix to #1516. This still may not be a correct fix if networks allow
    // SMS/MMS sending to alphanumeric recipients other than email addresses, but should also
    // help to fix issue #3099.
    if (!NumberUtil.isValidEmail(recipient)) {
      recipient =
          PhoneNumberUtils.stripSeparators(
              PhoneNumberUtils.convertKeypadLettersToDigits(recipient));
    }

    if (!NumberUtil.isValidSmsOrEmail(recipient)) {
      throw new UndeliverableMessageException("Not a valid SMS destination! " + recipient);
    }

    ArrayList<String> messages = SmsManager.getDefault().divideMessage(message.getBody().getBody());
    ArrayList<PendingIntent> sentIntents =
        constructSentIntents(message.getId(), message.getType(), messages, false);
    ArrayList<PendingIntent> deliveredIntents =
        constructDeliveredIntents(message.getId(), message.getType(), messages);

    // NOTE 11/04/14 -- There's apparently a bug where for some unknown recipients
    // and messages, this will throw an NPE.  We have no idea why, so we're just
    // catching it and marking the message as a failure.  That way at least it doesn't
    // repeatedly crash every time you start the app.
    try {
      getSmsManagerFor(message.getSubscriptionId())
          .sendMultipartTextMessage(recipient, null, messages, sentIntents, deliveredIntents);
    } catch (NullPointerException npe) {
      Log.w(TAG, npe);
      Log.w(TAG, "Recipient: " + recipient);
      Log.w(TAG, "Message Parts: " + messages.size());

      try {
        for (int i = 0; i < messages.size(); i++) {
          getSmsManagerFor(message.getSubscriptionId())
              .sendTextMessage(
                  recipient,
                  null,
                  messages.get(i),
                  sentIntents.get(i),
                  deliveredIntents == null ? null : deliveredIntents.get(i));
        }
      } catch (NullPointerException npe2) {
        Log.w(TAG, npe);
        throw new UndeliverableMessageException(npe2);
      }
    }
  }
예제 #3
0
  private void deliverSecureMessage(MasterSecret masterSecret, SmsMessageRecord message)
      throws UndeliverableMessageException, InsecureFallbackApprovalException {
    MultipartSmsMessageHandler multipartMessageHandler = new MultipartSmsMessageHandler();
    OutgoingTextMessage transportMessage = OutgoingTextMessage.from(message);

    if (message.isSecure() || message.isEndSession()) {
      transportMessage = getAsymmetricEncrypt(masterSecret, transportMessage);
    }

    ArrayList<String> messages = multipartMessageHandler.divideMessage(transportMessage);
    ArrayList<PendingIntent> sentIntents =
        constructSentIntents(message.getId(), message.getType(), messages, message.isSecure());
    ArrayList<PendingIntent> deliveredIntents =
        constructDeliveredIntents(message.getId(), message.getType(), messages);

    Log.w("SmsTransport", "Secure divide into message parts: " + messages.size());

    for (int i = 0; i < messages.size(); i++) {
      // NOTE 11/04/14 -- There's apparently a bug where for some unknown recipients
      // and messages, this will throw an NPE.  We have no idea why, so we're just
      // catching it and marking the message as a failure.  That way at least it
      // doesn't repeatedly crash every time you start the app.
      try {
        SmsManager.getDefault()
            .sendTextMessage(
                message.getIndividualRecipient().getNumber(),
                null,
                messages.get(i),
                sentIntents.get(i),
                deliveredIntents == null ? null : deliveredIntents.get(i));
      } catch (NullPointerException npe) {
        Log.w(TAG, npe);
        Log.w(TAG, "Recipient: " + message.getIndividualRecipient().getNumber());
        Log.w(TAG, "Message Total Parts/Current: " + messages.size() + "/" + i);
        Log.w(TAG, "Message Part Length: " + messages.get(i).getBytes().length);
        throw new UndeliverableMessageException(npe);
      } catch (IllegalArgumentException iae) {
        Log.w(TAG, iae);
        throw new UndeliverableMessageException(iae);
      }
    }
  }
예제 #4
0
  @Override
  public void onSend(MasterSecret masterSecret) throws NoSuchMessageException {
    EncryptingSmsDatabase database = DatabaseFactory.getEncryptingSmsDatabase(context);
    SmsMessageRecord record = database.getMessage(masterSecret, messageId);

    try {
      Log.w(TAG, "Sending message: " + messageId);

      deliver(masterSecret, record);
    } catch (UndeliverableMessageException ude) {
      Log.w(TAG, ude);
      DatabaseFactory.getSmsDatabase(context).markAsSentFailed(record.getId());
      MessageNotifier.notifyMessageDeliveryFailed(
          context, record.getRecipients(), record.getThreadId());
    } catch (InsecureFallbackApprovalException ifae) {
      Log.w(TAG, ifae);
      DatabaseFactory.getSmsDatabase(context).markAsPendingInsecureSmsFallback(record.getId());
      MessageNotifier.notifyMessageDeliveryFailed(
          context, record.getRecipients(), record.getThreadId());
    }
  }
예제 #5
0
 public static OutgoingTextMessage from(SmsMessageRecord record) {
   if (record.isSecure()) {
     return new OutgoingEncryptedMessage(
         record.getIndividualRecipient(), record.getBody().getBody());
   } else if (record.isKeyExchange()) {
     return new OutgoingKeyExchangeMessage(
         record.getIndividualRecipient(), record.getBody().getBody());
   } else if (record.isEndSession()) {
     return new OutgoingEndSessionMessage(
         new OutgoingTextMessage(record.getIndividualRecipient(), record.getBody().getBody()));
   } else {
     return new OutgoingTextMessage(record.getIndividualRecipient(), record.getBody().getBody());
   }
 }