diff options
Diffstat (limited to 'src/eu/siacs/conversations/utils')
-rw-r--r-- | src/eu/siacs/conversations/utils/CryptoHelper.java | 40 | ||||
-rw-r--r-- | src/eu/siacs/conversations/utils/DNSHelper.java | 50 | ||||
-rw-r--r-- | src/eu/siacs/conversations/utils/ExceptionHandler.java | 17 | ||||
-rw-r--r-- | src/eu/siacs/conversations/utils/ExceptionHelper.java | 107 | ||||
-rw-r--r-- | src/eu/siacs/conversations/utils/PRNGFixes.java | 539 | ||||
-rw-r--r-- | src/eu/siacs/conversations/utils/PhoneHelper.java | 13 | ||||
-rw-r--r-- | src/eu/siacs/conversations/utils/UIHelper.java | 14 | ||||
-rw-r--r-- | src/eu/siacs/conversations/utils/Validator.java | 6 | ||||
-rw-r--r-- | src/eu/siacs/conversations/utils/zlib/ZLibInputStream.java | 72 | ||||
-rw-r--r-- | src/eu/siacs/conversations/utils/zlib/ZLibOutputStream.java | 135 |
10 files changed, 516 insertions, 477 deletions
diff --git a/src/eu/siacs/conversations/utils/CryptoHelper.java b/src/eu/siacs/conversations/utils/CryptoHelper.java index a70b419e..a28b519e 100644 --- a/src/eu/siacs/conversations/utils/CryptoHelper.java +++ b/src/eu/siacs/conversations/utils/CryptoHelper.java @@ -11,7 +11,7 @@ import eu.siacs.conversations.entities.Account; import android.util.Base64; public class CryptoHelper { - public static final String FILETRANSFER = "?FILETRANSFERv1:"; + public static final String FILETRANSFER = "?FILETRANSFERv1:"; final protected static char[] hexArray = "0123456789abcdef".toCharArray(); final protected static char[] vowels = "aeiou".toCharArray(); final protected static char[] consonants = "bcdfghjklmnpqrstvwxyz" @@ -26,7 +26,7 @@ public class CryptoHelper { } return new String(hexChars); } - + public static byte[] hexToBytes(String hexString) { byte[] array = new BigInteger(hexString, 16).toByteArray(); if (array[0] == 0) { @@ -42,13 +42,14 @@ public class CryptoHelper { } private static byte[] concatenateByteArrays(byte[] a, byte[] b) { - byte[] result = new byte[a.length + b.length]; - System.arraycopy(a, 0, result, 0, a.length); - System.arraycopy(b, 0, result, a.length, b.length); - return result; - } - - public static String saslDigestMd5(Account account, String challenge, SecureRandom random) { + byte[] result = new byte[a.length + b.length]; + System.arraycopy(a, 0, result, 0, a.length); + System.arraycopy(b, 0, result, a.length, b.length); + return result; + } + + public static String saslDigestMd5(Account account, String challenge, + SecureRandom random) { try { String[] challengeParts = new String(Base64.decode(challenge, Base64.DEFAULT)).split(","); @@ -61,28 +62,29 @@ public class CryptoHelper { return null; } } - String digestUri = "xmpp/"+account.getServer(); + String digestUri = "xmpp/" + account.getServer(); String nonceCount = "00000001"; String x = account.getUsername() + ":" + account.getServer() + ":" + account.getPassword(); MessageDigest md = MessageDigest.getInstance("MD5"); - byte[] y = md - .digest(x.getBytes(Charset.defaultCharset())); + byte[] y = md.digest(x.getBytes(Charset.defaultCharset())); String cNonce = new BigInteger(100, random).toString(32); - byte[] a1 = concatenateByteArrays(y,(":"+nonce+":"+cNonce).getBytes(Charset.defaultCharset())); - String a2 = "AUTHENTICATE:"+digestUri; + byte[] a1 = concatenateByteArrays(y, + (":" + nonce + ":" + cNonce).getBytes(Charset + .defaultCharset())); + String a2 = "AUTHENTICATE:" + digestUri; String ha1 = bytesToHex(md.digest(a1)); String ha2 = bytesToHex(md.digest(a2.getBytes(Charset .defaultCharset()))); - String kd = ha1 + ":" + nonce + ":"+nonceCount+":" + cNonce + ":auth:" - + ha2; + String kd = ha1 + ":" + nonce + ":" + nonceCount + ":" + cNonce + + ":auth:" + ha2; String response = bytesToHex(md.digest(kd.getBytes(Charset .defaultCharset()))); String saslString = "username=\"" + account.getUsername() + "\",realm=\"" + account.getServer() + "\",nonce=\"" - + nonce + "\",cnonce=\"" + cNonce - + "\",nc="+nonceCount+",qop=auth,digest-uri=\""+digestUri+"\",response=" + response - + ",charset=utf-8"; + + nonce + "\",cnonce=\"" + cNonce + "\",nc=" + nonceCount + + ",qop=auth,digest-uri=\"" + digestUri + "\",response=" + + response + ",charset=utf-8"; return Base64.encodeToString( saslString.getBytes(Charset.defaultCharset()), Base64.NO_WRAP); diff --git a/src/eu/siacs/conversations/utils/DNSHelper.java b/src/eu/siacs/conversations/utils/DNSHelper.java index 002e124f..fd3b1953 100644 --- a/src/eu/siacs/conversations/utils/DNSHelper.java +++ b/src/eu/siacs/conversations/utils/DNSHelper.java @@ -10,6 +10,7 @@ import de.measite.minidns.record.A; import de.measite.minidns.record.AAAA; import de.measite.minidns.record.Data; import de.measite.minidns.util.NameUtil; +import eu.siacs.conversations.Config; import java.io.IOException; import java.net.InetAddress; @@ -47,14 +48,11 @@ public class DNSHelper { Bundle namePort = new Bundle(); try { String qname = "_xmpp-client._tcp." + host; - Log.d("xmppService", "using dns server: " + dnsServer.getHostAddress() - + " to look up " + host); - DNSMessage message = - client.query( - qname, - TYPE.SRV, - CLASS.IN, - dnsServer.getHostAddress()); + Log.d(Config.LOGTAG, + "using dns server: " + dnsServer.getHostAddress() + + " to look up " + host); + DNSMessage message = client.query(qname, TYPE.SRV, CLASS.IN, + dnsServer.getHostAddress()); // How should we handle priorities and weight? // Wikipedia has a nice article about priorities vs. weights: @@ -64,21 +62,20 @@ public class DNSHelper { // a random order respecting the weight, and dump that priority by // priority - TreeMap<Integer, ArrayList<SRV>> priorities = - new TreeMap<Integer, ArrayList<SRV>>(); - TreeMap<String, ArrayList<String>> ips4 = - new TreeMap<String, ArrayList<String>>(); - TreeMap<String, ArrayList<String>> ips6 = - new TreeMap<String, ArrayList<String>>(); + TreeMap<Integer, ArrayList<SRV>> priorities = new TreeMap<Integer, ArrayList<SRV>>(); + TreeMap<String, ArrayList<String>> ips4 = new TreeMap<String, ArrayList<String>>(); + TreeMap<String, ArrayList<String>> ips6 = new TreeMap<String, ArrayList<String>>(); - for (Record[] rrset : new Record[][]{ message.getAnswers(), - message.getAdditionalResourceRecords()}) { + for (Record[] rrset : new Record[][] { message.getAnswers(), + message.getAdditionalResourceRecords() }) { for (Record rr : rrset) { Data d = rr.getPayload(); - if (d instanceof SRV && NameUtil.idnEquals(qname,rr.getName())) { + if (d instanceof SRV + && NameUtil.idnEquals(qname, rr.getName())) { SRV srv = (SRV) d; if (!priorities.containsKey(srv.getPriority())) { - priorities.put(srv.getPriority(), new ArrayList<SRV>(2)); + priorities.put(srv.getPriority(), + new ArrayList<SRV>(2)); } priorities.get(srv.getPriority()).add(srv); } @@ -100,8 +97,9 @@ public class DNSHelper { } Random rnd = new Random(); - ArrayList<SRV> result = new ArrayList<SRV>(priorities.size() * 2 + 1); - for (ArrayList<SRV> s: priorities.values()) { + ArrayList<SRV> result = new ArrayList<SRV>( + priorities.size() * 2 + 1); + for (ArrayList<SRV> s : priorities.values()) { // trivial case if (s.size() <= 1) { @@ -110,18 +108,20 @@ public class DNSHelper { } long totalweight = 0l; - for (SRV srv: s) { + for (SRV srv : s) { totalweight += srv.getWeight(); } while (totalweight > 0l && s.size() > 0) { - long p = (rnd.nextLong() & 0x7fffffffffffffffl) % totalweight; + long p = (rnd.nextLong() & 0x7fffffffffffffffl) + % totalweight; int i = 0; while (p > 0) { p -= s.get(i++).getPriority(); } i--; - // remove is expensive, but we have only a few entries anyway + // remove is expensive, but we have only a few entries + // anyway SRV srv = s.remove(i); totalweight -= srv.getWeight(); result.add(srv); @@ -164,10 +164,10 @@ public class DNSHelper { } } catch (SocketTimeoutException e) { - Log.d("xmppService", "timeout during dns"); + Log.d(Config.LOGTAG, "timeout during dns"); namePort.putString("error", "timeout"); } catch (Exception e) { - Log.d("xmppService","unhandled exception in sub project"); + Log.d(Config.LOGTAG, "unhandled exception in sub project"); namePort.putString("error", "unhandled"); } return namePort; diff --git a/src/eu/siacs/conversations/utils/ExceptionHandler.java b/src/eu/siacs/conversations/utils/ExceptionHandler.java index 01cfebbb..88fa18ff 100644 --- a/src/eu/siacs/conversations/utils/ExceptionHandler.java +++ b/src/eu/siacs/conversations/utils/ExceptionHandler.java @@ -11,22 +11,25 @@ import java.lang.Thread.UncaughtExceptionHandler; import android.content.Context; public class ExceptionHandler implements UncaughtExceptionHandler { - + private UncaughtExceptionHandler defaultHandler; private Context context; + public ExceptionHandler(Context context) { this.context = context; this.defaultHandler = Thread.getDefaultUncaughtExceptionHandler(); } + @Override public void uncaughtException(Thread thread, Throwable ex) { Writer result = new StringWriter(); - PrintWriter printWriter = new PrintWriter(result); - ex.printStackTrace(printWriter); - String stacktrace = result.toString(); - printWriter.close(); - try { - OutputStream os = context.openFileOutput("stacktrace.txt",Context.MODE_PRIVATE); + PrintWriter printWriter = new PrintWriter(result); + ex.printStackTrace(printWriter); + String stacktrace = result.toString(); + printWriter.close(); + try { + OutputStream os = context.openFileOutput("stacktrace.txt", + Context.MODE_PRIVATE); os.write(stacktrace.getBytes()); } catch (FileNotFoundException e) { // TODO Auto-generated catch block diff --git a/src/eu/siacs/conversations/utils/ExceptionHelper.java b/src/eu/siacs/conversations/utils/ExceptionHelper.java index 373aadd3..b5fc88bd 100644 --- a/src/eu/siacs/conversations/utils/ExceptionHelper.java +++ b/src/eu/siacs/conversations/utils/ExceptionHelper.java @@ -7,6 +7,7 @@ import java.io.IOException; import java.io.InputStreamReader; import java.util.List; +import eu.siacs.conversations.Config; import eu.siacs.conversations.R; import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Conversation; @@ -26,77 +27,91 @@ import android.util.Log; public class ExceptionHelper { public static void init(Context context) { - if(!(Thread.getDefaultUncaughtExceptionHandler() instanceof ExceptionHandler)) { - Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler(context)); + if (!(Thread.getDefaultUncaughtExceptionHandler() instanceof ExceptionHandler)) { + Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler( + context)); } } - - public static void checkForCrash(Context context, final XmppConnectionService service) { + + public static void checkForCrash(Context context, + final XmppConnectionService service) { try { - final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); - boolean neverSend = preferences.getBoolean("never_send",false); + final SharedPreferences preferences = PreferenceManager + .getDefaultSharedPreferences(context); + boolean neverSend = preferences.getBoolean("never_send", false); if (neverSend) { return; } List<Account> accounts = service.getAccounts(); Account account = null; - for(int i = 0; i < accounts.size(); ++i) { + for (int i = 0; i < accounts.size(); ++i) { if (!accounts.get(i).isOptionSet(Account.OPTION_DISABLED)) { account = accounts.get(i); break; } } - if (account==null) { + if (account == null) { return; } final Account finalAccount = account; FileInputStream file = context.openFileInput("stacktrace.txt"); - InputStreamReader inputStreamReader = new InputStreamReader( - file); - BufferedReader stacktrace = new BufferedReader( - inputStreamReader); - final StringBuilder report = new StringBuilder(); - PackageManager pm = context.getPackageManager(); - PackageInfo packageInfo = null; - try { - packageInfo = pm.getPackageInfo(context.getPackageName(), 0); - report.append("Version: "+packageInfo.versionName+'\n'); - report.append("Last Update: "+DateUtils.formatDateTime(context, packageInfo.lastUpdateTime, DateUtils.FORMAT_SHOW_TIME|DateUtils.FORMAT_SHOW_DATE)+'\n'); - } catch (NameNotFoundException e) {} - String line; - while((line = stacktrace.readLine()) != null) { - report.append(line); - report.append('\n'); - } - file.close(); - context.deleteFile("stacktrace.txt"); + InputStreamReader inputStreamReader = new InputStreamReader(file); + BufferedReader stacktrace = new BufferedReader(inputStreamReader); + final StringBuilder report = new StringBuilder(); + PackageManager pm = context.getPackageManager(); + PackageInfo packageInfo = null; + try { + packageInfo = pm.getPackageInfo(context.getPackageName(), 0); + report.append("Version: " + packageInfo.versionName + '\n'); + report.append("Last Update: " + + DateUtils.formatDateTime(context, + packageInfo.lastUpdateTime, + DateUtils.FORMAT_SHOW_TIME + | DateUtils.FORMAT_SHOW_DATE) + '\n'); + } catch (NameNotFoundException e) { + } + String line; + while ((line = stacktrace.readLine()) != null) { + report.append(line); + report.append('\n'); + } + file.close(); + context.deleteFile("stacktrace.txt"); AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle(context.getString(R.string.crash_report_title)); builder.setMessage(context.getText(R.string.crash_report_message)); - builder.setPositiveButton(context.getText(R.string.send_now), new OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, int which) { - - Log.d("xmppService","using account="+finalAccount.getJid()+" to send in stack trace"); - Conversation conversation = service.findOrCreateConversation(finalAccount, "bugs@siacs.eu", false); - Message message = new Message(conversation, report.toString(), Message.ENCRYPTION_NONE); - service.sendMessage(message); - } - }); - builder.setNegativeButton(context.getText(R.string.send_never),new OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, int which) { - preferences.edit().putBoolean("never_send", true).commit(); - } - }); + builder.setPositiveButton(context.getText(R.string.send_now), + new OnClickListener() { + + @Override + public void onClick(DialogInterface dialog, int which) { + + Log.d(Config.LOGTAG, "using account=" + + finalAccount.getJid() + + " to send in stack trace"); + Conversation conversation = service + .findOrCreateConversation(finalAccount, + "bugs@siacs.eu", false); + Message message = new Message(conversation, report + .toString(), Message.ENCRYPTION_NONE); + service.sendMessage(message); + } + }); + builder.setNegativeButton(context.getText(R.string.send_never), + new OnClickListener() { + + @Override + public void onClick(DialogInterface dialog, int which) { + preferences.edit().putBoolean("never_send", true) + .commit(); + } + }); builder.create().show(); } catch (FileNotFoundException e) { return; } catch (IOException e) { return; } - + } } diff --git a/src/eu/siacs/conversations/utils/PRNGFixes.java b/src/eu/siacs/conversations/utils/PRNGFixes.java index cf28ff30..8fe67234 100644 --- a/src/eu/siacs/conversations/utils/PRNGFixes.java +++ b/src/eu/siacs/conversations/utils/PRNGFixes.java @@ -21,306 +21,307 @@ import java.security.Security; /** * Fixes for the output of the default PRNG having low entropy. - * + * * The fixes need to be applied via {@link #apply()} before any use of Java * Cryptography Architecture primitives. A good place to invoke them is in the * application's {@code onCreate}. */ public final class PRNGFixes { - private static final int VERSION_CODE_JELLY_BEAN = 16; - private static final int VERSION_CODE_JELLY_BEAN_MR2 = 18; - private static final byte[] BUILD_FINGERPRINT_AND_DEVICE_SERIAL = - getBuildFingerprintAndDeviceSerial(); + private static final int VERSION_CODE_JELLY_BEAN = 16; + private static final int VERSION_CODE_JELLY_BEAN_MR2 = 18; + private static final byte[] BUILD_FINGERPRINT_AND_DEVICE_SERIAL = getBuildFingerprintAndDeviceSerial(); - /** Hidden constructor to prevent instantiation. */ - private PRNGFixes() {} + /** Hidden constructor to prevent instantiation. */ + private PRNGFixes() { + } - /** - * Applies all fixes. - * - * @throws SecurityException if a fix is needed but could not be applied. - */ - public static void apply() { - applyOpenSSLFix(); - installLinuxPRNGSecureRandom(); - } + /** + * Applies all fixes. + * + * @throws SecurityException + * if a fix is needed but could not be applied. + */ + public static void apply() { + applyOpenSSLFix(); + installLinuxPRNGSecureRandom(); + } - /** - * Applies the fix for OpenSSL PRNG having low entropy. Does nothing if the - * fix is not needed. - * - * @throws SecurityException if the fix is needed but could not be applied. - */ - private static void applyOpenSSLFix() throws SecurityException { - if ((Build.VERSION.SDK_INT < VERSION_CODE_JELLY_BEAN) - || (Build.VERSION.SDK_INT > VERSION_CODE_JELLY_BEAN_MR2)) { - // No need to apply the fix - return; - } + /** + * Applies the fix for OpenSSL PRNG having low entropy. Does nothing if the + * fix is not needed. + * + * @throws SecurityException + * if the fix is needed but could not be applied. + */ + private static void applyOpenSSLFix() throws SecurityException { + if ((Build.VERSION.SDK_INT < VERSION_CODE_JELLY_BEAN) + || (Build.VERSION.SDK_INT > VERSION_CODE_JELLY_BEAN_MR2)) { + // No need to apply the fix + return; + } - try { - // Mix in the device- and invocation-specific seed. - Class.forName("org.apache.harmony.xnet.provider.jsse.NativeCrypto") - .getMethod("RAND_seed", byte[].class) - .invoke(null, generateSeed()); + try { + // Mix in the device- and invocation-specific seed. + Class.forName("org.apache.harmony.xnet.provider.jsse.NativeCrypto") + .getMethod("RAND_seed", byte[].class) + .invoke(null, generateSeed()); - // Mix output of Linux PRNG into OpenSSL's PRNG - int bytesRead = (Integer) Class.forName( - "org.apache.harmony.xnet.provider.jsse.NativeCrypto") - .getMethod("RAND_load_file", String.class, long.class) - .invoke(null, "/dev/urandom", 1024); - if (bytesRead != 1024) { - throw new IOException( - "Unexpected number of bytes read from Linux PRNG: " - + bytesRead); - } - } catch (Exception e) { - throw new SecurityException("Failed to seed OpenSSL PRNG", e); - } - } + // Mix output of Linux PRNG into OpenSSL's PRNG + int bytesRead = (Integer) Class + .forName( + "org.apache.harmony.xnet.provider.jsse.NativeCrypto") + .getMethod("RAND_load_file", String.class, long.class) + .invoke(null, "/dev/urandom", 1024); + if (bytesRead != 1024) { + throw new IOException( + "Unexpected number of bytes read from Linux PRNG: " + + bytesRead); + } + } catch (Exception e) { + throw new SecurityException("Failed to seed OpenSSL PRNG", e); + } + } - /** - * Installs a Linux PRNG-backed {@code SecureRandom} implementation as the - * default. Does nothing if the implementation is already the default or if - * there is not need to install the implementation. - * - * @throws SecurityException if the fix is needed but could not be applied. - */ - private static void installLinuxPRNGSecureRandom() - throws SecurityException { - if (Build.VERSION.SDK_INT > VERSION_CODE_JELLY_BEAN_MR2) { - // No need to apply the fix - return; - } + /** + * Installs a Linux PRNG-backed {@code SecureRandom} implementation as the + * default. Does nothing if the implementation is already the default or if + * there is not need to install the implementation. + * + * @throws SecurityException + * if the fix is needed but could not be applied. + */ + private static void installLinuxPRNGSecureRandom() throws SecurityException { + if (Build.VERSION.SDK_INT > VERSION_CODE_JELLY_BEAN_MR2) { + // No need to apply the fix + return; + } - // Install a Linux PRNG-based SecureRandom implementation as the - // default, if not yet installed. - Provider[] secureRandomProviders = - Security.getProviders("SecureRandom.SHA1PRNG"); - if ((secureRandomProviders == null) - || (secureRandomProviders.length < 1) - || (!LinuxPRNGSecureRandomProvider.class.equals( - secureRandomProviders[0].getClass()))) { - Security.insertProviderAt(new LinuxPRNGSecureRandomProvider(), 1); - } + // Install a Linux PRNG-based SecureRandom implementation as the + // default, if not yet installed. + Provider[] secureRandomProviders = Security + .getProviders("SecureRandom.SHA1PRNG"); + if ((secureRandomProviders == null) + || (secureRandomProviders.length < 1) + || (!LinuxPRNGSecureRandomProvider.class + .equals(secureRandomProviders[0].getClass()))) { + Security.insertProviderAt(new LinuxPRNGSecureRandomProvider(), 1); + } - // Assert that new SecureRandom() and - // SecureRandom.getInstance("SHA1PRNG") return a SecureRandom backed - // by the Linux PRNG-based SecureRandom implementation. - SecureRandom rng1 = new SecureRandom(); - if (!LinuxPRNGSecureRandomProvider.class.equals( - rng1.getProvider().getClass())) { - throw new SecurityException( - "new SecureRandom() backed by wrong Provider: " - + rng1.getProvider().getClass()); - } + // Assert that new SecureRandom() and + // SecureRandom.getInstance("SHA1PRNG") return a SecureRandom backed + // by the Linux PRNG-based SecureRandom implementation. + SecureRandom rng1 = new SecureRandom(); + if (!LinuxPRNGSecureRandomProvider.class.equals(rng1.getProvider() + .getClass())) { + throw new SecurityException( + "new SecureRandom() backed by wrong Provider: " + + rng1.getProvider().getClass()); + } - SecureRandom rng2; - try { - rng2 = SecureRandom.getInstance("SHA1PRNG"); - } catch (NoSuchAlgorithmException e) { - throw new SecurityException("SHA1PRNG not available", e); - } - if (!LinuxPRNGSecureRandomProvider.class.equals( - rng2.getProvider().getClass())) { - throw new SecurityException( - "SecureRandom.getInstance(\"SHA1PRNG\") backed by wrong" - + " Provider: " + rng2.getProvider().getClass()); - } - } + SecureRandom rng2; + try { + rng2 = SecureRandom.getInstance("SHA1PRNG"); + } catch (NoSuchAlgorithmException e) { + throw new SecurityException("SHA1PRNG not available", e); + } + if (!LinuxPRNGSecureRandomProvider.class.equals(rng2.getProvider() + .getClass())) { + throw new SecurityException( + "SecureRandom.getInstance(\"SHA1PRNG\") backed by wrong" + + " Provider: " + rng2.getProvider().getClass()); + } + } - /** - * {@code Provider} of {@code SecureRandom} engines which pass through - * all requests to the Linux PRNG. - */ - private static class LinuxPRNGSecureRandomProvider extends Provider { + /** + * {@code Provider} of {@code SecureRandom} engines which pass through all + * requests to the Linux PRNG. + */ + private static class LinuxPRNGSecureRandomProvider extends Provider { - public LinuxPRNGSecureRandomProvider() { - super("LinuxPRNG", - 1.0, - "A Linux-specific random number provider that uses" - + " /dev/urandom"); - // Although /dev/urandom is not a SHA-1 PRNG, some apps - // explicitly request a SHA1PRNG SecureRandom and we thus need to - // prevent them from getting the default implementation whose output - // may have low entropy. - put("SecureRandom.SHA1PRNG", LinuxPRNGSecureRandom.class.getName()); - put("SecureRandom.SHA1PRNG ImplementedIn", "Software"); - } - } + public LinuxPRNGSecureRandomProvider() { + super("LinuxPRNG", 1.0, + "A Linux-specific random number provider that uses" + + " /dev/urandom"); + // Although /dev/urandom is not a SHA-1 PRNG, some apps + // explicitly request a SHA1PRNG SecureRandom and we thus need to + // prevent them from getting the default implementation whose output + // may have low entropy. + put("SecureRandom.SHA1PRNG", LinuxPRNGSecureRandom.class.getName()); + put("SecureRandom.SHA1PRNG ImplementedIn", "Software"); + } + } - /** - * {@link SecureRandomSpi} which passes all requests to the Linux PRNG - * ({@code /dev/urandom}). - */ - public static class LinuxPRNGSecureRandom extends SecureRandomSpi { + /** + * {@link SecureRandomSpi} which passes all requests to the Linux PRNG ( + * {@code /dev/urandom}). + */ + public static class LinuxPRNGSecureRandom extends SecureRandomSpi { - /* - * IMPLEMENTATION NOTE: Requests to generate bytes and to mix in a seed - * are passed through to the Linux PRNG (/dev/urandom). Instances of - * this class seed themselves by mixing in the current time, PID, UID, - * build fingerprint, and hardware serial number (where available) into - * Linux PRNG. - * - * Concurrency: Read requests to the underlying Linux PRNG are - * serialized (on sLock) to ensure that multiple threads do not get - * duplicated PRNG output. - */ + /* + * IMPLEMENTATION NOTE: Requests to generate bytes and to mix in a seed + * are passed through to the Linux PRNG (/dev/urandom). Instances of + * this class seed themselves by mixing in the current time, PID, UID, + * build fingerprint, and hardware serial number (where available) into + * Linux PRNG. + * + * Concurrency: Read requests to the underlying Linux PRNG are + * serialized (on sLock) to ensure that multiple threads do not get + * duplicated PRNG output. + */ - private static final File URANDOM_FILE = new File("/dev/urandom"); + private static final File URANDOM_FILE = new File("/dev/urandom"); - private static final Object sLock = new Object(); + private static final Object sLock = new Object(); - /** - * Input stream for reading from Linux PRNG or {@code null} if not yet - * opened. - * - * @GuardedBy("sLock") - */ - private static DataInputStream sUrandomIn; + /** + * Input stream for reading from Linux PRNG or {@code null} if not yet + * opened. + * + * @GuardedBy("sLock") + */ + private static DataInputStream sUrandomIn; - /** - * Output stream for writing to Linux PRNG or {@code null} if not yet - * opened. - * - * @GuardedBy("sLock") - */ - private static OutputStream sUrandomOut; + /** + * Output stream for writing to Linux PRNG or {@code null} if not yet + * opened. + * + * @GuardedBy("sLock") + */ + private static OutputStream sUrandomOut; - /** - * Whether this engine instance has been seeded. This is needed because - * each instance needs to seed itself if the client does not explicitly - * seed it. - */ - private boolean mSeeded; + /** + * Whether this engine instance has been seeded. This is needed because + * each instance needs to seed itself if the client does not explicitly + * seed it. + */ + private boolean mSeeded; - @Override - protected void engineSetSeed(byte[] bytes) { - try { - OutputStream out; - synchronized (sLock) { - out = getUrandomOutputStream(); - } - out.write(bytes); - out.flush(); - } catch (IOException e) { - // On a small fraction of devices /dev/urandom is not writable. - // Log and ignore. - Log.w(PRNGFixes.class.getSimpleName(), - "Failed to mix seed into " + URANDOM_FILE); - } finally { - mSeeded = true; - } - } + @Override + protected void engineSetSeed(byte[] bytes) { + try { + OutputStream out; + synchronized (sLock) { + out = getUrandomOutputStream(); + } + out.write(bytes); + out.flush(); + } catch (IOException e) { + // On a small fraction of devices /dev/urandom is not writable. + // Log and ignore. + Log.w(PRNGFixes.class.getSimpleName(), + "Failed to mix seed into " + URANDOM_FILE); + } finally { + mSeeded = true; + } + } - @Override - protected void engineNextBytes(byte[] bytes) { - if (!mSeeded) { - // Mix in the device- and invocation-specific seed. - engineSetSeed(generateSeed()); - } + @Override + protected void engineNextBytes(byte[] bytes) { + if (!mSeeded) { + // Mix in the device- and invocation-specific seed. + engineSetSeed(generateSeed()); + } - try { - DataInputStream in; - synchronized (sLock) { - in = getUrandomInputStream(); - } - synchronized (in) { - in.readFully(bytes); - } - } catch (IOException e) { - throw new SecurityException( - "Failed to read from " + URANDOM_FILE, e); - } - } + try { + DataInputStream in; + synchronized (sLock) { + in = getUrandomInputStream(); + } + synchronized (in) { + in.readFully(bytes); + } + } catch (IOException e) { + throw new SecurityException("Failed to read from " + + URANDOM_FILE, e); + } + } - @Override - protected byte[] engineGenerateSeed(int size) { - byte[] seed = new byte[size]; - engineNextBytes(seed); - return seed; - } + @Override + protected byte[] engineGenerateSeed(int size) { + byte[] seed = new byte[size]; + engineNextBytes(seed); + return seed; + } - private DataInputStream getUrandomInputStream() { - synchronized (sLock) { - if (sUrandomIn == null) { - // NOTE: Consider inserting a BufferedInputStream between - // DataInputStream and FileInputStream if you need higher - // PRNG output performance and can live with future PRNG - // output being pulled into this process prematurely. - try { - sUrandomIn = new DataInputStream( - new FileInputStream(URANDOM_FILE)); - } catch (IOException e) { - throw new SecurityException("Failed to open " - + URANDOM_FILE + " for reading", e); - } - } - return sUrandomIn; - } - } + private DataInputStream getUrandomInputStream() { + synchronized (sLock) { + if (sUrandomIn == null) { + // NOTE: Consider inserting a BufferedInputStream between + // DataInputStream and FileInputStream if you need higher + // PRNG output performance and can live with future PRNG + // output being pulled into this process prematurely. + try { + sUrandomIn = new DataInputStream(new FileInputStream( + URANDOM_FILE)); + } catch (IOException e) { + throw new SecurityException("Failed to open " + + URANDOM_FILE + " for reading", e); + } + } + return sUrandomIn; + } + } - private OutputStream getUrandomOutputStream() throws IOException { - synchronized (sLock) { - if (sUrandomOut == null) { - sUrandomOut = new FileOutputStream(URANDOM_FILE); - } - return sUrandomOut; - } - } - } + private OutputStream getUrandomOutputStream() throws IOException { + synchronized (sLock) { + if (sUrandomOut == null) { + sUrandomOut = new FileOutputStream(URANDOM_FILE); + } + return sUrandomOut; + } + } + } - /** - * Generates a device- and invocation-specific seed to be mixed into the - * Linux PRNG. - */ - private static byte[] generateSeed() { - try { - ByteArrayOutputStream seedBuffer = new ByteArrayOutputStream(); - DataOutputStream seedBufferOut = - new DataOutputStream(seedBuffer); - seedBufferOut.writeLong(System.currentTimeMillis()); - seedBufferOut.writeLong(System.nanoTime()); - seedBufferOut.writeInt(Process.myPid()); - seedBufferOut.writeInt(Process.myUid()); - seedBufferOut.write(BUILD_FINGERPRINT_AND_DEVICE_SERIAL); - seedBufferOut.close(); - return seedBuffer.toByteArray(); - } catch (IOException e) { - throw new SecurityException("Failed to generate seed", e); - } - } + /** + * Generates a device- and invocation-specific seed to be mixed into the + * Linux PRNG. + */ + private static byte[] generateSeed() { + try { + ByteArrayOutputStream seedBuffer = new ByteArrayOutputStream(); + DataOutputStream seedBufferOut = new DataOutputStream(seedBuffer); + seedBufferOut.writeLong(System.currentTimeMillis()); + seedBufferOut.writeLong(System.nanoTime()); + seedBufferOut.writeInt(Process.myPid()); + seedBufferOut.writeInt(Process.myUid()); + seedBufferOut.write(BUILD_FINGERPRINT_AND_DEVICE_SERIAL); + seedBufferOut.close(); + return seedBuffer.toByteArray(); + } catch (IOException e) { + throw new SecurityException("Failed to generate seed", e); + } + } - /** - * Gets the hardware serial number of this device. - * - * @return serial number or {@code null} if not available. - */ - private static String getDeviceSerialNumber() { - // We're using the Reflection API because Build.SERIAL is only available - // since API Level 9 (Gingerbread, Android 2.3). - try { - return (String) Build.class.getField("SERIAL").get(null); - } catch (Exception ignored) { - return null; - } - } + /** + * Gets the hardware serial number of this device. + * + * @return serial number or {@code null} if not available. + */ + private static String getDeviceSerialNumber() { + // We're using the Reflection API because Build.SERIAL is only available + // since API Level 9 (Gingerbread, Android 2.3). + try { + return (String) Build.class.getField("SERIAL").get(null); + } catch (Exception ignored) { + return null; + } + } - private static byte[] getBuildFingerprintAndDeviceSerial() { - StringBuilder result = new StringBuilder(); - String fingerprint = Build.FINGERPRINT; - if (fingerprint != null) { - result.append(fingerprint); - } - String serial = getDeviceSerialNumber(); - if (serial != null) { - result.append(serial); - } - try { - return result.toString().getBytes("UTF-8"); - } catch (UnsupportedEncodingException e) { - throw new RuntimeException("UTF-8 encoding not supported"); - } - } + private static byte[] getBuildFingerprintAndDeviceSerial() { + StringBuilder result = new StringBuilder(); + String fingerprint = Build.FINGERPRINT; + if (fingerprint != null) { + result.append(fingerprint); + } + String serial = getDeviceSerialNumber(); + if (serial != null) { + result.append(serial); + } + try { + return result.toString().getBytes("UTF-8"); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException("UTF-8 encoding not supported"); + } + } }
\ No newline at end of file diff --git a/src/eu/siacs/conversations/utils/PhoneHelper.java b/src/eu/siacs/conversations/utils/PhoneHelper.java index 63c17761..975fa219 100644 --- a/src/eu/siacs/conversations/utils/PhoneHelper.java +++ b/src/eu/siacs/conversations/utils/PhoneHelper.java @@ -18,7 +18,7 @@ public class PhoneHelper { public static void loadPhoneContacts(Context context, final OnPhoneContactsLoadedListener listener) { final List<Bundle> phoneContacts = new ArrayList<Bundle>(); - + final String[] PROJECTION = new String[] { ContactsContract.Data._ID, ContactsContract.Data.DISPLAY_NAME, ContactsContract.Data.PHOTO_THUMBNAIL_URI, @@ -38,7 +38,7 @@ public class PhoneHelper { @Override public void onLoadComplete(Loader<Cursor> arg0, Cursor cursor) { - if (cursor==null) { + if (cursor == null) { return; } while (cursor.moveToNext()) { @@ -55,8 +55,10 @@ public class PhoneHelper { .getColumnIndex(ContactsContract.Data.PHOTO_THUMBNAIL_URI))); contact.putString("lookup", cursor.getString(cursor .getColumnIndex(ContactsContract.Data.LOOKUP_KEY))); - - contact.putString("jid",cursor.getString(cursor + + contact.putString( + "jid", + cursor.getString(cursor .getColumnIndex(ContactsContract.CommonDataKinds.Im.DATA))); phoneContacts.add(contact); } @@ -69,8 +71,7 @@ public class PhoneHelper { } public static Uri getSefliUri(Context context) { - String[] mProjection = new String[] { Profile._ID, - Profile.PHOTO_URI }; + String[] mProjection = new String[] { Profile._ID, Profile.PHOTO_URI }; Cursor mProfileCursor = context.getContentResolver().query( Profile.CONTENT_URI, mProjection, null, null, null); diff --git a/src/eu/siacs/conversations/utils/UIHelper.java b/src/eu/siacs/conversations/utils/UIHelper.java index 7a807b2f..1f584fe5 100644 --- a/src/eu/siacs/conversations/utils/UIHelper.java +++ b/src/eu/siacs/conversations/utils/UIHelper.java @@ -118,9 +118,13 @@ public class UIHelper { } private static int getNameColor(String name) { - /*int holoColors[] = { 0xFF1da9da, 0xFFb368d9, 0xFF83b600, 0xFFffa713, - 0xFFe92727 };*/ - int holoColors[] = {0xFFe91e63, 0xFF9c27b0, 0xFF673ab7, 0xFF3f51b5, 0xFF5677fc, 0xFF03a9f4, 0xFF00bcd4, 0xFF009688, 0xFFff5722, 0xFF795548, 0xFF607d8b}; + /* + * int holoColors[] = { 0xFF1da9da, 0xFFb368d9, 0xFF83b600, 0xFFffa713, + * 0xFFe92727 }; + */ + int holoColors[] = { 0xFFe91e63, 0xFF9c27b0, 0xFF673ab7, 0xFF3f51b5, + 0xFF5677fc, 0xFF03a9f4, 0xFF00bcd4, 0xFF009688, 0xFFff5722, + 0xFF795548, 0xFF607d8b }; return holoColors[(int) ((name.hashCode() & 0xffffffffl) % holoColors.length)]; } @@ -216,9 +220,9 @@ public class UIHelper { } ArrayList<String> names = new ArrayList<String>(); names.add(conversation.getMucOptions().getActualNick()); - for(User user : members) { + for (User user : members) { names.add(user.getName()); - if (names.size() > 4 ) { + if (names.size() > 4) { break; } } diff --git a/src/eu/siacs/conversations/utils/Validator.java b/src/eu/siacs/conversations/utils/Validator.java index a1a119e7..00130fa2 100644 --- a/src/eu/siacs/conversations/utils/Validator.java +++ b/src/eu/siacs/conversations/utils/Validator.java @@ -4,9 +4,9 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; public class Validator { - public static final Pattern VALID_JID = - Pattern.compile("^[^@/<>'\"\\s]+@[^@/<>'\"\\s]+$", Pattern.CASE_INSENSITIVE); - + public static final Pattern VALID_JID = Pattern.compile( + "^[^@/<>'\"\\s]+@[^@/<>'\"\\s]+$", Pattern.CASE_INSENSITIVE); + public static boolean isValidJid(String jid) { Matcher matcher = VALID_JID.matcher(jid); return matcher.find(); diff --git a/src/eu/siacs/conversations/utils/zlib/ZLibInputStream.java b/src/eu/siacs/conversations/utils/zlib/ZLibInputStream.java index 2eebf6f4..b777c10c 100644 --- a/src/eu/siacs/conversations/utils/zlib/ZLibInputStream.java +++ b/src/eu/siacs/conversations/utils/zlib/ZLibInputStream.java @@ -12,41 +12,43 @@ import java.util.zip.InflaterInputStream; */ public class ZLibInputStream extends InflaterInputStream { - /** - * Construct a ZLibInputStream, reading data from the underlying stream. - * - * @param is The {@code InputStream} to read data from. - * @throws IOException If an {@code IOException} occurs. - */ - public ZLibInputStream(InputStream is) throws IOException { - super(is, new Inflater(), 512); - } + /** + * Construct a ZLibInputStream, reading data from the underlying stream. + * + * @param is + * The {@code InputStream} to read data from. + * @throws IOException + * If an {@code IOException} occurs. + */ + public ZLibInputStream(InputStream is) throws IOException { + super(is, new Inflater(), 512); + } - /** - * Provide a more InputStream compatible version of available. - * A return value of 1 means that it is likly to read one byte without - * blocking, 0 means that the system is known to block for more input. - * - * @return 0 if no data is available, 1 otherwise - * @throws IOException - */ - @Override - public int available() throws IOException { - /* This is one of the funny code blocks. - * InflaterInputStream.available violates the contract of - * InputStream.available, which breaks kXML2. - * - * I'm not sure who's to blame, oracle/sun for a broken api or the - * google guys for mixing a sun bug with a xml reader that can't handle - * it.... - * - * Anyway, this simple if breaks suns distorted reality, but helps - * to use the api as intended. - */ - if (inf.needsInput()) { - return 0; - } - return super.available(); - } + /** + * Provide a more InputStream compatible version of available. A return + * value of 1 means that it is likly to read one byte without blocking, 0 + * means that the system is known to block for more input. + * + * @return 0 if no data is available, 1 otherwise + * @throws IOException + */ + @Override + public int available() throws IOException { + /* + * This is one of the funny code blocks. InflaterInputStream.available + * violates the contract of InputStream.available, which breaks kXML2. + * + * I'm not sure who's to blame, oracle/sun for a broken api or the + * google guys for mixing a sun bug with a xml reader that can't handle + * it.... + * + * Anyway, this simple if breaks suns distorted reality, but helps to + * use the api as intended. + */ + if (inf.needsInput()) { + return 0; + } + return super.available(); + } } diff --git a/src/eu/siacs/conversations/utils/zlib/ZLibOutputStream.java b/src/eu/siacs/conversations/utils/zlib/ZLibOutputStream.java index cc64a5e6..8b3f5e68 100644 --- a/src/eu/siacs/conversations/utils/zlib/ZLibOutputStream.java +++ b/src/eu/siacs/conversations/utils/zlib/ZLibOutputStream.java @@ -9,76 +9,87 @@ import java.util.zip.Deflater; import java.util.zip.DeflaterOutputStream; /** - * <p>Android 2.2 includes Java7 FLUSH_SYNC option, which will be used by this + * <p> + * Android 2.2 includes Java7 FLUSH_SYNC option, which will be used by this * Implementation, preferable via reflection. The @hide was remove in API level - * 19. This class might thus go away in the future.</p> - * <p>Please use {@link ZLibOutputStream#SUPPORTED} to check for flush - * compatibility.</p> + * 19. This class might thus go away in the future. + * </p> + * <p> + * Please use {@link ZLibOutputStream#SUPPORTED} to check for flush + * compatibility. + * </p> */ public class ZLibOutputStream extends DeflaterOutputStream { - /** - * The reflection based flush method. - */ + /** + * The reflection based flush method. + */ - private final static Method method; - /** - * SUPPORTED is true if a flush compatible method exists. - */ - public final static boolean SUPPORTED; + private final static Method method; + /** + * SUPPORTED is true if a flush compatible method exists. + */ + public final static boolean SUPPORTED; - /** - * Static block to initialize {@link #SUPPORTED} and {@link #method}. - */ - static { - Method m = null; - try { - m = Deflater.class.getMethod("deflate", byte[].class, int.class, int.class, int.class); - } catch (SecurityException e) { - } catch (NoSuchMethodException e) { - } - method = m; - SUPPORTED = (method != null); - } + /** + * Static block to initialize {@link #SUPPORTED} and {@link #method}. + */ + static { + Method m = null; + try { + m = Deflater.class.getMethod("deflate", byte[].class, int.class, + int.class, int.class); + } catch (SecurityException e) { + } catch (NoSuchMethodException e) { + } + method = m; + SUPPORTED = (method != null); + } - /** - * Create a new ZLib compatible output stream wrapping the given low level - * stream. ZLib compatiblity means we will send a zlib header. - * @param os OutputStream The underlying stream. - * @throws IOException In case of a lowlevel transfer problem. - * @throws NoSuchAlgorithmException In case of a {@link Deflater} error. - */ - public ZLibOutputStream(OutputStream os) throws IOException, - NoSuchAlgorithmException { - super(os, new Deflater(Deflater.BEST_COMPRESSION)); - } + /** + * Create a new ZLib compatible output stream wrapping the given low level + * stream. ZLib compatiblity means we will send a zlib header. + * + * @param os + * OutputStream The underlying stream. + * @throws IOException + * In case of a lowlevel transfer problem. + * @throws NoSuchAlgorithmException + * In case of a {@link Deflater} error. + */ + public ZLibOutputStream(OutputStream os) throws IOException, + NoSuchAlgorithmException { + super(os, new Deflater(Deflater.BEST_COMPRESSION)); + } - /** - * Flush the given stream, preferring Java7 FLUSH_SYNC if available. - * @throws IOException In case of a lowlevel exception. - */ - @Override - public void flush() throws IOException { - if (!SUPPORTED) { - super.flush(); - return; - } - try { - int count = 0; - do { - count = (Integer) method.invoke(def, buf, 0, buf.length, 3); - if (count > 0) { - out.write(buf, 0, count); + /** + * Flush the given stream, preferring Java7 FLUSH_SYNC if available. + * + * @throws IOException + * In case of a lowlevel exception. + */ + @Override + public void flush() throws IOException { + if (!SUPPORTED) { + super.flush(); + return; + } + try { + int count = 0; + do { + count = (Integer) method.invoke(def, buf, 0, buf.length, 3); + if (count > 0) { + out.write(buf, 0, count); + } + } while (count > 0); + } catch (IllegalArgumentException e) { + throw new IOException("Can't flush"); + } catch (IllegalAccessException e) { + throw new IOException("Can't flush"); + } catch (InvocationTargetException e) { + throw new IOException("Can't flush"); } - } while (count > 0); - } catch (IllegalArgumentException e) { - throw new IOException("Can't flush"); - } catch (IllegalAccessException e) { - throw new IOException("Can't flush"); - } catch (InvocationTargetException e) { - throw new IOException("Can't flush"); - } - super.flush(); - } + super.flush(); + } } |