Split out Util functions.

This commit is contained in:
Moxie Marlinspike
2014-11-12 11:15:05 -08:00
parent 0d102f76cc
commit 08ed90c5ec
86 changed files with 2777 additions and 434 deletions

View File

@@ -1,3 +1,19 @@
/**
* Copyright (C) 2014 Open Whisper Systems
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.whispersystems.textsecure.api;
import org.whispersystems.libaxolotl.IdentityKey;

View File

@@ -1,3 +1,19 @@
/**
* Copyright (C) 2014 Open Whisper Systems
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.whispersystems.textsecure.api;
import org.whispersystems.libaxolotl.InvalidMessageException;

View File

@@ -1,3 +1,19 @@
/**
* Copyright (C) 2014 Open Whisper Systems
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.whispersystems.textsecure.api;
import android.util.Log;
@@ -28,7 +44,7 @@ import org.whispersystems.textsecure.push.UnregisteredUserException;
import org.whispersystems.textsecure.push.exceptions.EncapsulatedExceptions;
import org.whispersystems.textsecure.push.exceptions.MismatchedDevicesException;
import org.whispersystems.textsecure.push.exceptions.StaleDevicesException;
import org.whispersystems.textsecure.util.Util;
import org.whispersystems.textsecure.internal.util.Util;
import java.io.IOException;
import java.util.LinkedList;

View File

@@ -1,5 +1,5 @@
/**
* Copyright (C) 2013 Open Whisper Systems
* Copyright (C) 2013-2014 Open Whisper Systems
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -20,7 +20,7 @@ import android.util.Log;
import org.whispersystems.libaxolotl.InvalidMacException;
import org.whispersystems.libaxolotl.InvalidMessageException;
import org.whispersystems.textsecure.util.Util;
import org.whispersystems.textsecure.internal.util.Util;
import java.io.File;
import java.io.FileInputStream;

View File

@@ -1,6 +1,22 @@
/**
* Copyright (C) 2014 Open Whisper Systems
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.whispersystems.textsecure.api.crypto;
import org.whispersystems.textsecure.util.Util;
import org.whispersystems.textsecure.internal.util.Util;
import java.io.IOException;
import java.io.OutputStream;

View File

@@ -1,7 +1,21 @@
/**
* Copyright (C) 2014 Open Whisper Systems
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.whispersystems.textsecure.api.crypto;
import android.util.Log;
import com.google.protobuf.InvalidProtocolBufferException;
import org.whispersystems.libaxolotl.DuplicateMessageException;

View File

@@ -1,3 +1,19 @@
/**
* Copyright (C) 2014 Open Whisper Systems
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.whispersystems.textsecure.api.crypto;
import org.whispersystems.libaxolotl.IdentityKey;

View File

@@ -1,7 +1,5 @@
package org.whispersystems.textsecure.api.messages;
import java.io.InputStream;
public abstract class TextSecureAttachment {
private final String contentType;

View File

@@ -1,3 +1,19 @@
/**
* Copyright (C) 2014 Open Whisper Systems
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.whispersystems.textsecure.api.messages;
import android.util.Log;
@@ -6,8 +22,8 @@ import com.google.protobuf.ByteString;
import org.whispersystems.libaxolotl.InvalidVersionException;
import org.whispersystems.textsecure.push.PushMessageProtos.IncomingPushMessageSignal;
import org.whispersystems.textsecure.util.Base64;
import org.whispersystems.textsecure.util.Hex;
import org.whispersystems.textsecure.internal.util.Base64;
import org.whispersystems.textsecure.internal.util.Hex;
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;

View File

@@ -1,3 +1,19 @@
/**
* Copyright (C) 2014 Open Whisper Systems
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.whispersystems.textsecure.api.messages;
import org.whispersystems.libaxolotl.util.guava.Optional;

View File

@@ -1,3 +1,19 @@
/**
* Copyright (C) 2014 Open Whisper Systems
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.whispersystems.textsecure.api.messages;
import org.whispersystems.libaxolotl.util.guava.Optional;

View File

@@ -1,4 +1,4 @@
package org.whispersystems.textsecure.util;
package org.whispersystems.textsecure.api.util;
public class InvalidNumberException extends Throwable {
public InvalidNumberException(String s) {

View File

@@ -1,4 +1,20 @@
package org.whispersystems.textsecure.util;
/**
* Copyright (C) 2014 Open Whisper Systems
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.whispersystems.textsecure.api.util;
import android.util.Log;
@@ -17,6 +33,8 @@ import java.util.Locale;
*/
public class PhoneNumberFormatter {
private static final String TAG = PhoneNumberFormatter.class.getSimpleName();
public static boolean isValidNumber(String number) {
return number.matches("^\\+[0-9]{10,}");
}
@@ -46,7 +64,7 @@ public class PhoneNumberFormatter {
PhoneNumber parsedNumber = util.parse(number, null);
return util.format(parsedNumber, PhoneNumberFormat.INTERNATIONAL);
} catch (NumberParseException e) {
Log.w("PhoneNumberFormatter", e);
Log.w(TAG, e);
return number;
}
}
@@ -72,12 +90,12 @@ public class PhoneNumberFormatter {
PhoneNumber localNumberObject = util.parse(localNumber, null);
String localCountryCode = util.getRegionCodeForNumber(localNumberObject);
Log.w("PhoneNumberFormatter", "Got local CC: " + localCountryCode);
Log.w(TAG, "Got local CC: " + localCountryCode);
PhoneNumber numberObject = util.parse(number, localCountryCode);
return util.format(numberObject, PhoneNumberFormat.E164);
} catch (NumberParseException e) {
Log.w("PhoneNumberFormatter", e);
Log.w(TAG, e);
return impreciseFormatNumber(number, localNumber);
}
}
@@ -95,10 +113,8 @@ public class PhoneNumberFormatter {
util.getRegionCodeForCountryCode(parsedCountryCode));
return util.format(parsedNumber, PhoneNumberUtil.PhoneNumberFormat.E164);
} catch (NumberParseException npe) {
Log.w("CreateAccountActivity", npe);
} catch (NumberFormatException nfe) {
Log.w("CreateAccountActivity", nfe);
} catch (NumberParseException | NumberFormatException npe) {
Log.w(TAG, npe);
}
return "+" +
@@ -112,7 +128,7 @@ public class PhoneNumberFormatter {
PhoneNumber parsedNumber = util.parse(e164number, null);
return util.format(parsedNumber, PhoneNumberFormat.INTERNATIONAL);
} catch (NumberParseException e) {
Log.w("PhoneNumberFormatter", e);
Log.w(TAG, e);
return e164number;
}
}

