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;
}
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();
}
}
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<>();
}
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);
}
}
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;
}
Aggregations