Search in sources :

Example 26 with Address

use of org.thoughtcrime.securesms.database.Address in project Signal-Android by signalapp.

the class MmsSendJob method constructSendPdu.

private SendReq constructSendPdu(OutgoingMediaMessage message) throws UndeliverableMessageException {
    SendReq req = new SendReq();
    String lineNumber = getMyNumber(context);
    Address destination = message.getRecipient().getAddress();
    MediaConstraints mediaConstraints = MediaConstraints.getMmsMediaConstraints(message.getSubscriptionId());
    List<Attachment> scaledAttachments = scaleAttachments(mediaConstraints, message.getAttachments());
    if (!TextUtils.isEmpty(lineNumber)) {
        req.setFrom(new EncodedStringValue(lineNumber));
    } else {
        req.setFrom(new EncodedStringValue(TextSecurePreferences.getLocalNumber(context)));
    }
    if (destination.isMmsGroup()) {
        List<Recipient> members = DatabaseFactory.getGroupDatabase(context).getGroupMembers(destination.toGroupString(), false);
        for (Recipient member : members) {
            if (message.getDistributionType() == ThreadDatabase.DistributionTypes.BROADCAST) {
                req.addBcc(new EncodedStringValue(member.getAddress().serialize()));
            } else {
                req.addTo(new EncodedStringValue(member.getAddress().serialize()));
            }
        }
    } else {
        req.addTo(new EncodedStringValue(destination.serialize()));
    }
    req.setDate(System.currentTimeMillis() / 1000);
    PduBody body = new PduBody();
    int size = 0;
    if (!TextUtils.isEmpty(message.getBody())) {
        PduPart part = new PduPart();
        String name = String.valueOf(System.currentTimeMillis());
        part.setData(Util.toUtf8Bytes(message.getBody()));
        part.setCharset(CharacterSets.UTF_8);
        part.setContentType(ContentType.TEXT_PLAIN.getBytes());
        part.setContentId(name.getBytes());
        part.setContentLocation((name + ".txt").getBytes());
        part.setName((name + ".txt").getBytes());
        body.addPart(part);
        size += getPartSize(part);
    }
    for (Attachment attachment : scaledAttachments) {
        try {
            if (attachment.getDataUri() == null)
                throw new IOException("Assertion failed, attachment for outgoing MMS has no data!");
            String fileName = attachment.getFileName();
            PduPart part = new PduPart();
            if (fileName == null) {
                fileName = String.valueOf(Math.abs(Util.getSecureRandom().nextLong()));
                String fileExtension = MimeTypeMap.getSingleton().getExtensionFromMimeType(attachment.getContentType());
                if (fileExtension != null)
                    fileName = fileName + "." + fileExtension;
            }
            if (attachment.getContentType().startsWith("text")) {
                part.setCharset(CharacterSets.UTF_8);
            }
            part.setContentType(attachment.getContentType().getBytes());
            part.setContentLocation(fileName.getBytes());
            part.setName(fileName.getBytes());
            int index = fileName.lastIndexOf(".");
            String contentId = (index == -1) ? fileName : fileName.substring(0, index);
            part.setContentId(contentId.getBytes());
            part.setData(Util.readFully(PartAuthority.getAttachmentStream(context, attachment.getDataUri())));
            body.addPart(part);
            size += getPartSize(part);
        } catch (IOException e) {
            Log.w(TAG, e);
        }
    }
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    SmilXmlSerializer.serialize(SmilHelper.createSmilDocument(body), out);
    PduPart smilPart = new PduPart();
    smilPart.setContentId("smil".getBytes());
    smilPart.setContentLocation("smil.xml".getBytes());
    smilPart.setContentType(ContentType.APP_SMIL.getBytes());
    smilPart.setData(out.toByteArray());
    body.addPart(0, smilPart);
    req.setBody(body);
    req.setMessageSize(size);
    req.setMessageClass(PduHeaders.MESSAGE_CLASS_PERSONAL_STR.getBytes());
    req.setExpiry(7 * 24 * 60 * 60);
    try {
        req.setPriority(PduHeaders.PRIORITY_NORMAL);
        req.setDeliveryReport(PduHeaders.VALUE_NO);
        req.setReadReport(PduHeaders.VALUE_NO);
    } catch (InvalidHeaderValueException e) {
    }
    return req;
}
Also used : EncodedStringValue(com.google.android.mms.pdu_alt.EncodedStringValue) Address(org.thoughtcrime.securesms.database.Address) PduBody(com.google.android.mms.pdu_alt.PduBody) Attachment(org.thoughtcrime.securesms.attachments.Attachment) Recipient(org.thoughtcrime.securesms.recipients.Recipient) IOException(java.io.IOException) ByteArrayOutputStream(java.io.ByteArrayOutputStream) SendReq(com.google.android.mms.pdu_alt.SendReq) MediaConstraints(org.thoughtcrime.securesms.mms.MediaConstraints) InvalidHeaderValueException(com.google.android.mms.InvalidHeaderValueException) PduPart(com.google.android.mms.pdu_alt.PduPart)

