@Override public void onSend(MasterSecret masterSecret) throws MmsException, IOException, NoSuchMessageException { MmsDatabase database = DatabaseFactory.getMmsDatabase(context); SendReq message = database.getOutgoingMessage(masterSecret, messageId); try { deliver(masterSecret, message); database.markAsPush(messageId); database.markAsSecure(messageId); database.markAsSent(messageId, "push".getBytes(), 0); } catch (InvalidNumberException | RecipientFormattingException e) { Log.w(TAG, e); database.markAsSentFailed(messageId); notifyMediaMessageDeliveryFailed(context, messageId); } catch (EncapsulatedExceptions e) { Log.w(TAG, e); if (!e.getUnregisteredUserExceptions().isEmpty()) { database.markAsSentFailed(messageId); } for (UntrustedIdentityException uie : e.getUntrustedIdentityExceptions()) { IncomingIdentityUpdateMessage identityUpdateMessage = IncomingIdentityUpdateMessage.createFor( message.getTo()[0].getString(), uie.getIdentityKey()); DatabaseFactory.getEncryptingSmsDatabase(context) .insertMessageInbox(masterSecret, identityUpdateMessage); database.markAsSentFailed(messageId); } notifyMediaMessageDeliveryFailed(context, messageId); } }
public ExpiringMessageManager(Context context) { this.context = context.getApplicationContext(); this.smsDatabase = DatabaseFactory.getSmsDatabase(context); this.mmsDatabase = DatabaseFactory.getMmsDatabase(context); executor.execute(new LoadTask()); executor.execute(new ProcessTask()); }
private void handleSentResult(MasterSecret masterSecret, long messageId, int result) { try { EncryptingSmsDatabase database = DatabaseFactory.getEncryptingSmsDatabase(context); SmsMessageRecord record = database.getMessage(masterSecret, messageId); switch (result) { case Activity.RESULT_OK: database.markAsSent(messageId); if (record != null && record.isEndSession()) { Log.w(TAG, "Ending session..."); SessionStore sessionStore = new TextSecureSessionStore(context, masterSecret); sessionStore.deleteAllSessions(record.getIndividualRecipient().getRecipientId()); SecurityEvent.broadcastSecurityUpdateEvent(context, record.getThreadId()); } break; case SmsManager.RESULT_ERROR_NO_SERVICE: case SmsManager.RESULT_ERROR_RADIO_OFF: Log.w(TAG, "Service connectivity problem, requeuing..."); ApplicationContext.getInstance(context) .getJobManager() .add(new SmsSendJob(context, messageId, record.getIndividualRecipient().getNumber())); break; default: database.markAsSentFailed(messageId); MessageNotifier.notifyMessageDeliveryFailed( context, record.getRecipients(), record.getThreadId()); } } catch (NoSuchMessageException e) { Log.w(TAG, e); } }
public void onClick(View v) { if (identityName.getText() == null || identityName.getText().toString().trim().length() == 0) { Toast.makeText( SaveIdentityActivity.this, "You must specify a name for this identity!", Toast.LENGTH_LONG) .show(); return; } try { DatabaseFactory.getIdentityDatabase(SaveIdentityActivity.this) .saveIdentity(masterSecret, identityKey, identityName.getText().toString()); } catch (InvalidKeyException e) { AlertDialog.Builder builder = new AlertDialog.Builder(SaveIdentityActivity.this); builder.setTitle("Identity Name Exists!"); builder.setMessage("An identity key with the specified name already exists."); builder.setPositiveButton( "Manage Identities", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { Intent intent = new Intent(SaveIdentityActivity.this, ReviewIdentitiesActivity.class); intent.putExtra("master_secret", masterSecret); startActivity(intent); } }); builder.setNegativeButton("Cancel", null); builder.show(); return; } finish(); }
private void handleCommonRegistration( MasterSecret masterSecret, TextSecureAccountManager accountManager, String number) throws IOException { setState(new RegistrationState(RegistrationState.STATE_GENERATING_KEYS, number)); Recipient self = RecipientFactory.getRecipientsFromString(this, number, false).getPrimaryRecipient(); IdentityKeyPair identityKey = IdentityKeyUtil.getIdentityKeyPair(this, masterSecret); List<PreKeyRecord> records = PreKeyUtil.generatePreKeys(this, masterSecret); PreKeyRecord lastResort = PreKeyUtil.generateLastResortKey(this, masterSecret); SignedPreKeyRecord signedPreKey = PreKeyUtil.generateSignedPreKey(this, masterSecret, identityKey); accountManager.setPreKeys(identityKey.getPublicKey(), lastResort, signedPreKey, records); setState(new RegistrationState(RegistrationState.STATE_GCM_REGISTERING, number)); String gcmRegistrationId = ""; accountManager.setGcmId(Optional.of(gcmRegistrationId)); TextSecurePreferences.setGcmRegistrationId(this, gcmRegistrationId); TextSecurePreferences.setWebsocketRegistered(this, true); DatabaseFactory.getIdentityDatabase(this) .saveIdentity(masterSecret, self.getRecipientId(), identityKey.getPublicKey()); DirectoryHelper.refreshDirectory(this, accountManager, number); DirectoryRefreshListener.schedule(this); }
private @NonNull RecipientDetails getIndividualRecipientDetails( Context context, long recipientId, String number) { Optional<RecipientsPreferences> preferences = DatabaseFactory.getRecipientPreferenceDatabase(context) .getRecipientsPreferences(new long[] {recipientId}); MaterialColor color = preferences.isPresent() ? preferences.get().getColor() : null; Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(number)); Cursor cursor = context.getContentResolver().query(uri, CALLER_ID_PROJECTION, null, null, null); try { if (cursor != null && cursor.moveToFirst()) { Uri contactUri = Contacts.getLookupUri(cursor.getLong(2), cursor.getString(1)); String name = cursor.getString(3).equals(cursor.getString(0)) ? null : cursor.getString(0); ContactPhoto contactPhoto = ContactPhotoFactory.getContactPhoto( context, Uri.withAppendedPath(Contacts.CONTENT_URI, cursor.getLong(2) + ""), name); return new RecipientDetails( cursor.getString(0), cursor.getString(3), contactUri, contactPhoto, color); } } finally { if (cursor != null) cursor.close(); } return new RecipientDetails( null, number, null, ContactPhotoFactory.getDefaultContactPhoto(null), color); }
private void handleSentMessage(Intent intent) { long messageId = intent.getLongExtra("message_id", -1); int result = intent.getIntExtra("ResultCode", -31337); boolean upgraded = intent.getBooleanExtra("upgraded", false); boolean push = intent.getBooleanExtra("push", false); Log.w("SMSReceiverService", "Intent resultcode: " + result); Log.w("SMSReceiverService", "Running sent callback: " + messageId); if (result == Activity.RESULT_OK) { SmsDatabase database = DatabaseFactory.getSmsDatabase(context); Cursor cursor = database.getMessage(messageId); SmsDatabase.Reader reader = database.readerFor(cursor); database.markAsSent(messageId); if (upgraded) database.markAsSecure(messageId); if (push) database.markAsPush(messageId); SmsMessageRecord record = reader.getNext(); if (record != null && record.isEndSession()) { Log.w("SmsSender", "Ending session..."); Session.abortSessionFor(context, record.getIndividualRecipient()); KeyExchangeProcessor.broadcastSecurityUpdateEvent(context, record.getThreadId()); } unregisterForRadioChanges(); } else if (result == SmsManager.RESULT_ERROR_NO_SERVICE || result == SmsManager.RESULT_ERROR_RADIO_OFF) { DatabaseFactory.getSmsDatabase(context).markAsOutbox(messageId); toastHandler .obtainMessage( 0, context.getString(R.string.SmsReceiver_currently_unable_to_send_your_sms_message)) .sendToTarget(); registerForRadioChanges(); } else { long threadId = DatabaseFactory.getSmsDatabase(context).getThreadIdForMessage(messageId); Recipients recipients = DatabaseFactory.getThreadDatabase(context).getRecipientsForThreadId(threadId); DatabaseFactory.getSmsDatabase(context).markAsSentFailed(messageId); MessageNotifier.notifyMessageDeliveryFailed(context, recipients, threadId); unregisterForRadioChanges(); } }
@Override protected Recipients doInBackground(Void... params) { try { String groupId = recipients.getPrimaryRecipient().getNumber(); return DatabaseFactory.getGroupDatabase(context) .getGroupMembers(GroupUtil.getDecodedId(groupId), true); } catch (IOException e) { Log.w(TAG, e); return RecipientFactory.getRecipientsFor(context, new LinkedList<Recipient>(), true); } }
private void handleDeliveredMessage(Intent intent) { long messageId = intent.getLongExtra("message_id", -1); byte[] pdu = intent.getByteArrayExtra("pdu"); SmsMessage message = SmsMessage.createFromPdu(pdu); if (message == null) { return; } DatabaseFactory.getSmsDatabase(context).markStatus(messageId, message.getStatus()); }
private Cursor getUnarchivedConversationList() { List<Cursor> cursorList = new LinkedList<>(); cursorList.add(DatabaseFactory.getThreadDatabase(context).getConversationList()); int archivedCount = DatabaseFactory.getThreadDatabase(context).getArchivedConversationListCount(); if (archivedCount > 0) { MatrixCursor switchToArchiveCursor = new MatrixCursor( new String[] { ThreadDatabase.ID, ThreadDatabase.DATE, ThreadDatabase.MESSAGE_COUNT, ThreadDatabase.RECIPIENT_IDS, ThreadDatabase.SNIPPET, ThreadDatabase.READ, ThreadDatabase.TYPE, ThreadDatabase.SNIPPET_TYPE, ThreadDatabase.SNIPPET_URI, ThreadDatabase.ARCHIVED, ThreadDatabase.STATUS, ThreadDatabase.RECEIPT_COUNT, ThreadDatabase.EXPIRES_IN }, 1); switchToArchiveCursor.addRow( new Object[] { -1L, System.currentTimeMillis(), archivedCount, "-1", null, 1, ThreadDatabase.DistributionTypes.ARCHIVE, 0, null, 0, -1, 0, 0 }); cursorList.add(switchToArchiveCursor); } return new MergeCursor(cursorList.toArray(new Cursor[0])); }
private boolean isActiveGroup() { if (!isGroupConversation()) return false; try { byte[] groupId = GroupUtil.getDecodedId(getRecipients().getPrimaryRecipient().getNumber()); GroupRecord record = DatabaseFactory.getGroupDatabase(this).getGroup(groupId); return record != null && record.isActive(); } catch (IOException e) { Log.w("ConversationActivity", e); return false; } }
private void handleSendMessage(MasterSecret masterSecret, Intent intent) { long messageId = intent.getLongExtra("message_id", -1); UniversalTransport transport = new UniversalTransport(context, masterSecret); EncryptingSmsDatabase database = DatabaseFactory.getEncryptingSmsDatabase(context); EncryptingSmsDatabase.Reader reader = null; SmsMessageRecord record; Log.w("SmsSender", "Sending message: " + messageId); try { if (messageId != -1) reader = database.getMessage(masterSecret, messageId); else reader = database.getOutgoingMessages(masterSecret); while (reader != null && (record = reader.getNext()) != null) { try { database.markAsSending(record.getId()); transport.deliver(record); } catch (UntrustedIdentityException e) { Log.w("SmsSender", e); IncomingIdentityUpdateMessage identityUpdateMessage = IncomingIdentityUpdateMessage.createFor(e.getE164Number(), e.getIdentityKey()); DatabaseFactory.getEncryptingSmsDatabase(context) .insertMessageInbox(masterSecret, identityUpdateMessage); DatabaseFactory.getSmsDatabase(context).markAsSentFailed(messageId); } catch (UndeliverableMessageException ude) { Log.w("SmsSender", ude); DatabaseFactory.getSmsDatabase(context).markAsSentFailed(messageId); } catch (RetryLaterException rle) { Log.w("SmsSender", rle); if (systemStateListener.isConnected()) scheduleQuickRetryAlarm(); else systemStateListener.registerForConnectivityChange(); } } } finally { if (reader != null) reader.close(); } }
private Pair<Long, Long> storeMessage( MasterSecretUnion masterSecret, IncomingTextMessage message) { EncryptingSmsDatabase database = DatabaseFactory.getEncryptingSmsDatabase(context); Pair<Long, Long> messageAndThreadId; if (message.isSecureMessage()) { IncomingTextMessage placeholder = new IncomingTextMessage(message, ""); messageAndThreadId = database.insertMessageInbox(placeholder); database.markAsLegacyVersion(messageAndThreadId.first); } else { messageAndThreadId = database.insertMessageInbox(masterSecret, message); } return messageAndThreadId; }
private @NonNull RecipientDetails getGroupRecipientDetails(Context context, String groupId) { try { GroupDatabase.GroupRecord record = DatabaseFactory.getGroupDatabase(context).getGroup(GroupUtil.getDecodedId(groupId)); if (record != null) { ContactPhoto contactPhoto = ContactPhotoFactory.getGroupContactPhoto(record.getAvatar()); return new RecipientDetails(record.getTitle(), groupId, null, contactPhoto, null); } return new RecipientDetails( null, groupId, null, ContactPhotoFactory.getDefaultGroupPhoto(), null); } catch (IOException e) { Log.w("RecipientProvider", e); return new RecipientDetails( null, groupId, null, ContactPhotoFactory.getDefaultGroupPhoto(), null); } }
private void deliver(MasterSecret masterSecret, SendReq message) throws IOException, RecipientFormattingException, InvalidNumberException, EncapsulatedExceptions { TextSecureMessageSender messageSender = messageSenderFactory.create(masterSecret); byte[] groupId = GroupUtil.getDecodedId(message.getTo()[0].getString()); Recipients recipients = DatabaseFactory.getGroupDatabase(context).getGroupMembers(groupId, false); List<PushAddress> addresses = getPushAddresses(recipients); List<TextSecureAttachment> attachments = getAttachments(masterSecret, message); if (MmsSmsColumns.Types.isGroupUpdate(message.getDatabaseMessageBox()) || MmsSmsColumns.Types.isGroupQuit(message.getDatabaseMessageBox())) { String content = PartParser.getMessageText(message.getBody()); if (content != null && !content.trim().isEmpty()) { PushMessageProtos.PushMessageContent.GroupContext groupContext = PushMessageProtos.PushMessageContent.GroupContext.parseFrom(Base64.decode(content)); TextSecureAttachment avatar = attachments.isEmpty() ? null : attachments.get(0); TextSecureGroup.Type type = MmsSmsColumns.Types.isGroupQuit(message.getDatabaseMessageBox()) ? TextSecureGroup.Type.QUIT : TextSecureGroup.Type.UPDATE; TextSecureGroup group = new TextSecureGroup( type, groupId, groupContext.getName(), groupContext.getMembersList(), avatar); TextSecureMessage groupMessage = new TextSecureMessage(message.getSentTimestamp(), group, null, null); messageSender.sendMessage(addresses, groupMessage); } } else { String body = PartParser.getMessageText(message.getBody()); TextSecureGroup group = new TextSecureGroup(groupId); TextSecureMessage groupMessage = new TextSecureMessage(message.getSentTimestamp(), group, attachments, body); messageSender.sendMessage(addresses, groupMessage); } }
private void createConversationIfNecessary(Intent intent) { long thread = intent.getLongExtra("thread_id", -1L); Recipients recipients = null; if (intent.getAction() != null && intent.getAction().equals("android.intent.action.SENDTO")) { try { recipients = RecipientFactory.getRecipientsFromString( this, intent.getData().getSchemeSpecificPart()); thread = DatabaseFactory.getThreadDatabase(this).getThreadIdIfExistsFor(recipients); } catch (RecipientFormattingException rfe) { recipients = null; } } else { recipients = intent.getParcelableExtra("recipients"); } if (recipients != null) { createConversation(thread, recipients); intent.putExtra("thread_id", -1L); intent.putExtra("recipients", (Parcelable) null); intent.setAction(null); } }
private static Recipient getRecipientFromProviderId( Context context, String recipientId, boolean asynchronous) { String number = DatabaseFactory.getAddressDatabase(context).getAddressFromId(recipientId); return getRecipientForNumber(context, number, asynchronous); }
private Cursor getArchivedConversationList() { return DatabaseFactory.getThreadDatabase(context).getArchivedConversationList(); }
private Cursor getFilteredConversationList(String filter) { List<String> numbers = ContactAccessor.getInstance().getNumbersForThreadSearchFilter(context, filter); return DatabaseFactory.getThreadDatabase(context).getFilteredConversationList(numbers); }
private void handleDeliveredResult(long messageId, int result) { DatabaseFactory.getEncryptingSmsDatabase(context).markStatus(messageId, result); }
private @Nullable RecipientsPreferences getRecipientsPreferencesSync( Context context, long[] recipientIds) { return DatabaseFactory.getRecipientPreferenceDatabase(context) .getRecipientsPreferences(recipientIds) .orNull(); }
@Override public void onCanceled() { DatabaseFactory.getMmsDatabase(context).markAsSentFailed(messageId); }