mirror of
https://github.com/oxen-io/session-android.git
synced 2025-01-11 22:23:39 +00:00
parent
b7badec752
commit
0b62cf372b
@ -25,11 +25,11 @@ package org.thoughtcrime.securesms.contacts;
|
|||||||
public class NameAndNumber {
|
public class NameAndNumber {
|
||||||
public String name;
|
public String name;
|
||||||
public String number;
|
public String number;
|
||||||
|
|
||||||
public NameAndNumber(String name, String number) {
|
public NameAndNumber(String name, String number) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.number = number;
|
this.number = number;
|
||||||
}
|
}
|
||||||
|
|
||||||
public NameAndNumber() {}
|
public NameAndNumber() {}
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,7 @@ public class AsymmetricMasterCipher {
|
|||||||
public AsymmetricMasterCipher(AsymmetricMasterSecret asymmetricMasterSecret) {
|
public AsymmetricMasterCipher(AsymmetricMasterSecret asymmetricMasterSecret) {
|
||||||
this.asymmetricMasterSecret = asymmetricMasterSecret;
|
this.asymmetricMasterSecret = asymmetricMasterSecret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String decryptBody(String body) throws IOException, InvalidMessageException {
|
public String decryptBody(String body) throws IOException, InvalidMessageException {
|
||||||
try {
|
try {
|
||||||
byte[] combined = Base64.decode(body);
|
byte[] combined = Base64.decode(body);
|
||||||
@ -77,7 +77,7 @@ public class AsymmetricMasterCipher {
|
|||||||
throw new InvalidMessageException(ike);
|
throw new InvalidMessageException(ike);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String encryptBody(String body) {
|
public String encryptBody(String body) {
|
||||||
try {
|
try {
|
||||||
ECPublicKey theirPublic = asymmetricMasterSecret.getDjbPublicKey();
|
ECPublicKey theirPublic = asymmetricMasterSecret.getDjbPublicKey();
|
||||||
@ -95,31 +95,31 @@ public class AsymmetricMasterCipher {
|
|||||||
throw new AssertionError(e);
|
throw new AssertionError(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private MasterCipher getMasterCipherForSecret(byte[] secretBytes) {
|
private MasterCipher getMasterCipherForSecret(byte[] secretBytes) {
|
||||||
SecretKeySpec cipherKey = deriveCipherKey(secretBytes);
|
SecretKeySpec cipherKey = deriveCipherKey(secretBytes);
|
||||||
SecretKeySpec macKey = deriveMacKey(secretBytes);
|
SecretKeySpec macKey = deriveMacKey(secretBytes);
|
||||||
MasterSecret masterSecret = new MasterSecret(cipherKey, macKey);
|
MasterSecret masterSecret = new MasterSecret(cipherKey, macKey);
|
||||||
|
|
||||||
return new MasterCipher(masterSecret);
|
return new MasterCipher(masterSecret);
|
||||||
}
|
}
|
||||||
|
|
||||||
private SecretKeySpec deriveMacKey(byte[] secretBytes) {
|
private SecretKeySpec deriveMacKey(byte[] secretBytes) {
|
||||||
byte[] digestedBytes = getDigestedBytes(secretBytes, 1);
|
byte[] digestedBytes = getDigestedBytes(secretBytes, 1);
|
||||||
byte[] macKeyBytes = new byte[20];
|
byte[] macKeyBytes = new byte[20];
|
||||||
|
|
||||||
System.arraycopy(digestedBytes, 0, macKeyBytes, 0, macKeyBytes.length);
|
System.arraycopy(digestedBytes, 0, macKeyBytes, 0, macKeyBytes.length);
|
||||||
return new SecretKeySpec(macKeyBytes, "HmacSHA1");
|
return new SecretKeySpec(macKeyBytes, "HmacSHA1");
|
||||||
}
|
}
|
||||||
|
|
||||||
private SecretKeySpec deriveCipherKey(byte[] secretBytes) {
|
private SecretKeySpec deriveCipherKey(byte[] secretBytes) {
|
||||||
byte[] digestedBytes = getDigestedBytes(secretBytes, 0);
|
byte[] digestedBytes = getDigestedBytes(secretBytes, 0);
|
||||||
byte[] cipherKeyBytes = new byte[16];
|
byte[] cipherKeyBytes = new byte[16];
|
||||||
|
|
||||||
System.arraycopy(digestedBytes, 0, cipherKeyBytes, 0, cipherKeyBytes.length);
|
System.arraycopy(digestedBytes, 0, cipherKeyBytes, 0, cipherKeyBytes.length);
|
||||||
return new SecretKeySpec(cipherKeyBytes, "AES");
|
return new SecretKeySpec(cipherKeyBytes, "AES");
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte[] getDigestedBytes(byte[] secretBytes, int iteration) {
|
private byte[] getDigestedBytes(byte[] secretBytes, int iteration) {
|
||||||
try {
|
try {
|
||||||
Mac mac = Mac.getInstance("HmacSHA256");
|
Mac mac = Mac.getInstance("HmacSHA256");
|
||||||
|
@ -44,24 +44,24 @@ import android.util.Log;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
public class DecryptingPartInputStream extends FileInputStream {
|
public class DecryptingPartInputStream extends FileInputStream {
|
||||||
|
|
||||||
private static final int IV_LENGTH = 16;
|
private static final int IV_LENGTH = 16;
|
||||||
private static final int MAC_LENGTH = 20;
|
private static final int MAC_LENGTH = 20;
|
||||||
|
|
||||||
private Cipher cipher;
|
private Cipher cipher;
|
||||||
private Mac mac;
|
private Mac mac;
|
||||||
|
|
||||||
private boolean done;
|
private boolean done;
|
||||||
private long totalDataSize;
|
private long totalDataSize;
|
||||||
private long totalRead;
|
private long totalRead;
|
||||||
private byte[] overflowBuffer;
|
private byte[] overflowBuffer;
|
||||||
|
|
||||||
public DecryptingPartInputStream(File file, MasterSecret masterSecret) throws FileNotFoundException {
|
public DecryptingPartInputStream(File file, MasterSecret masterSecret) throws FileNotFoundException {
|
||||||
super(file);
|
super(file);
|
||||||
try {
|
try {
|
||||||
if (file.length() <= IV_LENGTH + MAC_LENGTH)
|
if (file.length() <= IV_LENGTH + MAC_LENGTH)
|
||||||
throw new FileNotFoundException("Part shorter than crypto overhead!");
|
throw new FileNotFoundException("Part shorter than crypto overhead!");
|
||||||
|
|
||||||
done = false;
|
done = false;
|
||||||
mac = initializeMac(masterSecret.getMacKey());
|
mac = initializeMac(masterSecret.getMacKey());
|
||||||
cipher = initializeCipher(masterSecret.getEncryptionKey());
|
cipher = initializeCipher(masterSecret.getEncryptionKey());
|
||||||
@ -81,12 +81,12 @@ public class DecryptingPartInputStream extends FileInputStream {
|
|||||||
throw new FileNotFoundException("IOException while reading IV!");
|
throw new FileNotFoundException("IOException while reading IV!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int read(byte[] buffer) throws IOException {
|
public int read(byte[] buffer) throws IOException {
|
||||||
return read(buffer, 0, buffer.length);
|
return read(buffer, 0, buffer.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int read(byte[] buffer, int offset, int length) throws IOException {
|
public int read(byte[] buffer, int offset, int length) throws IOException {
|
||||||
if (totalRead != totalDataSize)
|
if (totalRead != totalDataSize)
|
||||||
@ -96,11 +96,11 @@ public class DecryptingPartInputStream extends FileInputStream {
|
|||||||
else
|
else
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int readFinal(byte[] buffer, int offset, int length) throws IOException {
|
private int readFinal(byte[] buffer, int offset, int length) throws IOException {
|
||||||
try {
|
try {
|
||||||
int flourish = cipher.doFinal(buffer, offset);
|
int flourish = cipher.doFinal(buffer, offset);
|
||||||
// mac.update(buffer, offset, flourish);
|
//mac.update(buffer, offset, flourish);
|
||||||
|
|
||||||
byte[] ourMac = mac.doFinal();
|
byte[] ourMac = mac.doFinal();
|
||||||
byte[] theirMac = new byte[mac.getMacLength()];
|
byte[] theirMac = new byte[mac.getMacLength()];
|
||||||
@ -108,7 +108,7 @@ public class DecryptingPartInputStream extends FileInputStream {
|
|||||||
|
|
||||||
if (!Arrays.equals(ourMac, theirMac))
|
if (!Arrays.equals(ourMac, theirMac))
|
||||||
throw new IOException("MAC doesn't match! Potential tampering?");
|
throw new IOException("MAC doesn't match! Potential tampering?");
|
||||||
|
|
||||||
done = true;
|
done = true;
|
||||||
return flourish;
|
return flourish;
|
||||||
} catch (IllegalBlockSizeException e) {
|
} catch (IllegalBlockSizeException e) {
|
||||||
@ -122,7 +122,7 @@ public class DecryptingPartInputStream extends FileInputStream {
|
|||||||
throw new IOException("Bad padding exception!");
|
throw new IOException("Bad padding exception!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int readIncremental(byte[] buffer, int offset, int length) throws IOException {
|
private int readIncremental(byte[] buffer, int offset, int length) throws IOException {
|
||||||
int readLength = 0;
|
int readLength = 0;
|
||||||
if (null != overflowBuffer) {
|
if (null != overflowBuffer) {
|
||||||
@ -145,11 +145,11 @@ public class DecryptingPartInputStream extends FileInputStream {
|
|||||||
|
|
||||||
if (length + totalRead > totalDataSize)
|
if (length + totalRead > totalDataSize)
|
||||||
length = (int)(totalDataSize - totalRead);
|
length = (int)(totalDataSize - totalRead);
|
||||||
|
|
||||||
byte[] internalBuffer = new byte[length];
|
byte[] internalBuffer = new byte[length];
|
||||||
int read = super.read(internalBuffer, 0, internalBuffer.length <= cipher.getBlockSize() ? internalBuffer.length : internalBuffer.length - cipher.getBlockSize());
|
int read = super.read(internalBuffer, 0, internalBuffer.length <= cipher.getBlockSize() ? internalBuffer.length : internalBuffer.length - cipher.getBlockSize());
|
||||||
totalRead += read;
|
totalRead += read;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
mac.update(internalBuffer, 0, read);
|
mac.update(internalBuffer, 0, read);
|
||||||
|
|
||||||
@ -175,41 +175,41 @@ public class DecryptingPartInputStream extends FileInputStream {
|
|||||||
throw new AssertionError(e);
|
throw new AssertionError(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Mac initializeMac(SecretKeySpec key) throws NoSuchAlgorithmException, InvalidKeyException {
|
private Mac initializeMac(SecretKeySpec key) throws NoSuchAlgorithmException, InvalidKeyException {
|
||||||
Mac hmac = Mac.getInstance("HmacSHA1");
|
Mac hmac = Mac.getInstance("HmacSHA1");
|
||||||
hmac.init(key);
|
hmac.init(key);
|
||||||
|
|
||||||
return hmac;
|
return hmac;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Cipher initializeCipher(SecretKeySpec key)
|
private Cipher initializeCipher(SecretKeySpec key)
|
||||||
throws InvalidKeyException, InvalidAlgorithmParameterException,
|
throws InvalidKeyException, InvalidAlgorithmParameterException,
|
||||||
NoSuchAlgorithmException, NoSuchPaddingException, IOException
|
NoSuchAlgorithmException, NoSuchPaddingException, IOException
|
||||||
{
|
{
|
||||||
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
|
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
|
||||||
IvParameterSpec iv = readIv(cipher.getBlockSize());
|
IvParameterSpec iv = readIv(cipher.getBlockSize());
|
||||||
cipher.init(Cipher.DECRYPT_MODE, key, iv);
|
cipher.init(Cipher.DECRYPT_MODE, key, iv);
|
||||||
|
|
||||||
return cipher;
|
return cipher;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IvParameterSpec readIv(int size) throws IOException {
|
private IvParameterSpec readIv(int size) throws IOException {
|
||||||
byte[] iv = new byte[size];
|
byte[] iv = new byte[size];
|
||||||
readFully(iv);
|
readFully(iv);
|
||||||
|
|
||||||
mac.update(iv);
|
mac.update(iv);
|
||||||
return new IvParameterSpec(iv);
|
return new IvParameterSpec(iv);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readFully(byte[] buffer) throws IOException {
|
private void readFully(byte[] buffer) throws IOException {
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
int read = super.read(buffer, offset, buffer.length-offset);
|
int read = super.read(buffer, offset, buffer.length-offset);
|
||||||
|
|
||||||
if (read + offset < buffer.length) offset += read;
|
if (read + offset < buffer.length) offset += read;
|
||||||
else return;
|
else return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@ public class EncryptingPartOutputStream extends FileOutputStream {
|
|||||||
private Cipher cipher;
|
private Cipher cipher;
|
||||||
private Mac mac;
|
private Mac mac;
|
||||||
private boolean closed;
|
private boolean closed;
|
||||||
|
|
||||||
public EncryptingPartOutputStream(File file, MasterSecret masterSecret) throws FileNotFoundException {
|
public EncryptingPartOutputStream(File file, MasterSecret masterSecret) throws FileNotFoundException {
|
||||||
super(file);
|
super(file);
|
||||||
|
|
||||||
@ -62,37 +62,37 @@ public class EncryptingPartOutputStream extends FileOutputStream {
|
|||||||
throw new AssertionError(e);
|
throw new AssertionError(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(byte[] buffer) throws IOException {
|
public void write(byte[] buffer) throws IOException {
|
||||||
this.write(buffer, 0, buffer.length);
|
this.write(buffer, 0, buffer.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(byte[] buffer, int offset, int length) throws IOException {
|
public void write(byte[] buffer, int offset, int length) throws IOException {
|
||||||
byte[] encryptedBuffer = cipher.update(buffer, offset, length);
|
byte[] encryptedBuffer = cipher.update(buffer, offset, length);
|
||||||
|
|
||||||
if (encryptedBuffer != null) {
|
if (encryptedBuffer != null) {
|
||||||
mac.update(encryptedBuffer);
|
mac.update(encryptedBuffer);
|
||||||
super.write(encryptedBuffer, 0, encryptedBuffer.length);
|
super.write(encryptedBuffer, 0, encryptedBuffer.length);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
try {
|
try {
|
||||||
if (!closed) {
|
if (!closed) {
|
||||||
byte[] encryptedRemainder = cipher.doFinal();
|
byte[] encryptedRemainder = cipher.doFinal();
|
||||||
mac.update(encryptedRemainder);
|
mac.update(encryptedRemainder);
|
||||||
|
|
||||||
byte[] macBytes = mac.doFinal();
|
byte[] macBytes = mac.doFinal();
|
||||||
|
|
||||||
super.write(encryptedRemainder, 0, encryptedRemainder.length);
|
super.write(encryptedRemainder, 0, encryptedRemainder.length);
|
||||||
super.write(macBytes, 0, macBytes.length);
|
super.write(macBytes, 0, macBytes.length);
|
||||||
|
|
||||||
closed = true;
|
closed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
super.close();
|
super.close();
|
||||||
} catch (BadPaddingException bpe) {
|
} catch (BadPaddingException bpe) {
|
||||||
throw new AssertionError(bpe);
|
throw new AssertionError(bpe);
|
||||||
@ -100,22 +100,22 @@ public class EncryptingPartOutputStream extends FileOutputStream {
|
|||||||
throw new AssertionError(e);
|
throw new AssertionError(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Mac initializeMac(SecretKeySpec key) throws NoSuchAlgorithmException, InvalidKeyException {
|
private Mac initializeMac(SecretKeySpec key) throws NoSuchAlgorithmException, InvalidKeyException {
|
||||||
Mac hmac = Mac.getInstance("HmacSHA1");
|
Mac hmac = Mac.getInstance("HmacSHA1");
|
||||||
hmac.init(key);
|
hmac.init(key);
|
||||||
|
|
||||||
return hmac;
|
return hmac;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Cipher initializeCipher(Mac mac, SecretKeySpec key) throws IOException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException {
|
private Cipher initializeCipher(Mac mac, SecretKeySpec key) throws IOException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException {
|
||||||
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
|
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
|
||||||
cipher.init(Cipher.ENCRYPT_MODE, key);
|
cipher.init(Cipher.ENCRYPT_MODE, key);
|
||||||
|
|
||||||
byte[] ivBytes = cipher.getIV();
|
byte[] ivBytes = cipher.getIV();
|
||||||
mac.update(ivBytes);
|
mac.update(ivBytes);
|
||||||
super.write(ivBytes, 0, ivBytes.length);
|
super.write(ivBytes, 0, ivBytes.length);
|
||||||
|
|
||||||
return cipher;
|
return cipher;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ public class IdentityKeyUtil {
|
|||||||
|
|
||||||
private static final String IDENTITY_PUBLIC_KEY_DJB_PREF = "pref_identity_public_curve25519";
|
private static final String IDENTITY_PUBLIC_KEY_DJB_PREF = "pref_identity_public_curve25519";
|
||||||
private static final String IDENTITY_PRIVATE_KEY_DJB_PREF = "pref_identity_private_curve25519";
|
private static final String IDENTITY_PRIVATE_KEY_DJB_PREF = "pref_identity_private_curve25519";
|
||||||
|
|
||||||
public static boolean hasIdentityKey(Context context) {
|
public static boolean hasIdentityKey(Context context) {
|
||||||
SharedPreferences preferences = context.getSharedPreferences(MasterSecretUtil.PREFERENCES_NAME, 0);
|
SharedPreferences preferences = context.getSharedPreferences(MasterSecretUtil.PREFERENCES_NAME, 0);
|
||||||
|
|
||||||
@ -50,10 +50,10 @@ public class IdentityKeyUtil {
|
|||||||
preferences.contains(IDENTITY_PUBLIC_KEY_DJB_PREF) &&
|
preferences.contains(IDENTITY_PUBLIC_KEY_DJB_PREF) &&
|
||||||
preferences.contains(IDENTITY_PRIVATE_KEY_DJB_PREF);
|
preferences.contains(IDENTITY_PRIVATE_KEY_DJB_PREF);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IdentityKey getIdentityKey(Context context) {
|
public static IdentityKey getIdentityKey(Context context) {
|
||||||
if (!hasIdentityKey(context)) return null;
|
if (!hasIdentityKey(context)) return null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
byte[] publicKeyBytes = Base64.decode(retrieve(context, IDENTITY_PUBLIC_KEY_DJB_PREF));
|
byte[] publicKeyBytes = Base64.decode(retrieve(context, IDENTITY_PUBLIC_KEY_DJB_PREF));
|
||||||
return new IdentityKey(publicKeyBytes, 0);
|
return new IdentityKey(publicKeyBytes, 0);
|
||||||
@ -114,11 +114,11 @@ public class IdentityKeyUtil {
|
|||||||
SharedPreferences preferences = context.getSharedPreferences(MasterSecretUtil.PREFERENCES_NAME, 0);
|
SharedPreferences preferences = context.getSharedPreferences(MasterSecretUtil.PREFERENCES_NAME, 0);
|
||||||
return preferences.getString(key, null);
|
return preferences.getString(key, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void save(Context context, String key, String value) {
|
public static void save(Context context, String key, String value) {
|
||||||
SharedPreferences preferences = context.getSharedPreferences(MasterSecretUtil.PREFERENCES_NAME, 0);
|
SharedPreferences preferences = context.getSharedPreferences(MasterSecretUtil.PREFERENCES_NAME, 0);
|
||||||
Editor preferencesEditor = preferences.edit();
|
Editor preferencesEditor = preferences.edit();
|
||||||
|
|
||||||
preferencesEditor.putString(key, value);
|
preferencesEditor.putString(key, value);
|
||||||
if (!preferencesEditor.commit()) throw new AssertionError("failed to save identity key/value to shared preferences");
|
if (!preferencesEditor.commit()) throw new AssertionError("failed to save identity key/value to shared preferences");
|
||||||
}
|
}
|
||||||
|
@ -41,12 +41,12 @@ public class AudioSlide extends Slide {
|
|||||||
public AudioSlide(Context context, Uri uri) throws IOException, MediaTooLargeException {
|
public AudioSlide(Context context, Uri uri) throws IOException, MediaTooLargeException {
|
||||||
super(context, constructPartFromUri(context, uri));
|
super(context, constructPartFromUri(context, uri));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasImage() {
|
public boolean hasImage() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasAudio() {
|
public boolean hasAudio() {
|
||||||
return true;
|
return true;
|
||||||
@ -69,15 +69,15 @@ public class AudioSlide extends Slide {
|
|||||||
|
|
||||||
public static PduPart constructPartFromUri(Context context, Uri uri) throws IOException, MediaTooLargeException {
|
public static PduPart constructPartFromUri(Context context, Uri uri) throws IOException, MediaTooLargeException {
|
||||||
PduPart part = new PduPart();
|
PduPart part = new PduPart();
|
||||||
|
|
||||||
if (getMediaSize(context, uri) > MAX_MESSAGE_SIZE)
|
if (getMediaSize(context, uri) > MAX_MESSAGE_SIZE)
|
||||||
throw new MediaTooLargeException("Audio track larger than size maximum.");
|
throw new MediaTooLargeException("Audio track larger than size maximum.");
|
||||||
|
|
||||||
Cursor cursor = null;
|
Cursor cursor = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
cursor = context.getContentResolver().query(uri, new String[]{Audio.Media.MIME_TYPE}, null, null, null);
|
cursor = context.getContentResolver().query(uri, new String[]{Audio.Media.MIME_TYPE}, null, null, null);
|
||||||
|
|
||||||
if (cursor != null && cursor.moveToFirst())
|
if (cursor != null && cursor.moveToFirst())
|
||||||
part.setContentType(cursor.getString(0).getBytes());
|
part.setContentType(cursor.getString(0).getBytes());
|
||||||
else
|
else
|
||||||
@ -90,7 +90,7 @@ public class AudioSlide extends Slide {
|
|||||||
part.setDataUri(uri);
|
part.setDataUri(uri);
|
||||||
part.setContentId((System.currentTimeMillis()+"").getBytes());
|
part.setContentId((System.currentTimeMillis()+"").getBytes());
|
||||||
part.setName(("Audio" + System.currentTimeMillis()).getBytes());
|
part.setName(("Audio" + System.currentTimeMillis()).getBytes());
|
||||||
|
|
||||||
return part;
|
return part;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,7 @@ public class SlideDeck {
|
|||||||
public void clear() {
|
public void clear() {
|
||||||
slides.clear();
|
slides.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public PduBody toPduBody() {
|
public PduBody toPduBody() {
|
||||||
PduBody body = new PduBody();
|
PduBody body = new PduBody();
|
||||||
|
|
||||||
@ -87,7 +87,7 @@ public class SlideDeck {
|
|||||||
public void addSlide(Slide slide) {
|
public void addSlide(Slide slide) {
|
||||||
slides.add(slide);
|
slides.add(slide);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Slide> getSlides() {
|
public List<Slide> getSlides() {
|
||||||
return slides;
|
return slides;
|
||||||
}
|
}
|
||||||
@ -101,5 +101,5 @@ public class SlideDeck {
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ import ws.com.google.android.mms.pdu.CharacterSets;
|
|||||||
import ws.com.google.android.mms.pdu.PduPart;
|
import ws.com.google.android.mms.pdu.PduPart;
|
||||||
|
|
||||||
public class TextSlide extends Slide {
|
public class TextSlide extends Slide {
|
||||||
|
|
||||||
private static final int MAX_CACHE_SIZE = 10;
|
private static final int MAX_CACHE_SIZE = 10;
|
||||||
private static final Map<Uri, SoftReference<String>> textCache =
|
private static final Map<Uri, SoftReference<String>> textCache =
|
||||||
Collections.synchronizedMap(new LRUCache<Uri, SoftReference<String>>(MAX_CACHE_SIZE));
|
Collections.synchronizedMap(new LRUCache<Uri, SoftReference<String>>(MAX_CACHE_SIZE));
|
||||||
@ -54,7 +54,7 @@ public class TextSlide extends Slide {
|
|||||||
public boolean hasText() {
|
public boolean hasText() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getText() {
|
public String getText() {
|
||||||
try {
|
try {
|
||||||
@ -69,9 +69,9 @@ public class TextSlide extends Slide {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
String text = new String(getPartData(), CharacterSets.getMimeName(part.getCharset()));
|
String text = new String(getPartData(), CharacterSets.getMimeName(part.getCharset()));
|
||||||
textCache.put(part.getDataUri(), new SoftReference<String>(text));
|
textCache.put(part.getDataUri(), new SoftReference<String>(text));
|
||||||
|
|
||||||
return text;
|
return text;
|
||||||
} catch (UnsupportedEncodingException uee) {
|
} catch (UnsupportedEncodingException uee) {
|
||||||
Log.w("TextSlide", uee);
|
Log.w("TextSlide", uee);
|
||||||
|
@ -79,7 +79,7 @@ public class VideoSlide extends Slide {
|
|||||||
PduPart part = new PduPart();
|
PduPart part = new PduPart();
|
||||||
ContentResolver resolver = context.getContentResolver();
|
ContentResolver resolver = context.getContentResolver();
|
||||||
Cursor cursor = null;
|
Cursor cursor = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
cursor = resolver.query(uri, new String[] {MediaStore.Video.Media.MIME_TYPE}, null, null, null);
|
cursor = resolver.query(uri, new String[] {MediaStore.Video.Media.MIME_TYPE}, null, null, null);
|
||||||
if (cursor != null && cursor.moveToFirst()) {
|
if (cursor != null && cursor.moveToFirst()) {
|
||||||
@ -90,14 +90,14 @@ public class VideoSlide extends Slide {
|
|||||||
if (cursor != null)
|
if (cursor != null)
|
||||||
cursor.close();
|
cursor.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getMediaSize(context, uri) > MAX_MESSAGE_SIZE)
|
if (getMediaSize(context, uri) > MAX_MESSAGE_SIZE)
|
||||||
throw new MediaTooLargeException("Video exceeds maximum message size.");
|
throw new MediaTooLargeException("Video exceeds maximum message size.");
|
||||||
|
|
||||||
part.setDataUri(uri);
|
part.setDataUri(uri);
|
||||||
part.setContentId((System.currentTimeMillis()+"").getBytes());
|
part.setContentId((System.currentTimeMillis()+"").getBytes());
|
||||||
part.setName(("Video" + System.currentTimeMillis()).getBytes());
|
part.setName(("Video" + System.currentTimeMillis()).getBytes());
|
||||||
|
|
||||||
return part;
|
return part;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/**
|
/**
|
||||||
* Copyright (C) 2011 Whisper Systems
|
* Copyright (C) 2011 Whisper Systems
|
||||||
* Copyright (C) 2014 Open Whisper Systems
|
* Copyright (C) 2014 Open Whisper Systems
|
||||||
*
|
*
|
||||||
@ -26,7 +26,7 @@ import org.whispersystems.libaxolotl.protocol.CiphertextMessage;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
public class SmsTransportDetails {
|
public class SmsTransportDetails {
|
||||||
|
|
||||||
public static final int SMS_SIZE = 160;
|
public static final int SMS_SIZE = 160;
|
||||||
public static final int MULTIPART_SMS_SIZE = 153;
|
public static final int MULTIPART_SMS_SIZE = 153;
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ public class MemoryCleaner {
|
|||||||
public static void clean(MasterSecret masterSecret) {
|
public static void clean(MasterSecret masterSecret) {
|
||||||
// if (masterSecret == null)
|
// if (masterSecret == null)
|
||||||
// return;
|
// return;
|
||||||
//
|
//
|
||||||
// try {
|
// try {
|
||||||
// SecretKeySpec cipherKey = masterSecret.getEncryptionKey();
|
// SecretKeySpec cipherKey = masterSecret.getEncryptionKey();
|
||||||
// SecretKeySpec macKey = masterSecret.getMacKey();
|
// SecretKeySpec macKey = masterSecret.getMacKey();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user