Example 27 with Address

use of org.thoughtcrime.securesms.database.Address in project Signal-Android by signalapp.

the class MultiDeviceContactUpdateJob method generateFullContactUpdate.

private void generateFullContactUpdate() throws IOException, UntrustedIdentityException, NetworkException {
    if (!Permissions.hasAny(context, Manifest.permission.READ_CONTACTS, Manifest.permission.WRITE_CONTACTS)) {
        Log.w(TAG, "No contact permissions, skipping multi-device contact update...");
        return;
    }
    File contactDataFile = createTempFile("multidevice-contact-update");
    try {
        DeviceContactsOutputStream out = new DeviceContactsOutputStream(new FileOutputStream(contactDataFile));
        Collection<ContactData> contacts = ContactAccessor.getInstance().getContactsWithPush(context);
        for (ContactData contactData : contacts) {
            Uri contactUri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_URI, String.valueOf(contactData.id));
            Address address = Address.fromExternal(context, contactData.numbers.get(0).number);
            Recipient recipient = Recipient.from(context, address, false);
            Optional<IdentityDatabase.IdentityRecord> identity = DatabaseFactory.getIdentityDatabase(context).getIdentity(address);
            Optional<VerifiedMessage> verified = getVerifiedMessage(recipient, identity);
            Optional<String> name = Optional.fromNullable(contactData.name);
            Optional<String> color = Optional.of(recipient.getColor().serialize());
            Optional<byte[]> profileKey = Optional.fromNullable(recipient.getProfileKey());
            boolean blocked = recipient.isBlocked();
            Optional<Integer> expireTimer = recipient.getExpireMessages() > 0 ? Optional.of(recipient.getExpireMessages()) : Optional.absent();
            out.write(new DeviceContact(address.toPhoneString(), name, getAvatar(contactUri), color, verified, profileKey, blocked, expireTimer));
        }
        if (ProfileKeyUtil.hasProfileKey(context)) {
            out.write(new DeviceContact(TextSecurePreferences.getLocalNumber(context), Optional.absent(), Optional.absent(), Optional.absent(), Optional.absent(), Optional.of(ProfileKeyUtil.getProfileKey(context)), false, Optional.absent()));
        }
        out.close();
        sendUpdate(messageSender, contactDataFile, true);
    } catch (InvalidNumberException e) {
        Log.w(TAG, e);
    } finally {
        if (contactDataFile != null)
            contactDataFile.delete();
    }
}
Also used : DeviceContact(org.whispersystems.signalservice.api.messages.multidevice.DeviceContact) Address(org.thoughtcrime.securesms.database.Address) DeviceContactsOutputStream(org.whispersystems.signalservice.api.messages.multidevice.DeviceContactsOutputStream) InvalidNumberException(org.whispersystems.signalservice.api.util.InvalidNumberException) Recipient(org.thoughtcrime.securesms.recipients.Recipient) Uri(android.net.Uri) FileOutputStream(java.io.FileOutputStream) ContactData(org.thoughtcrime.securesms.contacts.ContactAccessor.ContactData) VerifiedMessage(org.whispersystems.signalservice.api.messages.multidevice.VerifiedMessage) File(java.io.File)