View File

@@ -1,4 +1,4 @@
package org.whispersystems.textsecure.util;
package org.whispersystems.textsecure.internal.util;
/**
* <p>Encodes and decodes to and from Base64 notation.</p>

View File

@@ -14,7 +14,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.whispersystems.textsecure.util;
package org.whispersystems.textsecure.internal.util;
import java.math.BigInteger;
import java.security.cert.CertificateException;

View File

@@ -14,7 +14,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.whispersystems.textsecure.util;
package org.whispersystems.textsecure.internal.util;
import java.io.IOException;

View File

@@ -0,0 +1,76 @@
package org.whispersystems.textsecure.internal.util;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
public class Util {
public static byte[][] split(byte[] input, int firstLength, int secondLength) {
byte[][] parts = new byte[2][];
parts[0] = new byte[firstLength];
System.arraycopy(input, 0, parts[0], 0, firstLength);
parts[1] = new byte[secondLength];
System.arraycopy(input, firstLength, parts[1], 0, secondLength);
return parts;
}
public static boolean isEmpty(String value) {
return value == null || value.trim().length() == 0;
}
public static byte[] getSecretBytes(int size) {
try {
byte[] secret = new byte[size];
SecureRandom.getInstance("SHA1PRNG").nextBytes(secret);
return secret;
} catch (NoSuchAlgorithmException e) {
throw new AssertionError(e);
}
}
public static String readFully(InputStream in) throws IOException {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
byte[] buffer = new byte[4096];
int read;
while ((read = in.read(buffer)) != -1) {
bout.write(buffer, 0, read);
}
in.close();
return new String(bout.toByteArray());
}
public static void readFully(InputStream in, byte[] buffer) throws IOException {
int offset = 0;
for (;;) {
int read = in.read(buffer, offset, buffer.length - offset);
if (read + offset < buffer.length) offset += read;
else return;
}
}
public static void copy(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[4096];
int read;
while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
in.close();
out.close();
}
}

View File

@@ -16,7 +16,8 @@
*/
package org.whispersystems.textsecure.push;
import org.whispersystems.textsecure.util.Base64;
import org.whispersystems.textsecure.internal.util.Base64;
public class OutgoingPushMessage {

View File

@@ -9,11 +9,10 @@ import com.google.thoughtcrimegson.JsonPrimitive;
import com.google.thoughtcrimegson.JsonSerializationContext;
import com.google.thoughtcrimegson.JsonSerializer;
import org.whispersystems.libaxolotl.IdentityKey;
import org.whispersystems.libaxolotl.InvalidKeyException;
import org.whispersystems.libaxolotl.ecc.Curve;
import org.whispersystems.libaxolotl.ecc.ECPublicKey;
import org.whispersystems.textsecure.util.Base64;
import org.whispersystems.textsecure.internal.util.Base64;
import java.io.IOException;
import java.lang.reflect.Type;

View File

@@ -11,7 +11,7 @@ import com.google.thoughtcrimegson.JsonSerializer;
import org.whispersystems.libaxolotl.IdentityKey;
import org.whispersystems.libaxolotl.InvalidKeyException;
import org.whispersystems.textsecure.util.Base64;
import org.whispersystems.textsecure.internal.util.Base64;
import java.io.IOException;
import java.lang.reflect.Type;

View File

@@ -28,6 +28,8 @@ import org.whispersystems.libaxolotl.state.PreKeyBundle;
import org.whispersystems.libaxolotl.state.PreKeyRecord;
import org.whispersystems.libaxolotl.state.SignedPreKeyRecord;
import org.whispersystems.textsecure.api.crypto.AttachmentCipherOutputStream;
import org.whispersystems.textsecure.internal.util.Base64;
import org.whispersystems.textsecure.internal.util.Util;
import org.whispersystems.textsecure.push.exceptions.AuthorizationFailedException;
import org.whispersystems.textsecure.push.exceptions.ExpectationFailedException;
import org.whispersystems.textsecure.push.exceptions.MismatchedDevicesException;
@@ -36,9 +38,7 @@ import org.whispersystems.textsecure.push.exceptions.NotFoundException;
import org.whispersystems.textsecure.push.exceptions.PushNetworkException;
import org.whispersystems.textsecure.push.exceptions.RateLimitException;
import org.whispersystems.textsecure.push.exceptions.StaleDevicesException;
import org.whispersystems.textsecure.util.Base64;
import org.whispersystems.textsecure.util.BlacklistingTrustManager;
import org.whispersystems.textsecure.util.Util;
import org.whispersystems.textsecure.internal.util.BlacklistingTrustManager;
import java.io.File;
import java.io.FileOutputStream;

View File

@@ -10,7 +10,7 @@ import com.google.thoughtcrimegson.JsonSerializationContext;
import com.google.thoughtcrimegson.JsonSerializer;
import org.whispersystems.libaxolotl.ecc.ECPublicKey;
import org.whispersystems.textsecure.util.Base64;
import org.whispersystems.textsecure.internal.util.Base64;
import java.io.IOException;
import java.lang.reflect.Type;

View File

@@ -1,219 +0,0 @@
package org.whispersystems.textsecure.util;
import android.content.Context;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.DrawableContainer;
import android.graphics.drawable.StateListDrawable;
import android.telephony.TelephonyManager;
import android.view.View;
import android.widget.EditText;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.text.ParseException;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
public class Util {
public static byte[] combine(byte[]... elements) {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
for (byte[] element : elements) {
baos.write(element);
}
return baos.toByteArray();
} catch (IOException e) {
throw new AssertionError(e);
}
}
public static byte[][] split(byte[] input, int firstLength, int secondLength) {
byte[][] parts = new byte[2][];
parts[0] = new byte[firstLength];
System.arraycopy(input, 0, parts[0], 0, firstLength);
parts[1] = new byte[secondLength];
System.arraycopy(input, firstLength, parts[1], 0, secondLength);
return parts;
}
public static byte[][] split(byte[] input, int firstLength, int secondLength, int thirdLength)
throws ParseException
{
if (input == null || firstLength < 0 || secondLength < 0 || thirdLength < 0 ||
input.length < firstLength + secondLength + thirdLength)
{
throw new ParseException("Input too small: " + (input == null ? null : Hex.toString(input)), 0);
}
byte[][] parts = new byte[3][];
parts[0] = new byte[firstLength];
System.arraycopy(input, 0, parts[0], 0, firstLength);
parts[1] = new byte[secondLength];
System.arraycopy(input, firstLength, parts[1], 0, secondLength);
parts[2] = new byte[thirdLength];
System.arraycopy(input, firstLength + secondLength, parts[2], 0, thirdLength);
return parts;
}
public static byte[] trim(byte[] input, int length) {
byte[] result = new byte[length];
System.arraycopy(input, 0, result, 0, result.length);
return result;
}
public static boolean isEmpty(String value) {
return value == null || value.trim().length() == 0;
}
public static boolean isEmpty(EditText value) {
return value == null || value.getText() == null || isEmpty(value.getText().toString());
}
public static boolean isEmpty(CharSequence value) {
return value == null || value.length() == 0;
}
public static String getSecret(int size) {
byte[] secret = getSecretBytes(size);
return Base64.encodeBytes(secret);
}
public static byte[] getSecretBytes(int size) {
try {
byte[] secret = new byte[size];
SecureRandom.getInstance("SHA1PRNG").nextBytes(secret);
return secret;
} catch (NoSuchAlgorithmException e) {
throw new AssertionError(e);
}
}
public static String readFully(File file) throws IOException {
return readFully(new FileInputStream(file));
}
public static String readFully(InputStream in) throws IOException {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
byte[] buffer = new byte[4096];
int read;
while ((read = in.read(buffer)) != -1) {
bout.write(buffer, 0, read);
}
in.close();
return new String(bout.toByteArray());
}
public static void readFully(InputStream in, byte[] buffer) throws IOException {
int offset = 0;
for (;;) {
int read = in.read(buffer, offset, buffer.length - offset);
if (read + offset < buffer.length) offset += read;
else return;
}
}
public static void copy(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[4096];
int read;
while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
in.close();
out.close();
}
public static String join(Collection<String> list, String delimiter) {
StringBuilder result = new StringBuilder();
int i=0;
for (String item : list) {
result.append(item);
if (++i < list.size())
result.append(delimiter);
}
return result.toString();
}
public static List<String> split(String source, String delimiter) {
List<String> results = new LinkedList<String>();
if (isEmpty(source)) {
return results;
}
String[] elements = source.split(delimiter);
for (String element : elements) {
results.add(element);
}
return results;
}
public static String getDeviceE164Number(Context context) {
String localNumber = ((TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE))
.getLine1Number();
if (!org.whispersystems.textsecure.util.Util.isEmpty(localNumber) &&
!localNumber.startsWith("+"))
{
if (localNumber.length() == 10) localNumber = "+1" + localNumber;
else localNumber = "+" + localNumber;
return localNumber;
}
return null;
}
public static SecureRandom getSecureRandom() {
try {
return SecureRandom.getInstance("SHA1PRNG");
} catch (NoSuchAlgorithmException e) {
throw new AssertionError(e);
}
}
/*
* source: http://stackoverflow.com/a/9500334
*/
public static void fixBackgroundRepeat(Drawable bg) {
if (bg != null) {
if (bg instanceof BitmapDrawable) {
BitmapDrawable bmp = (BitmapDrawable) bg;
bmp.mutate();
bmp.setTileModeXY(Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
}
}
}
}