Example 28 with Address

use of org.thoughtcrime.securesms.database.Address in project Signal-Android by signalapp.

the class DirectoryHelper method refreshDirectory.

@NonNull
private static List<Address> refreshDirectory(@NonNull Context context, @NonNull SignalServiceAccountManager accountManager) throws IOException {
    if (TextUtils.isEmpty(TextSecurePreferences.getLocalNumber(context))) {
        return new LinkedList<>();
    }
    if (!Permissions.hasAll(context, Manifest.permission.WRITE_CONTACTS)) {
        return new LinkedList<>();
    }
    RecipientDatabase recipientDatabase = DatabaseFactory.getRecipientDatabase(context);
    Stream<String> eligibleRecipientDatabaseContactNumbers = Stream.of(recipientDatabase.getAllAddresses()).filter(Address::isPhone).map(Address::toPhoneString);
    Stream<String> eligibleSystemDatabaseContactNumbers = Stream.of(ContactAccessor.getInstance().getAllContactsWithNumbers(context)).map(Address::serialize);
    Set<String> eligibleContactNumbers = Stream.concat(eligibleRecipientDatabaseContactNumbers, eligibleSystemDatabaseContactNumbers).collect(Collectors.toSet());
    List<ContactTokenDetails> activeTokens = accountManager.getContacts(eligibleContactNumbers);
    if (activeTokens != null) {
        List<Address> activeAddresses = new LinkedList<>();
        List<Address> inactiveAddresses = new LinkedList<>();
        Set<String> inactiveContactNumbers = new HashSet<>(eligibleContactNumbers);
        for (ContactTokenDetails activeToken : activeTokens) {
            activeAddresses.add(Address.fromSerialized(activeToken.getNumber()));
            inactiveContactNumbers.remove(activeToken.getNumber());
        }
        for (String inactiveContactNumber : inactiveContactNumbers) {
            inactiveAddresses.add(Address.fromSerialized(inactiveContactNumber));
        }
        Set<Address> currentActiveAddresses = new HashSet<>(recipientDatabase.getRegistered());
        Set<Address> contactAddresses = new HashSet<>(recipientDatabase.getSystemContacts());
        List<Address> newlyActiveAddresses = Stream.of(activeAddresses).filter(address -> !currentActiveAddresses.contains(address)).filter(contactAddresses::contains).toList();
        recipientDatabase.setRegistered(activeAddresses, inactiveAddresses);
        updateContactsDatabase(context, activeAddresses, true);
        if (TextSecurePreferences.hasSuccessfullyRetrievedDirectory(context)) {
            return newlyActiveAddresses;
        } else {
            TextSecurePreferences.setHasSuccessfullyRetrievedDirectory(context, true);
            return new LinkedList<>();
        }
    }
    return new LinkedList<>();
}
Also used : RecipientDatabase(org.thoughtcrime.securesms.database.RecipientDatabase) Address(org.thoughtcrime.securesms.database.Address) ContactTokenDetails(org.whispersystems.signalservice.api.push.ContactTokenDetails) LinkedList(java.util.LinkedList) HashSet(java.util.HashSet) NonNull(android.support.annotation.NonNull)

Example 29 with Address

use of org.thoughtcrime.securesms.database.Address in project Signal-Android by signalapp.

the class QuickResponseService method onHandleIntent.

@Override
protected void onHandleIntent(Intent intent) {
    if (!TelephonyManager.ACTION_RESPOND_VIA_MESSAGE.equals(intent.getAction())) {
        Log.w(TAG, "Received unknown intent: " + intent.getAction());
        return;
    }
    if (KeyCachingService.isLocked(this)) {
        Log.w(TAG, "Got quick response request when locked...");
        Toast.makeText(this, R.string.QuickResponseService_quick_response_unavailable_when_Signal_is_locked, Toast.LENGTH_LONG).show();
        return;
    }
    try {
        Rfc5724Uri uri = new Rfc5724Uri(intent.getDataString());
        String content = intent.getStringExtra(Intent.EXTRA_TEXT);
        String number = uri.getPath();
        if (number.contains("%")) {
            number = URLDecoder.decode(number);
        }
        Address address = Address.fromExternal(this, number);
        Recipient recipient = Recipient.from(this, address, false);
        int subscriptionId = recipient.getDefaultSubscriptionId().or(-1);
        long expiresIn = recipient.getExpireMessages() * 1000L;
        if (!TextUtils.isEmpty(content)) {
            MessageSender.send(this, new OutgoingTextMessage(recipient, content, expiresIn, subscriptionId), -1, false, null);
        }
    } catch (URISyntaxException e) {
        Toast.makeText(this, R.string.QuickResponseService_problem_sending_message, Toast.LENGTH_LONG).show();
        Log.w(TAG, e);
    }
}
Also used : OutgoingTextMessage(org.thoughtcrime.securesms.sms.OutgoingTextMessage) Rfc5724Uri(org.thoughtcrime.securesms.util.Rfc5724Uri) Address(org.thoughtcrime.securesms.database.Address) Recipient(org.thoughtcrime.securesms.recipients.Recipient) URISyntaxException(java.net.URISyntaxException)

Example 30 with Address

use of org.thoughtcrime.securesms.database.Address in project Signal-Android by signalapp.

the class ContactAccessor method getContactsWithPush.

public Collection<ContactData> getContactsWithPush(Context context) {
    final ContentResolver resolver = context.getContentResolver();
    final String[] inProjection = new String[] { PhoneLookup._ID, PhoneLookup.DISPLAY_NAME };
    final List<Address> registeredAddresses = DatabaseFactory.getRecipientDatabase(context).getRegistered();
    final Collection<ContactData> lookupData = new ArrayList<>(registeredAddresses.size());
    for (Address registeredAddress : registeredAddresses) {
        Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(registeredAddress.serialize()));
        Cursor lookupCursor = resolver.query(uri, inProjection, null, null, null);
        try {
            if (lookupCursor != null && lookupCursor.moveToFirst()) {
                final ContactData contactData = new ContactData(lookupCursor.getLong(0), lookupCursor.getString(1));
                contactData.numbers.add(new NumberData("TextSecure", registeredAddress.serialize()));
                lookupData.add(contactData);
            }
        } finally {
            if (lookupCursor != null)
                lookupCursor.close();
        }
    }
    return lookupData;
}
Also used : Address(org.thoughtcrime.securesms.database.Address) ArrayList(java.util.ArrayList) MergeCursor(android.database.MergeCursor) Cursor(android.database.Cursor) Uri(android.net.Uri) ContentResolver(android.content.ContentResolver)

Aggregations

Address (org.thoughtcrime.securesms.database.Address)40 Recipient (org.thoughtcrime.securesms.recipients.Recipient)13 LinkedList (java.util.LinkedList)10 Uri (android.net.Uri)9 GroupDatabase (org.thoughtcrime.securesms.database.GroupDatabase)7 Cursor (android.database.Cursor)6 ByteString (com.google.protobuf.ByteString)6 IOException (java.io.IOException)6 File (java.io.File)5 GroupContext (org.whispersystems.signalservice.internal.push.SignalServiceProtos.GroupContext)5 NonNull (android.support.annotation.NonNull)4 Attachment (org.thoughtcrime.securesms.attachments.Attachment)4 InsertResult (org.thoughtcrime.securesms.database.MessagingDatabase.InsertResult)4 SignalServiceAttachment (org.whispersystems.signalservice.api.messages.SignalServiceAttachment)4 SignalServiceAddress (org.whispersystems.signalservice.api.push.SignalServiceAddress)4 SuppressLint (android.annotation.SuppressLint)3 Nullable (android.support.annotation.Nullable)3 HashSet (java.util.HashSet)3 List (java.util.List)3 ContentValues (android.content.ContentValues)2