diff options
author | Christian Schneppe <christian@pix-art.de> | 2016-07-29 19:52:37 +0200 |
---|---|---|
committer | Christian Schneppe <christian@pix-art.de> | 2016-07-29 19:52:37 +0200 |
commit | 94933e21cd08c53a23e5ec6c12bc1dc383b1f3ce (patch) | |
tree | 4fa096547d0917f603252c9a279e4208ba4ef711 /src/main/java/eu/siacs/conversations/utils | |
parent | 50889004f3c679387d95ba9c49a53a8f882ba33c (diff) |
changed package id inside manifest and project
Diffstat (limited to 'src/main/java/eu/siacs/conversations/utils')
20 files changed, 0 insertions, 2722 deletions
diff --git a/src/main/java/eu/siacs/conversations/utils/ConversationsFileObserver.java b/src/main/java/eu/siacs/conversations/utils/ConversationsFileObserver.java deleted file mode 100644 index e6993bfe5..000000000 --- a/src/main/java/eu/siacs/conversations/utils/ConversationsFileObserver.java +++ /dev/null @@ -1,72 +0,0 @@ -package eu.siacs.conversations.utils; - - -import android.os.FileObserver; - -import java.io.File; -import java.util.ArrayList; -import java.util.List; -import java.util.Stack; - -/** - * Copyright (C) 2012 Bartek Przybylski - * Copyright (C) 2015 ownCloud Inc. - * Copyright (C) 2016 Daniel Gultsch - */ - -public abstract class ConversationsFileObserver { - - private final String path; - private final List<SingleFileObserver> mObservers = new ArrayList<>(); - - public ConversationsFileObserver(String path) { - this.path = path; - } - - public synchronized void startWatching() { - Stack<String> stack = new Stack<>(); - stack.push(path); - - while (!stack.empty()) { - String parent = stack.pop(); - mObservers.add(new SingleFileObserver(parent, FileObserver.DELETE)); - final File path = new File(parent); - final File[] files = path.listFiles(); - if (files == null) { - continue; - } - for(File file : files) { - if (file.isDirectory() && !file.getName().equals(".") && !file.getName().equals("..")) { - stack.push(file.getPath()); - } - } - } - for(FileObserver observer : mObservers) { - observer.startWatching(); - } - } - - public synchronized void stopWatching() { - for(FileObserver observer : mObservers) { - observer.stopWatching(); - } - mObservers.clear(); - } - - abstract public void onEvent(int event, String path); - - private class SingleFileObserver extends FileObserver { - private final String path; - - public SingleFileObserver(String path, int mask) { - super(path, mask); - this.path = path; - } - - @Override - public void onEvent(int event, String filename) { - ConversationsFileObserver.this.onEvent(event, path+'/'+filename); - } - - } -} diff --git a/src/main/java/eu/siacs/conversations/utils/CryptoHelper.java b/src/main/java/eu/siacs/conversations/utils/CryptoHelper.java deleted file mode 100644 index 253584bf1..000000000 --- a/src/main/java/eu/siacs/conversations/utils/CryptoHelper.java +++ /dev/null @@ -1,216 +0,0 @@ -package eu.siacs.conversations.utils; - -import android.os.Bundle; -import android.util.Pair; - -import org.bouncycastle.asn1.x500.X500Name; -import org.bouncycastle.asn1.x500.style.BCStyle; -import org.bouncycastle.asn1.x500.style.IETFUtils; -import org.bouncycastle.cert.jcajce.JcaX509CertificateHolder; - -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.security.cert.CertificateEncodingException; -import java.security.cert.CertificateParsingException; -import java.security.cert.X509Certificate; -import java.text.Normalizer; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Iterator; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Locale; - -import eu.siacs.conversations.Config; -import eu.siacs.conversations.R; -import eu.siacs.conversations.entities.Message; -import eu.siacs.conversations.xmpp.jid.InvalidJidException; -import eu.siacs.conversations.xmpp.jid.Jid; - -public final class CryptoHelper { - public static final String FILETRANSFER = "?FILETRANSFERv1:"; - private final static char[] hexArray = "0123456789abcdef".toCharArray(); - final public static byte[] ONE = new byte[] { 0, 0, 0, 1 }; - - public static String bytesToHex(byte[] bytes) { - char[] hexChars = new char[bytes.length * 2]; - for (int j = 0; j < bytes.length; j++) { - int v = bytes[j] & 0xFF; - hexChars[j * 2] = hexArray[v >>> 4]; - hexChars[j * 2 + 1] = hexArray[v & 0x0F]; - } - return new String(hexChars); - } - - public static byte[] hexToBytes(String hexString) { - int len = hexString.length(); - byte[] array = new byte[len / 2]; - for (int i = 0; i < len; i += 2) { - array[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4) + Character - .digit(hexString.charAt(i + 1), 16)); - } - return array; - } - - public static String hexToString(final String hexString) { - return new String(hexToBytes(hexString)); - } - - public 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; - } - - /** - * Escapes usernames or passwords for SASL. - */ - public static String saslEscape(final String s) { - final StringBuilder sb = new StringBuilder((int) (s.length() * 1.1)); - for (int i = 0; i < s.length(); i++) { - char c = s.charAt(i); - switch (c) { - case ',': - sb.append("=2C"); - break; - case '=': - sb.append("=3D"); - break; - default: - sb.append(c); - break; - } - } - return sb.toString(); - } - - public static String saslPrep(final String s) { - return Normalizer.normalize(s, Normalizer.Form.NFKC); - } - - public static String prettifyFingerprint(String fingerprint) { - if (fingerprint==null) { - return ""; - } else if (fingerprint.length() < 40) { - return fingerprint; - } - StringBuilder builder = new StringBuilder(fingerprint.toLowerCase(Locale.US).replaceAll("\\s", "")); - for(int i=8;i<builder.length();i+=9) { - builder.insert(i, ' '); - } - return builder.toString(); - } - - public static String prettifyFingerprintCert(String fingerprint) { - StringBuilder builder = new StringBuilder(fingerprint); - for(int i=2;i < builder.length(); i+=3) { - builder.insert(i,':'); - } - return builder.toString(); - } - - public static String[] getOrderedCipherSuites(final String[] platformSupportedCipherSuites) { - final Collection<String> cipherSuites = new LinkedHashSet<>(Arrays.asList(Config.ENABLED_CIPHERS)); - final List<String> platformCiphers = Arrays.asList(platformSupportedCipherSuites); - cipherSuites.retainAll(platformCiphers); - cipherSuites.addAll(platformCiphers); - filterWeakCipherSuites(cipherSuites); - return cipherSuites.toArray(new String[cipherSuites.size()]); - } - - private static void filterWeakCipherSuites(final Collection<String> cipherSuites) { - final Iterator<String> it = cipherSuites.iterator(); - while (it.hasNext()) { - String cipherName = it.next(); - // remove all ciphers with no or very weak encryption or no authentication - for (String weakCipherPattern : Config.WEAK_CIPHER_PATTERNS) { - if (cipherName.contains(weakCipherPattern)) { - it.remove(); - break; - } - } - } - } - - public static Pair<Jid,String> extractJidAndName(X509Certificate certificate) throws CertificateEncodingException, InvalidJidException, CertificateParsingException { - Collection<List<?>> alternativeNames = certificate.getSubjectAlternativeNames(); - List<String> emails = new ArrayList<>(); - if (alternativeNames != null) { - for(List<?> san : alternativeNames) { - Integer type = (Integer) san.get(0); - if (type == 1) { - emails.add((String) san.get(1)); - } - } - } - X500Name x500name = new JcaX509CertificateHolder(certificate).getSubject(); - if (emails.size() == 0) { - emails.add(IETFUtils.valueToString(x500name.getRDNs(BCStyle.EmailAddress)[0].getFirst().getValue())); - } - String name = IETFUtils.valueToString(x500name.getRDNs(BCStyle.CN)[0].getFirst().getValue()); - if (emails.size() >= 1) { - return new Pair<>(Jid.fromString(emails.get(0)), name); - } else { - return null; - } - } - - public static Bundle extractCertificateInformation(X509Certificate certificate) { - Bundle information = new Bundle(); - try { - JcaX509CertificateHolder holder = new JcaX509CertificateHolder(certificate); - X500Name subject = holder.getSubject(); - try { - information.putString("subject_cn", subject.getRDNs(BCStyle.CN)[0].getFirst().getValue().toString()); - } catch (Exception e) { - //ignored - } - try { - information.putString("subject_o",subject.getRDNs(BCStyle.O)[0].getFirst().getValue().toString()); - } catch (Exception e) { - //ignored - } - - X500Name issuer = holder.getIssuer(); - try { - information.putString("issuer_cn", issuer.getRDNs(BCStyle.CN)[0].getFirst().getValue().toString()); - } catch (Exception e) { - //ignored - } - try { - information.putString("issuer_o", issuer.getRDNs(BCStyle.O)[0].getFirst().getValue().toString()); - } catch (Exception e) { - //ignored - } - try { - information.putString("sha1", getFingerprintCert(certificate.getEncoded())); - } catch (Exception e) { - - } - return information; - } catch (CertificateEncodingException e) { - return information; - } - } - - public static String getFingerprintCert(byte[] input) throws NoSuchAlgorithmException { - MessageDigest md = MessageDigest.getInstance("SHA-1"); - byte[] fingerprint = md.digest(input); - return prettifyFingerprintCert(bytesToHex(fingerprint)); - } - - public static int encryptionTypeToText(int encryption) { - switch (encryption) { - case Message.ENCRYPTION_OTR: - return R.string.encryption_choice_otr; - case Message.ENCRYPTION_AXOLOTL: - return R.string.encryption_choice_omemo; - case Message.ENCRYPTION_NONE: - return R.string.encryption_choice_unencrypted; - default: - return R.string.encryption_choice_pgp; - } - } -} diff --git a/src/main/java/eu/siacs/conversations/utils/DNSHelper.java b/src/main/java/eu/siacs/conversations/utils/DNSHelper.java deleted file mode 100644 index b51a9f16a..000000000 --- a/src/main/java/eu/siacs/conversations/utils/DNSHelper.java +++ /dev/null @@ -1,294 +0,0 @@ -package eu.siacs.conversations.utils; - -import android.annotation.TargetApi; -import android.content.Context; -import android.net.ConnectivityManager; -import android.net.LinkProperties; -import android.net.Network; -import android.net.RouteInfo; -import android.os.Build; -import android.os.Bundle; -import android.os.Parcelable; -import android.util.Log; - -import java.io.IOException; -import java.net.Inet4Address; -import java.net.InetAddress; -import java.net.SocketTimeoutException; -import java.net.UnknownHostException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Random; -import java.util.TreeMap; -import java.util.regex.Pattern; - -import de.measite.minidns.Client; -import de.measite.minidns.DNSMessage; -import de.measite.minidns.Record; -import de.measite.minidns.Record.CLASS; -import de.measite.minidns.Record.TYPE; -import de.measite.minidns.record.A; -import de.measite.minidns.record.AAAA; -import de.measite.minidns.record.Data; -import de.measite.minidns.record.SRV; -import de.measite.minidns.util.NameUtil; -import eu.siacs.conversations.Config; -import eu.siacs.conversations.xmpp.jid.Jid; - -public class DNSHelper { - - public static final Pattern PATTERN_IPV4 = Pattern.compile("\\A(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}\\z"); - public static final Pattern PATTERN_IPV6_HEX4DECCOMPRESSED = Pattern.compile("\\A((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?) ::((?:[0-9A-Fa-f]{1,4}:)*)(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}\\z"); - public static final Pattern PATTERN_IPV6_6HEX4DEC = Pattern.compile("\\A((?:[0-9A-Fa-f]{1,4}:){6,6})(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}\\z"); - public static final Pattern PATTERN_IPV6_HEXCOMPRESSED = Pattern.compile("\\A((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)::((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)\\z"); - public static final Pattern PATTERN_IPV6 = Pattern.compile("\\A(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}\\z"); - - protected static Client client = new Client(); - - protected static Context context; - - public static Bundle getSRVRecord(final Jid jid, Context context) throws IOException { - DNSHelper.context = context; - final String host = jid.getDomainpart(); - final List<InetAddress> servers = Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? getDnsServers(context) : getDnsServersPreLollipop(); - Bundle b = new Bundle(); - boolean interrupted = false; - for(InetAddress server : servers) { - if (Thread.currentThread().isInterrupted()) { - interrupted = true; - break; - } - b = queryDNS(host, server); - if (b.containsKey("values")) { - return b; - } - } - if (!b.containsKey("values")) { - Log.d(Config.LOGTAG,(interrupted ? "Thread interrupted during DNS query" :"all dns queries failed") + ". provide fallback A record"); - ArrayList<Parcelable> values = new ArrayList<>(); - values.add(createNamePortBundle(host, 5222, false)); - b.putParcelableArrayList("values",values); - } - return b; - } - - @TargetApi(21) - private static List<InetAddress> getDnsServers(Context context) { - List<InetAddress> servers = new ArrayList<>(); - ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); - Network[] networks = connectivityManager == null ? null : connectivityManager.getAllNetworks(); - if (networks == null) { - return getDnsServersPreLollipop(); - } - for(int i = 0; i < networks.length; ++i) { - LinkProperties linkProperties = connectivityManager.getLinkProperties(networks[i]); - if (linkProperties != null) { - if (hasDefaultRoute(linkProperties)) { - servers.addAll(0, getIPv4First(linkProperties.getDnsServers())); - } else { - servers.addAll(getIPv4First(linkProperties.getDnsServers())); - } - } - } - if (servers.size() > 0) { - Log.d(Config.LOGTAG, "used lollipop variant to discover dns servers in " + networks.length + " networks"); - } - return servers.size() > 0 ? servers : getDnsServersPreLollipop(); - } - - private static List<InetAddress> getIPv4First(List<InetAddress> in) { - List<InetAddress> out = new ArrayList<>(); - for(InetAddress addr : in) { - if (addr instanceof Inet4Address) { - out.add(0, addr); - } else { - out.add(addr); - } - } - return out; - } - - @TargetApi(Build.VERSION_CODES.LOLLIPOP) - private static boolean hasDefaultRoute(LinkProperties linkProperties) { - for(RouteInfo route: linkProperties.getRoutes()) { - if (route.isDefaultRoute()) { - return true; - } - } - return false; - } - - private static List<InetAddress> getDnsServersPreLollipop() { - List<InetAddress> servers = new ArrayList<>(); - String[] dns = client.findDNS(); - for(int i = 0; i < dns.length; ++i) { - try { - servers.add(InetAddress.getByName(dns[i])); - } catch (UnknownHostException e) { - //ignore - } - } - return servers; - } - - private static class TlsSrv { - private final SRV srv; - private final boolean tls; - - public TlsSrv(SRV srv, boolean tls) { - this.srv = srv; - this.tls = tls; - } - } - - private static void fillSrvMaps(final String qname, final InetAddress dnsServer, final Map<Integer, List<TlsSrv>> priorities, final Map<String, List<String>> ips4, final Map<String, List<String>> ips6, final boolean tls) throws IOException { - final DNSMessage message = client.query(qname, TYPE.SRV, CLASS.IN, dnsServer.getHostAddress()); - 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())) { - SRV srv = (SRV) d; - if (!priorities.containsKey(srv.getPriority())) { - priorities.put(srv.getPriority(),new ArrayList<TlsSrv>()); - } - priorities.get(srv.getPriority()).add(new TlsSrv(srv, tls)); - } - if (d instanceof A) { - A a = (A) d; - if (!ips4.containsKey(rr.getName())) { - ips4.put(rr.getName(), new ArrayList<String>()); - } - ips4.get(rr.getName()).add(a.toString()); - } - if (d instanceof AAAA) { - AAAA aaaa = (AAAA) d; - if (!ips6.containsKey(rr.getName())) { - ips6.put(rr.getName(), new ArrayList<String>()); - } - ips6.get(rr.getName()).add("[" + aaaa.toString() + "]"); - } - } - } - } - - public static Bundle queryDNS(String host, InetAddress dnsServer) { - Bundle bundle = new Bundle(); - try { - client.setTimeout(Config.SOCKET_TIMEOUT * 1000); - final String qname = "_xmpp-client._tcp." + host; - final String tlsQname = "_xmpps-client._tcp." + host; - Log.d(Config.LOGTAG, "using dns server: " + dnsServer.getHostAddress() + " to look up " + host); - - final Map<Integer, List<TlsSrv>> priorities = new TreeMap<>(); - final Map<String, List<String>> ips4 = new TreeMap<>(); - final Map<String, List<String>> ips6 = new TreeMap<>(); - - fillSrvMaps(qname, dnsServer, priorities, ips4, ips6, false); - fillSrvMaps(tlsQname, dnsServer, priorities, ips4, ips6, true); - - final List<TlsSrv> result = new ArrayList<>(); - for (final List<TlsSrv> s : priorities.values()) { - result.addAll(s); - } - - final ArrayList<Bundle> values = new ArrayList<>(); - if (result.size() == 0) { - DNSMessage response; - try { - response = client.query(host, TYPE.A, CLASS.IN, dnsServer.getHostAddress()); - for (int i = 0; i < response.getAnswers().length; ++i) { - values.add(createNamePortBundle(host, 5222, response.getAnswers()[i].getPayload(), false)); - } - } catch (SocketTimeoutException e) { - Log.d(Config.LOGTAG,"ignoring timeout exception when querying A record on "+dnsServer.getHostAddress()); - } - try { - response = client.query(host, TYPE.AAAA, CLASS.IN, dnsServer.getHostAddress()); - for (int i = 0; i < response.getAnswers().length; ++i) { - values.add(createNamePortBundle(host, 5222, response.getAnswers()[i].getPayload(), false)); - } - } catch (SocketTimeoutException e) { - Log.d(Config.LOGTAG,"ignoring timeout exception when querying AAAA record on "+dnsServer.getHostAddress()); - } - values.add(createNamePortBundle(host, 5222, false)); - bundle.putParcelableArrayList("values", values); - return bundle; - } - for (final TlsSrv tlsSrv : result) { - final SRV srv = tlsSrv.srv; - if (ips6.containsKey(srv.getName())) { - values.add(createNamePortBundle(srv.getName(),srv.getPort(),ips6, tlsSrv.tls)); - } else { - try { - DNSMessage response = client.query(srv.getName(), TYPE.AAAA, CLASS.IN, dnsServer.getHostAddress()); - for (int i = 0; i < response.getAnswers().length; ++i) { - values.add(createNamePortBundle(srv.getName(), srv.getPort(), response.getAnswers()[i].getPayload(), tlsSrv.tls)); - } - } catch (SocketTimeoutException e) { - Log.d(Config.LOGTAG,"ignoring timeout exception when querying AAAA record on "+dnsServer.getHostAddress()); - } - } - if (ips4.containsKey(srv.getName())) { - values.add(createNamePortBundle(srv.getName(),srv.getPort(),ips4, tlsSrv.tls)); - } else { - DNSMessage response = client.query(srv.getName(), TYPE.A, CLASS.IN, dnsServer.getHostAddress()); - for(int i = 0; i < response.getAnswers().length; ++i) { - values.add(createNamePortBundle(srv.getName(),srv.getPort(),response.getAnswers()[i].getPayload(), tlsSrv.tls)); - } - } - values.add(createNamePortBundle(srv.getName(), srv.getPort(), tlsSrv.tls)); - } - bundle.putParcelableArrayList("values", values); - } catch (SocketTimeoutException e) { - bundle.putString("error", "timeout"); - } catch (Exception e) { - bundle.putString("error", "unhandled"); - } - return bundle; - } - - private static Bundle createNamePortBundle(String name, int port, final boolean tls) { - Bundle namePort = new Bundle(); - namePort.putString("name", name); - namePort.putBoolean("tls", tls); - namePort.putInt("port", port); - return namePort; - } - - private static Bundle createNamePortBundle(String name, int port, Map<String, List<String>> ips, final boolean tls) { - Bundle namePort = new Bundle(); - namePort.putString("name", name); - namePort.putBoolean("tls", tls); - namePort.putInt("port", port); - if (ips!=null) { - List<String> ip = ips.get(name); - Collections.shuffle(ip, new Random()); - namePort.putString("ip", ip.get(0)); - } - return namePort; - } - - private static Bundle createNamePortBundle(String name, int port, Data data, final boolean tls) { - Bundle namePort = new Bundle(); - namePort.putString("name", name); - namePort.putBoolean("tls", tls); - namePort.putInt("port", port); - if (data instanceof A) { - namePort.putString("ip", data.toString()); - } else if (data instanceof AAAA) { - namePort.putString("ip","["+data.toString()+"]"); - } - return namePort; - } - - public static boolean isIp(final String server) { - return server != null && ( - PATTERN_IPV4.matcher(server).matches() - || PATTERN_IPV6.matcher(server).matches() - || PATTERN_IPV6_6HEX4DEC.matcher(server).matches() - || PATTERN_IPV6_HEX4DECCOMPRESSED.matcher(server).matches() - || PATTERN_IPV6_HEXCOMPRESSED.matcher(server).matches()); - } -} diff --git a/src/main/java/eu/siacs/conversations/utils/ExceptionHandler.java b/src/main/java/eu/siacs/conversations/utils/ExceptionHandler.java deleted file mode 100644 index b8a0fa511..000000000 --- a/src/main/java/eu/siacs/conversations/utils/ExceptionHandler.java +++ /dev/null @@ -1,31 +0,0 @@ -package eu.siacs.conversations.utils; - -import android.content.Context; - -import java.io.PrintWriter; -import java.io.StringWriter; -import java.io.Writer; -import java.lang.Thread.UncaughtExceptionHandler; - -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(); - ExceptionHelper.writeToStacktraceFile(context, stacktrace); - this.defaultHandler.uncaughtException(thread, ex); - } - -} diff --git a/src/main/java/eu/siacs/conversations/utils/ExceptionHelper.java b/src/main/java/eu/siacs/conversations/utils/ExceptionHelper.java deleted file mode 100644 index 79c547889..000000000 --- a/src/main/java/eu/siacs/conversations/utils/ExceptionHelper.java +++ /dev/null @@ -1,137 +0,0 @@ -package eu.siacs.conversations.utils; - -import android.app.AlertDialog; -import android.content.Context; -import android.content.DialogInterface; -import android.content.DialogInterface.OnClickListener; -import android.content.SharedPreferences; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.content.pm.Signature; -import android.preference.PreferenceManager; -import android.util.Log; - -import java.io.BufferedReader; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.text.SimpleDateFormat; -import java.util.Date; -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; -import eu.siacs.conversations.entities.Message; -import eu.siacs.conversations.services.XmppConnectionService; -import eu.siacs.conversations.ui.ConversationActivity; -import eu.siacs.conversations.xmpp.jid.InvalidJidException; -import eu.siacs.conversations.xmpp.jid.Jid; - -public class ExceptionHelper { - private static SimpleDateFormat DATE_FORMATs = new SimpleDateFormat("yyyy-MM-dd"); - public static void init(Context context) { - if (!(Thread.getDefaultUncaughtExceptionHandler() instanceof ExceptionHandler)) { - Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler( - context)); - } - } - - public static boolean checkForCrash(ConversationActivity activity, final XmppConnectionService service) { - try { - final SharedPreferences preferences = PreferenceManager - .getDefaultSharedPreferences(activity); - boolean crashreport = preferences.getBoolean("crashreport", true); - if (!crashreport || Config.BUG_REPORTS == null) { - return false; - } - List<Account> accounts = service.getAccounts(); - Account account = null; - for (int i = 0; i < accounts.size(); ++i) { - if (!accounts.get(i).isOptionSet(Account.OPTION_DISABLED)) { - account = accounts.get(i); - break; - } - } - if (account == null) { - return false; - } - final Account finalAccount = account; - FileInputStream file = activity.openFileInput("stacktrace.txt"); - InputStreamReader inputStreamReader = new InputStreamReader(file); - BufferedReader stacktrace = new BufferedReader(inputStreamReader); - final StringBuilder report = new StringBuilder(); - PackageManager pm = activity.getPackageManager(); - PackageInfo packageInfo; - try { - packageInfo = pm.getPackageInfo(activity.getPackageName(), PackageManager.GET_SIGNATURES); - report.append("Version: " + packageInfo.versionName + '\n'); - report.append("Last Update: " + DATE_FORMATs.format(new Date(packageInfo.lastUpdateTime)) + '\n'); - Signature[] signatures = packageInfo.signatures; - if (signatures != null && signatures.length >= 1) { - report.append("SHA-1: " + CryptoHelper.getFingerprintCert(packageInfo.signatures[0].toByteArray()) + "\n"); - } - report.append('\n'); - } catch (Exception e) { - e.printStackTrace(); - return false; - } - String line; - while ((line = stacktrace.readLine()) != null) { - report.append(line); - report.append('\n'); - } - file.close(); - activity.deleteFile("stacktrace.txt"); - AlertDialog.Builder builder = new AlertDialog.Builder(activity); - builder.setTitle(activity.getString(R.string.crash_report_title)); - builder.setMessage(activity.getText(R.string.crash_report_message)); - builder.setPositiveButton(activity.getText(R.string.send_now), - new OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, int which) { - - Log.d(Config.LOGTAG, "using account=" - + finalAccount.getJid().toBareJid() - + " to send in stack trace"); - - Conversation conversation = null; - try { - conversation = service.findOrCreateConversation(finalAccount, - Jid.fromString(Config.BUG_REPORTS), false); - } catch (final InvalidJidException ignored) { - } - Message message = new Message(conversation, report - .toString(), Message.ENCRYPTION_NONE); - service.sendMessage(message); - } - }); - builder.setNegativeButton(activity.getText(R.string.send_never), - new OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, int which) { - preferences.edit().putBoolean("crash_report", false) - .apply(); - } - }); - builder.create().show(); - return true; - } catch (final IOException ignored) { - return false; - } - } - - public static void writeToStacktraceFile(Context context, String msg) { - try { - OutputStream os = context.openFileOutput("stacktrace.txt", Context.MODE_PRIVATE); - os.write(msg.getBytes()); - os.flush(); - os.close(); - } catch (IOException ignored) { - } - } -} diff --git a/src/main/java/eu/siacs/conversations/utils/ExifHelper.java b/src/main/java/eu/siacs/conversations/utils/ExifHelper.java deleted file mode 100644 index ceda72933..000000000 --- a/src/main/java/eu/siacs/conversations/utils/ExifHelper.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package eu.siacs.conversations.utils; - -import android.util.Log; - -import java.io.IOException; -import java.io.InputStream; - -public class ExifHelper { - private static final String TAG = "CameraExif"; - - public static int getOrientation(InputStream is) { - if (is == null) { - return 0; - } - - byte[] buf = new byte[8]; - int length = 0; - - // ISO/IEC 10918-1:1993(E) - while (read(is, buf, 2) && (buf[0] & 0xFF) == 0xFF) { - int marker = buf[1] & 0xFF; - - // Check if the marker is a padding. - if (marker == 0xFF) { - continue; - } - - // Check if the marker is SOI or TEM. - if (marker == 0xD8 || marker == 0x01) { - continue; - } - // Check if the marker is EOI or SOS. - if (marker == 0xD9 || marker == 0xDA) { - return 0; - } - - // Get the length and check if it is reasonable. - if (!read(is, buf, 2)) { - return 0; - } - length = pack(buf, 0, 2, false); - if (length < 2) { - Log.e(TAG, "Invalid length"); - return 0; - } - length -= 2; - - // Break if the marker is EXIF in APP1. - if (marker == 0xE1 && length >= 6) { - if (!read(is, buf, 6)) return 0; - length -= 6; - if (pack(buf, 0, 4, false) == 0x45786966 && - pack(buf, 4, 2, false) == 0) { - break; - } - } - - // Skip other markers. - try { - is.skip(length); - } catch (IOException ex) { - return 0; - } - length = 0; - } - - // JEITA CP-3451 Exif Version 2.2 - if (length > 8) { - int offset = 0; - byte[] jpeg = new byte[length]; - if (!read(is, jpeg, length)) { - return 0; - } - - // Identify the byte order. - int tag = pack(jpeg, offset, 4, false); - if (tag != 0x49492A00 && tag != 0x4D4D002A) { - Log.e(TAG, "Invalid byte order"); - return 0; - } - boolean littleEndian = (tag == 0x49492A00); - - // Get the offset and check if it is reasonable. - int count = pack(jpeg, offset + 4, 4, littleEndian) + 2; - if (count < 10 || count > length) { - Log.e(TAG, "Invalid offset"); - return 0; - } - offset += count; - length -= count; - - // Get the count and go through all the elements. - count = pack(jpeg, offset - 2, 2, littleEndian); - while (count-- > 0 && length >= 12) { - // Get the tag and check if it is orientation. - tag = pack(jpeg, offset, 2, littleEndian); - if (tag == 0x0112) { - // We do not really care about type and count, do we? - int orientation = pack(jpeg, offset + 8, 2, littleEndian); - switch (orientation) { - case 1: - return 0; - case 3: - return 180; - case 6: - return 90; - case 8: - return 270; - } - Log.i(TAG, "Unsupported orientation"); - return 0; - } - offset += 12; - length -= 12; - } - } - - Log.i(TAG, "Orientation not found"); - return 0; - } - - private static int pack(byte[] bytes, int offset, int length, - boolean littleEndian) { - int step = 1; - if (littleEndian) { - offset += length - 1; - step = -1; - } - - int value = 0; - while (length-- > 0) { - value = (value << 8) | (bytes[offset] & 0xFF); - offset += step; - } - return value; - } - - private static boolean read(InputStream is, byte[] buf, int length) { - try { - return is.read(buf, 0, length) == length; - } catch (IOException ex) { - return false; - } - } -} diff --git a/src/main/java/eu/siacs/conversations/utils/FileUtils.java b/src/main/java/eu/siacs/conversations/utils/FileUtils.java deleted file mode 100644 index 6e75d41cd..000000000 --- a/src/main/java/eu/siacs/conversations/utils/FileUtils.java +++ /dev/null @@ -1,158 +0,0 @@ -package eu.siacs.conversations.utils; - -import android.annotation.SuppressLint; -import android.content.ContentUris; -import android.content.Context; -import android.database.Cursor; -import android.net.Uri; -import android.os.Build; -import android.os.Environment; -import android.provider.DocumentsContract; -import android.provider.MediaStore; - -import java.io.File; - -public class FileUtils { - - /** - * Get a file path from a Uri. This will get the the path for Storage Access - * Framework Documents, as well as the _data field for the MediaStore and - * other file-based ContentProviders. - * - * @param context The context. - * @param uri The Uri to query. - * @author paulburke - */ - @SuppressLint("NewApi") - public static String getPath(final Context context, final Uri uri) { - if (uri == null) { - return null; - } - - final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; - - // DocumentProvider - if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) { - // ExternalStorageProvider - if (isExternalStorageDocument(uri)) { - final String docId = DocumentsContract.getDocumentId(uri); - final String[] split = docId.split(":"); - final String type = split[0]; - - if ("primary".equalsIgnoreCase(type)) { - return Environment.getExternalStorageDirectory() + "/" + split[1]; - } - - // TODO handle non-primary volumes - } - // DownloadsProvider - else if (isDownloadsDocument(uri)) { - - final String id = DocumentsContract.getDocumentId(uri); - final Uri contentUri = ContentUris.withAppendedId( - Uri.parse("content://downloads/public_downloads"), Long.valueOf(id)); - - return getDataColumn(context, contentUri, null, null); - } - // MediaProvider - else if (isMediaDocument(uri)) { - final String docId = DocumentsContract.getDocumentId(uri); - final String[] split = docId.split(":"); - final String type = split[0]; - - Uri contentUri = null; - if ("image".equals(type)) { - contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; - } else if ("video".equals(type)) { - contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; - } else if ("audio".equals(type)) { - contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; - } - - final String selection = "_id=?"; - final String[] selectionArgs = new String[]{ - split[1] - }; - - return getDataColumn(context, contentUri, selection, selectionArgs); - } - } - // MediaStore (and general) - else if ("content".equalsIgnoreCase(uri.getScheme())) { - String path = getDataColumn(context, uri, null, null); - if (path != null) { - File file = new File(path); - if (!file.canRead()) { - return null; - } - } - return path; - } - // File - else if ("file".equalsIgnoreCase(uri.getScheme())) { - return uri.getPath(); - } - - return null; - } - - /** - * Get the value of the data column for this Uri. This is useful for - * MediaStore Uris, and other file-based ContentProviders. - * - * @param context The context. - * @param uri The Uri to query. - * @param selection (Optional) Filter used in the query. - * @param selectionArgs (Optional) Selection arguments used in the query. - * @return The value of the _data column, which is typically a file path. - */ - public static String getDataColumn(Context context, Uri uri, String selection, - String[] selectionArgs) { - - Cursor cursor = null; - final String column = "_data"; - final String[] projection = { - column - }; - - try { - cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,null); - if (cursor != null && cursor.moveToFirst()) { - final int column_index = cursor.getColumnIndexOrThrow(column); - return cursor.getString(column_index); - } - } catch(Exception e) { - return null; - } finally { - if (cursor != null) { - cursor.close(); - } - } - return null; - } - - - /** - * @param uri The Uri to check. - * @return Whether the Uri authority is ExternalStorageProvider. - */ - public static boolean isExternalStorageDocument(Uri uri) { - return "com.android.externalstorage.documents".equals(uri.getAuthority()); - } - - /** - * @param uri The Uri to check. - * @return Whether the Uri authority is DownloadsProvider. - */ - public static boolean isDownloadsDocument(Uri uri) { - return "com.android.providers.downloads.documents".equals(uri.getAuthority()); - } - - /** - * @param uri The Uri to check. - * @return Whether the Uri authority is MediaProvider. - */ - public static boolean isMediaDocument(Uri uri) { - return "com.android.providers.media.documents".equals(uri.getAuthority()); - } -} diff --git a/src/main/java/eu/siacs/conversations/utils/GeoHelper.java b/src/main/java/eu/siacs/conversations/utils/GeoHelper.java deleted file mode 100644 index 171e7dba6..000000000 --- a/src/main/java/eu/siacs/conversations/utils/GeoHelper.java +++ /dev/null @@ -1,81 +0,0 @@ -package eu.siacs.conversations.utils; - -import android.content.Intent; -import android.net.Uri; - -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; -import java.util.ArrayList; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import eu.siacs.conversations.entities.Contact; -import eu.siacs.conversations.entities.Conversation; -import eu.siacs.conversations.entities.Message; - -public class GeoHelper { - public static Pattern GEO_URI = Pattern.compile("geo:([\\-0-9.]+),([\\-0-9.]+)(?:,([\\-0-9.]+))?(?:\\?(.*))?", Pattern.CASE_INSENSITIVE); - - public static boolean isGeoUri(String body) { - return body != null && GEO_URI.matcher(body).matches(); - } - - public static ArrayList<Intent> createGeoIntentsFromMessage(Message message) { - final ArrayList<Intent> intents = new ArrayList<>(); - Matcher matcher = GEO_URI.matcher(message.getBody()); - if (!matcher.matches()) { - return intents; - } - double latitude; - double longitude; - try { - latitude = Double.parseDouble(matcher.group(1)); - if (latitude > 90.0 || latitude < -90.0) { - return intents; - } - longitude = Double.parseDouble(matcher.group(2)); - if (longitude > 180.0 || longitude < -180.0) { - return intents; - } - } catch (NumberFormatException nfe) { - return intents; - } - final Conversation conversation = message.getConversation(); - String label; - if (conversation.getMode() == Conversation.MODE_SINGLE && message.getStatus() == Message.STATUS_RECEIVED) { - try { - label = "(" + URLEncoder.encode(message.getConversation().getName(), "UTF-8") + ")"; - } catch (UnsupportedEncodingException e) { - label = ""; - } - } else { - label = ""; - } - - Intent locationPluginIntent = new Intent("eu.siacs.conversations.location.show"); - locationPluginIntent.putExtra("latitude",latitude); - locationPluginIntent.putExtra("longitude",longitude); - if (message.getStatus() != Message.STATUS_RECEIVED) { - locationPluginIntent.putExtra("jid",conversation.getAccount().getJid().toString()); - locationPluginIntent.putExtra("name",conversation.getAccount().getJid().getLocalpart()); - } else { - Contact contact = message.getContact(); - if (contact != null) { - locationPluginIntent.putExtra("name", contact.getDisplayName()); - locationPluginIntent.putExtra("jid", contact.getJid().toString()); - } else { - locationPluginIntent.putExtra("name", UIHelper.getDisplayedMucCounterpart(message.getCounterpart())); - } - } - intents.add(locationPluginIntent); - - Intent geoIntent = new Intent(Intent.ACTION_VIEW); - geoIntent.setData(Uri.parse("geo:" + String.valueOf(latitude) + "," + String.valueOf(longitude) + "?q=" + String.valueOf(latitude) + "," + String.valueOf(longitude) + label)); - intents.add(geoIntent); - - Intent httpIntent = new Intent(Intent.ACTION_VIEW); - httpIntent.setData(Uri.parse("https://maps.google.com/maps?q=loc:"+String.valueOf(latitude) + "," + String.valueOf(longitude) +label)); - intents.add(httpIntent); - return intents; - } -}
\ No newline at end of file diff --git a/src/main/java/eu/siacs/conversations/utils/MimeUtils.java b/src/main/java/eu/siacs/conversations/utils/MimeUtils.java deleted file mode 100644 index d45444240..000000000 --- a/src/main/java/eu/siacs/conversations/utils/MimeUtils.java +++ /dev/null @@ -1,487 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package eu.siacs.conversations.utils; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.HashMap; -import java.util.Map; -import java.util.Properties; -/** - * Utilities for dealing with MIME types. - * Used to implement java.net.URLConnection and android.webkit.MimeTypeMap. - */ -public final class MimeUtils { - private static final Map<String, String> mimeTypeToExtensionMap = new HashMap<String, String>(); - private static final Map<String, String> extensionToMimeTypeMap = new HashMap<String, String>(); - static { - // The following table is based on /etc/mime.types data minus - // chemical/* MIME types and MIME types that don't map to any - // file extensions. We also exclude top-level domain names to - // deal with cases like: - // - // mail.google.com/a/google.com - // - // and "active" MIME types (due to potential security issues). - // Note that this list is _not_ in alphabetical order and must not be sorted. - // The "most popular" extension must come first, so that it's the one returned - // by guessExtensionFromMimeType. - add("application/andrew-inset", "ez"); - add("application/dsptype", "tsp"); - add("application/hta", "hta"); - add("application/mac-binhex40", "hqx"); - add("application/mathematica", "nb"); - add("application/msaccess", "mdb"); - add("application/oda", "oda"); - add("application/ogg", "ogg"); - add("application/ogg", "oga"); - add("application/pdf", "pdf"); - add("application/pgp-keys", "key"); - add("application/pgp-signature", "pgp"); - add("application/pics-rules", "prf"); - add("application/pkix-cert", "cer"); - add("application/rar", "rar"); - add("application/rdf+xml", "rdf"); - add("application/rss+xml", "rss"); - add("application/zip", "zip"); - add("application/vnd.android.package-archive", "apk"); - add("application/vnd.cinderella", "cdy"); - add("application/vnd.ms-pki.stl", "stl"); - add("application/vnd.oasis.opendocument.database", "odb"); - add("application/vnd.oasis.opendocument.formula", "odf"); - add("application/vnd.oasis.opendocument.graphics", "odg"); - add("application/vnd.oasis.opendocument.graphics-template", "otg"); - add("application/vnd.oasis.opendocument.image", "odi"); - add("application/vnd.oasis.opendocument.spreadsheet", "ods"); - add("application/vnd.oasis.opendocument.spreadsheet-template", "ots"); - add("application/vnd.oasis.opendocument.text", "odt"); - add("application/vnd.oasis.opendocument.text-master", "odm"); - add("application/vnd.oasis.opendocument.text-template", "ott"); - add("application/vnd.oasis.opendocument.text-web", "oth"); - add("application/vnd.google-earth.kml+xml", "kml"); - add("application/vnd.google-earth.kmz", "kmz"); - add("application/msword", "doc"); - add("application/msword", "dot"); - add("application/vnd.openxmlformats-officedocument.wordprocessingml.document", "docx"); - add("application/vnd.openxmlformats-officedocument.wordprocessingml.template", "dotx"); - add("application/vnd.ms-excel", "xls"); - add("application/vnd.ms-excel", "xlt"); - add("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", "xlsx"); - add("application/vnd.openxmlformats-officedocument.spreadsheetml.template", "xltx"); - add("application/vnd.ms-powerpoint", "ppt"); - add("application/vnd.ms-powerpoint", "pot"); - add("application/vnd.ms-powerpoint", "pps"); - add("application/vnd.openxmlformats-officedocument.presentationml.presentation", "pptx"); - add("application/vnd.openxmlformats-officedocument.presentationml.template", "potx"); - add("application/vnd.openxmlformats-officedocument.presentationml.slideshow", "ppsx"); - add("application/vnd.rim.cod", "cod"); - add("application/vnd.smaf", "mmf"); - add("application/vnd.stardivision.calc", "sdc"); - add("application/vnd.stardivision.draw", "sda"); - add("application/vnd.stardivision.impress", "sdd"); - add("application/vnd.stardivision.impress", "sdp"); - add("application/vnd.stardivision.math", "smf"); - add("application/vnd.stardivision.writer", "sdw"); - add("application/vnd.stardivision.writer", "vor"); - add("application/vnd.stardivision.writer-global", "sgl"); - add("application/vnd.sun.xml.calc", "sxc"); - add("application/vnd.sun.xml.calc.template", "stc"); - add("application/vnd.sun.xml.draw", "sxd"); - add("application/vnd.sun.xml.draw.template", "std"); - add("application/vnd.sun.xml.impress", "sxi"); - add("application/vnd.sun.xml.impress.template", "sti"); - add("application/vnd.sun.xml.math", "sxm"); - add("application/vnd.sun.xml.writer", "sxw"); - add("application/vnd.sun.xml.writer.global", "sxg"); - add("application/vnd.sun.xml.writer.template", "stw"); - add("application/vnd.visio", "vsd"); - add("application/x-abiword", "abw"); - add("application/x-apple-diskimage", "dmg"); - add("application/x-bcpio", "bcpio"); - add("application/x-bittorrent", "torrent"); - add("application/x-cdf", "cdf"); - add("application/x-cdlink", "vcd"); - add("application/x-chess-pgn", "pgn"); - add("application/x-cpio", "cpio"); - add("application/x-debian-package", "deb"); - add("application/x-debian-package", "udeb"); - add("application/x-director", "dcr"); - add("application/x-director", "dir"); - add("application/x-director", "dxr"); - add("application/x-dms", "dms"); - add("application/x-doom", "wad"); - add("application/x-dvi", "dvi"); - add("application/x-font", "pfa"); - add("application/x-font", "pfb"); - add("application/x-font", "gsf"); - add("application/x-font", "pcf"); - add("application/x-font", "pcf.Z"); - add("application/x-freemind", "mm"); - // application/futuresplash isn't IANA, so application/x-futuresplash should come first. - add("application/x-futuresplash", "spl"); - add("application/futuresplash", "spl"); - add("application/x-gnumeric", "gnumeric"); - add("application/x-go-sgf", "sgf"); - add("application/x-graphing-calculator", "gcf"); - add("application/x-gtar", "tgz"); - add("application/x-gtar", "gtar"); - add("application/x-gtar", "taz"); - add("application/x-hdf", "hdf"); - add("application/x-ica", "ica"); - add("application/x-internet-signup", "ins"); - add("application/x-internet-signup", "isp"); - add("application/x-iphone", "iii"); - add("application/x-iso9660-image", "iso"); - add("application/x-jmol", "jmz"); - add("application/x-kchart", "chrt"); - add("application/x-killustrator", "kil"); - add("application/x-koan", "skp"); - add("application/x-koan", "skd"); - add("application/x-koan", "skt"); - add("application/x-koan", "skm"); - add("application/x-kpresenter", "kpr"); - add("application/x-kpresenter", "kpt"); - add("application/x-kspread", "ksp"); - add("application/x-kword", "kwd"); - add("application/x-kword", "kwt"); - add("application/x-latex", "latex"); - add("application/x-lha", "lha"); - add("application/x-lzh", "lzh"); - add("application/x-lzx", "lzx"); - add("application/x-maker", "frm"); - add("application/x-maker", "maker"); - add("application/x-maker", "frame"); - add("application/x-maker", "fb"); - add("application/x-maker", "book"); - add("application/x-maker", "fbdoc"); - add("application/x-mif", "mif"); - add("application/x-ms-wmd", "wmd"); - add("application/x-ms-wmz", "wmz"); - add("application/x-msi", "msi"); - add("application/x-ns-proxy-autoconfig", "pac"); - add("application/x-nwc", "nwc"); - add("application/x-object", "o"); - add("application/x-oz-application", "oza"); - add("application/x-pem-file", "pem"); - add("application/x-pkcs12", "p12"); - add("application/x-pkcs12", "pfx"); - add("application/x-pkcs7-certreqresp", "p7r"); - add("application/x-pkcs7-crl", "crl"); - add("application/x-quicktimeplayer", "qtl"); - add("application/x-shar", "shar"); - add("application/x-shockwave-flash", "swf"); - add("application/x-stuffit", "sit"); - add("application/x-sv4cpio", "sv4cpio"); - add("application/x-sv4crc", "sv4crc"); - add("application/x-tar", "tar"); - add("application/x-texinfo", "texinfo"); - add("application/x-texinfo", "texi"); - add("application/x-troff", "t"); - add("application/x-troff", "roff"); - add("application/x-troff-man", "man"); - add("application/x-ustar", "ustar"); - add("application/x-wais-source", "src"); - add("application/x-wingz", "wz"); - add("application/x-webarchive", "webarchive"); - add("application/x-webarchive-xml", "webarchivexml"); - add("application/x-x509-ca-cert", "crt"); - add("application/x-x509-user-cert", "crt"); - add("application/x-x509-server-cert", "crt"); - add("application/x-xcf", "xcf"); - add("application/x-xfig", "fig"); - add("application/xhtml+xml", "xhtml"); - add("audio/3gpp", "3gpp"); - add("audio/aac", "aac"); - add("audio/aac-adts", "aac"); - add("audio/amr", "amr"); - add("audio/amr-wb", "awb"); - add("audio/basic", "snd"); - add("audio/flac", "flac"); - add("application/x-flac", "flac"); - add("audio/imelody", "imy"); - add("audio/midi", "mid"); - add("audio/midi", "midi"); - add("audio/midi", "ota"); - add("audio/midi", "kar"); - add("audio/midi", "rtttl"); - add("audio/midi", "xmf"); - add("audio/mobile-xmf", "mxmf"); - // add ".mp3" first so it will be the default for guessExtensionFromMimeType - add("audio/mpeg", "mp3"); - add("audio/mpeg", "mpga"); - add("audio/mpeg", "mpega"); - add("audio/mpeg", "mp2"); - add("audio/mpeg", "m4a"); - add("audio/mpegurl", "m3u"); - add("audio/prs.sid", "sid"); - add("audio/x-aiff", "aif"); - add("audio/x-aiff", "aiff"); - add("audio/x-aiff", "aifc"); - add("audio/x-gsm", "gsm"); - add("audio/x-matroska", "mka"); - add("audio/x-mpegurl", "m3u"); - add("audio/x-ms-wma", "wma"); - add("audio/x-ms-wax", "wax"); - add("audio/x-pn-realaudio", "ra"); - add("audio/x-pn-realaudio", "rm"); - add("audio/x-pn-realaudio", "ram"); - add("audio/x-realaudio", "ra"); - add("audio/x-scpls", "pls"); - add("audio/x-sd2", "sd2"); - add("audio/x-wav", "wav"); - // image/bmp isn't IANA, so image/x-ms-bmp should come first. - add("image/x-ms-bmp", "bmp"); - add("image/bmp", "bmp"); - add("image/gif", "gif"); - // image/ico isn't IANA, so image/x-icon should come first. - add("image/x-icon", "ico"); - add("image/ico", "cur"); - add("image/ico", "ico"); - add("image/ief", "ief"); - // add ".jpg" first so it will be the default for guessExtensionFromMimeType - add("image/jpeg", "jpg"); - add("image/jpeg", "jpeg"); - add("image/jpeg", "jpe"); - add("image/pcx", "pcx"); - add("image/png", "png"); - add("image/svg+xml", "svg"); - add("image/svg+xml", "svgz"); - add("image/tiff", "tiff"); - add("image/tiff", "tif"); - add("image/vnd.djvu", "djvu"); - add("image/vnd.djvu", "djv"); - add("image/vnd.wap.wbmp", "wbmp"); - add("image/webp", "webp"); - add("image/x-cmu-raster", "ras"); - add("image/x-coreldraw", "cdr"); - add("image/x-coreldrawpattern", "pat"); - add("image/x-coreldrawtemplate", "cdt"); - add("image/x-corelphotopaint", "cpt"); - add("image/x-jg", "art"); - add("image/x-jng", "jng"); - add("image/x-photoshop", "psd"); - add("image/x-portable-anymap", "pnm"); - add("image/x-portable-bitmap", "pbm"); - add("image/x-portable-graymap", "pgm"); - add("image/x-portable-pixmap", "ppm"); - add("image/x-rgb", "rgb"); - add("image/x-xbitmap", "xbm"); - add("image/x-xpixmap", "xpm"); - add("image/x-xwindowdump", "xwd"); - add("model/iges", "igs"); - add("model/iges", "iges"); - add("model/mesh", "msh"); - add("model/mesh", "mesh"); - add("model/mesh", "silo"); - add("text/calendar", "ics"); - add("text/calendar", "icz"); - add("text/comma-separated-values", "csv"); - add("text/css", "css"); - add("text/html", "htm"); - add("text/html", "html"); - add("text/h323", "323"); - add("text/iuls", "uls"); - add("text/mathml", "mml"); - // add ".txt" first so it will be the default for guessExtensionFromMimeType - add("text/plain", "txt"); - add("text/plain", "asc"); - add("text/plain", "text"); - add("text/plain", "diff"); - add("text/plain", "po"); // reserve "pot" for vnd.ms-powerpoint - add("text/richtext", "rtx"); - add("text/rtf", "rtf"); - add("text/text", "phps"); - add("text/tab-separated-values", "tsv"); - add("text/xml", "xml"); - add("text/x-bibtex", "bib"); - add("text/x-boo", "boo"); - add("text/x-c++hdr", "hpp"); - add("text/x-c++hdr", "h++"); - add("text/x-c++hdr", "hxx"); - add("text/x-c++hdr", "hh"); - add("text/x-c++src", "cpp"); - add("text/x-c++src", "c++"); - add("text/x-c++src", "cc"); - add("text/x-c++src", "cxx"); - add("text/x-chdr", "h"); - add("text/x-component", "htc"); - add("text/x-csh", "csh"); - add("text/x-csrc", "c"); - add("text/x-dsrc", "d"); - add("text/x-haskell", "hs"); - add("text/x-java", "java"); - add("text/x-literate-haskell", "lhs"); - add("text/x-moc", "moc"); - add("text/x-pascal", "p"); - add("text/x-pascal", "pas"); - add("text/x-pcs-gcd", "gcd"); - add("text/x-setext", "etx"); - add("text/x-tcl", "tcl"); - add("text/x-tex", "tex"); - add("text/x-tex", "ltx"); - add("text/x-tex", "sty"); - add("text/x-tex", "cls"); - add("text/x-vcalendar", "vcs"); - add("text/x-vcard", "vcf"); - add("video/3gpp", "3gpp"); - add("video/3gpp", "3gp"); - add("video/3gpp2", "3gpp2"); - add("video/3gpp2", "3g2"); - add("video/avi", "avi"); - add("video/dl", "dl"); - add("video/dv", "dif"); - add("video/dv", "dv"); - add("video/fli", "fli"); - add("video/m4v", "m4v"); - add("video/mp2ts", "ts"); - add("video/mpeg", "mpeg"); - add("video/mpeg", "mpg"); - add("video/mpeg", "mpe"); - add("video/mp4", "mp4"); - add("video/mpeg", "VOB"); - add("video/quicktime", "qt"); - add("video/quicktime", "mov"); - add("video/vnd.mpegurl", "mxu"); - add("video/webm", "webm"); - add("video/x-la-asf", "lsf"); - add("video/x-la-asf", "lsx"); - add("video/x-matroska", "mkv"); - add("video/x-mng", "mng"); - add("video/x-ms-asf", "asf"); - add("video/x-ms-asf", "asx"); - add("video/x-ms-wm", "wm"); - add("video/x-ms-wmv", "wmv"); - add("video/x-ms-wmx", "wmx"); - add("video/x-ms-wvx", "wvx"); - add("video/x-sgi-movie", "movie"); - add("video/x-webex", "wrf"); - add("x-conference/x-cooltalk", "ice"); - add("x-epoc/x-sisx-app", "sisx"); - applyOverrides(); - } - private static void add(String mimeType, String extension) { - // If we have an existing x -> y mapping, we do not want to - // override it with another mapping x -> y2. - // If a mime type maps to several extensions - // the first extension added is considered the most popular - // so we do not want to overwrite it later. - if (!mimeTypeToExtensionMap.containsKey(mimeType)) { - mimeTypeToExtensionMap.put(mimeType, extension); - } - if (!extensionToMimeTypeMap.containsKey(extension)) { - extensionToMimeTypeMap.put(extension, mimeType); - } - } - private static InputStream getContentTypesPropertiesStream() { - // User override? - String userTable = System.getProperty("content.types.user.table"); - if (userTable != null) { - File f = new File(userTable); - if (f.exists()) { - try { - return new FileInputStream(f); - } catch (IOException ignored) { - } - } - } - // Standard location? - File f = new File(System.getProperty("java.home"), "lib" + File.separator + "content-types.properties"); - if (f.exists()) { - try { - return new FileInputStream(f); - } catch (IOException ignored) { - } - } - return null; - } - /** - * This isn't what the RI does. The RI doesn't have hard-coded defaults, so supplying your - * own "content.types.user.table" means you don't get any of the built-ins, and the built-ins - * come from "$JAVA_HOME/lib/content-types.properties". - */ - private static void applyOverrides() { - // Get the appropriate InputStream to read overrides from, if any. - InputStream stream = getContentTypesPropertiesStream(); - if (stream == null) { - return; - } - try { - try { - // Read the properties file... - Properties overrides = new Properties(); - overrides.load(stream); - // And translate its mapping to ours... - for (Map.Entry<Object, Object> entry : overrides.entrySet()) { - String extension = (String) entry.getKey(); - String mimeType = (String) entry.getValue(); - add(mimeType, extension); - } - } finally { - stream.close(); - } - } catch (IOException ignored) { - } - } - private MimeUtils() { - } - /** - * Returns true if the given MIME type has an entry in the map. - * @param mimeType A MIME type (i.e. text/plain) - * @return True iff there is a mimeType entry in the map. - */ - public static boolean hasMimeType(String mimeType) { - if (mimeType == null || mimeType.isEmpty()) { - return false; - } - return mimeTypeToExtensionMap.containsKey(mimeType); - } - /** - * Returns the MIME type for the given extension. - * @param extension A file extension without the leading '.' - * @return The MIME type for the given extension or null iff there is none. - */ - public static String guessMimeTypeFromExtension(String extension) { - if (extension == null || extension.isEmpty()) { - return null; - } - return extensionToMimeTypeMap.get(extension.toLowerCase()); - } - /** - * Returns true if the given extension has a registered MIME type. - * @param extension A file extension without the leading '.' - * @return True iff there is an extension entry in the map. - */ - public static boolean hasExtension(String extension) { - if (extension == null || extension.isEmpty()) { - return false; - } - return extensionToMimeTypeMap.containsKey(extension); - } - /** - * Returns the registered extension for the given MIME type. Note that some - * MIME types map to multiple extensions. This call will return the most - * common extension for the given MIME type. - * @param mimeType A MIME type (i.e. text/plain) - * @return The extension for the given MIME type or null iff there is none. - */ - public static String guessExtensionFromMimeType(String mimeType) { - if (mimeType == null || mimeType.isEmpty()) { - return null; - } - return mimeTypeToExtensionMap.get(mimeType); - } -} diff --git a/src/main/java/eu/siacs/conversations/utils/OnPhoneContactsLoadedListener.java b/src/main/java/eu/siacs/conversations/utils/OnPhoneContactsLoadedListener.java deleted file mode 100644 index f18a4ed8e..000000000 --- a/src/main/java/eu/siacs/conversations/utils/OnPhoneContactsLoadedListener.java +++ /dev/null @@ -1,9 +0,0 @@ -package eu.siacs.conversations.utils; - -import android.os.Bundle; - -import java.util.List; - -public interface OnPhoneContactsLoadedListener { - public void onPhoneContactsLoaded(List<Bundle> phoneContacts); -} diff --git a/src/main/java/eu/siacs/conversations/utils/PRNGFixes.java b/src/main/java/eu/siacs/conversations/utils/PRNGFixes.java deleted file mode 100644 index 8fe67234e..000000000 --- a/src/main/java/eu/siacs/conversations/utils/PRNGFixes.java +++ /dev/null @@ -1,327 +0,0 @@ -package eu.siacs.conversations.utils; - -import android.os.Build; -import android.os.Process; -import android.util.Log; - -import java.io.ByteArrayOutputStream; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.io.UnsupportedEncodingException; -import java.security.NoSuchAlgorithmException; -import java.security.Provider; -import java.security.SecureRandom; -import java.security.SecureRandomSpi; -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(); - - /** 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 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()); - - // 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; - } - - // 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()); - } - - 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 { - - 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 { - - /* - * 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 Object sLock = new Object(); - - /** - * 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; - - /** - * 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 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); - } - } - - @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 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); - } - } - - /** - * 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"); - } - } -}
\ No newline at end of file diff --git a/src/main/java/eu/siacs/conversations/utils/PhoneHelper.java b/src/main/java/eu/siacs/conversations/utils/PhoneHelper.java deleted file mode 100644 index e77b2bae3..000000000 --- a/src/main/java/eu/siacs/conversations/utils/PhoneHelper.java +++ /dev/null @@ -1,142 +0,0 @@ -package eu.siacs.conversations.utils; - -import android.Manifest; -import android.content.Context; -import android.content.CursorLoader; -import android.content.Loader; -import android.content.Loader.OnLoadCompleteListener; -import android.content.pm.PackageManager; -import android.database.Cursor; -import android.net.Uri; -import android.os.Build; -import android.os.Bundle; -import android.provider.ContactsContract; -import android.provider.ContactsContract.Profile; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.RejectedExecutionException; - -public class PhoneHelper { - - public static void loadPhoneContacts(Context context, final OnPhoneContactsLoadedListener listener) { - final List<Bundle> phoneContacts = new ArrayList<>(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M - && context.checkSelfPermission(Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) { - listener.onPhoneContactsLoaded(phoneContacts); - return; - } - final String[] PROJECTION = new String[]{ContactsContract.Data._ID, - ContactsContract.Data.DISPLAY_NAME, - ContactsContract.Data.PHOTO_URI, - ContactsContract.Data.LOOKUP_KEY, - ContactsContract.CommonDataKinds.Im.DATA}; - - final String SELECTION = "(" + ContactsContract.Data.MIMETYPE + "=\"" - + ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE - + "\") AND (" + ContactsContract.CommonDataKinds.Im.PROTOCOL - + "=\"" + ContactsContract.CommonDataKinds.Im.PROTOCOL_JABBER - + "\")"; - - CursorLoader mCursorLoader = new NotThrowCursorLoader(context, - ContactsContract.Data.CONTENT_URI, PROJECTION, SELECTION, null, - null); - mCursorLoader.registerListener(0, new OnLoadCompleteListener<Cursor>() { - - @Override - public void onLoadComplete(Loader<Cursor> arg0, Cursor cursor) { - if (cursor != null) { - while (cursor.moveToNext()) { - Bundle contact = new Bundle(); - contact.putInt("phoneid", cursor.getInt(cursor - .getColumnIndex(ContactsContract.Data._ID))); - contact.putString( - "displayname", - cursor.getString(cursor - .getColumnIndex(ContactsContract.Data.DISPLAY_NAME))); - contact.putString("photouri", cursor.getString(cursor - .getColumnIndex(ContactsContract.Data.PHOTO_URI))); - contact.putString("lookup", cursor.getString(cursor - .getColumnIndex(ContactsContract.Data.LOOKUP_KEY))); - - contact.putString( - "jid", - cursor.getString(cursor - .getColumnIndex(ContactsContract.CommonDataKinds.Im.DATA))); - phoneContacts.add(contact); - } - cursor.close(); - } - - if (listener != null) { - listener.onPhoneContactsLoaded(phoneContacts); - } - } - }); - try { - mCursorLoader.startLoading(); - } catch (RejectedExecutionException e) { - if (listener != null) { - listener.onPhoneContactsLoaded(phoneContacts); - } - } - } - - private static class NotThrowCursorLoader extends CursorLoader { - - public NotThrowCursorLoader(Context c, Uri u, String[] p, String s, String[] sa, String so) { - super(c, u, p, s, sa, so); - } - - @Override - public Cursor loadInBackground() { - - try { - return (super.loadInBackground()); - } catch (SecurityException e) { - return(null); - } - } - - } - - public static Uri getSefliUri(Context context) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M - && context.checkSelfPermission(Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) { - return null; - } - String[] mProjection = new String[]{Profile._ID, Profile.PHOTO_URI}; - Cursor mProfileCursor = context.getContentResolver().query( - Profile.CONTENT_URI, mProjection, null, null, null); - - if (mProfileCursor == null || mProfileCursor.getCount() == 0) { - return null; - } else { - mProfileCursor.moveToFirst(); - String uri = mProfileCursor.getString(1); - mProfileCursor.close(); - if (uri == null) { - return null; - } else { - return Uri.parse(uri); - } - } - } - - public static String getVersionName(Context context) { - final String packageName = context == null ? null : context.getPackageName(); - if (packageName != null) { - try { - return context.getPackageManager().getPackageInfo(packageName, 0).versionName; - } catch (final PackageManager.NameNotFoundException | RuntimeException e) { - return "unknown"; - } - } else { - return "unknown"; - } - } - - public static String getOSVersion(Context context) { - return "Android/" + android.os.Build.MODEL + "/" + android.os.Build.VERSION.RELEASE; - } -} diff --git a/src/main/java/eu/siacs/conversations/utils/ReplacingSerialSingleThreadExecutor.java b/src/main/java/eu/siacs/conversations/utils/ReplacingSerialSingleThreadExecutor.java deleted file mode 100644 index dc8a0a825..000000000 --- a/src/main/java/eu/siacs/conversations/utils/ReplacingSerialSingleThreadExecutor.java +++ /dev/null @@ -1,14 +0,0 @@ -package eu.siacs.conversations.utils; - -public class ReplacingSerialSingleThreadExecutor extends SerialSingleThreadExecutor { - - public ReplacingSerialSingleThreadExecutor(boolean prepareLooper) { - super(prepareLooper); - } - - @Override - public synchronized void execute(final Runnable r) { - tasks.clear(); - super.execute(r); - } -} diff --git a/src/main/java/eu/siacs/conversations/utils/SSLSocketHelper.java b/src/main/java/eu/siacs/conversations/utils/SSLSocketHelper.java deleted file mode 100644 index 3a8c1c0aa..000000000 --- a/src/main/java/eu/siacs/conversations/utils/SSLSocketHelper.java +++ /dev/null @@ -1,73 +0,0 @@ -package eu.siacs.conversations.utils; - -import android.os.Build; - -import java.lang.reflect.Method; -import java.security.NoSuchAlgorithmException; -import java.util.Arrays; -import java.util.Collection; -import java.util.LinkedList; - -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLSocket; -import javax.net.ssl.SSLSocketFactory; - -public class SSLSocketHelper { - - public static void setSecurity(final SSLSocket sslSocket) throws NoSuchAlgorithmException { - final String[] supportProtocols; - final Collection<String> supportedProtocols = new LinkedList<>( - Arrays.asList(sslSocket.getSupportedProtocols())); - supportedProtocols.remove("SSLv3"); - supportProtocols = supportedProtocols.toArray(new String[supportedProtocols.size()]); - - sslSocket.setEnabledProtocols(supportProtocols); - - final String[] cipherSuites = CryptoHelper.getOrderedCipherSuites( - sslSocket.getSupportedCipherSuites()); - if (cipherSuites.length > 0) { - sslSocket.setEnabledCipherSuites(cipherSuites); - } - } - - public static void setSNIHost(final SSLSocketFactory factory, final SSLSocket socket, final String hostname) { - if (factory instanceof android.net.SSLCertificateSocketFactory && android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) { - ((android.net.SSLCertificateSocketFactory) factory).setHostname(socket, hostname); - } else { - try { - socket.getClass().getMethod("setHostname", String.class).invoke(socket, hostname); - } catch (Throwable e) { - // ignore any error, we just can't set the hostname... - } - } - } - - public static void setAlpnProtocol(final SSLSocketFactory factory, final SSLSocket socket, final String protocol) { - try { - if (factory instanceof android.net.SSLCertificateSocketFactory && android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) { - // can't call directly because of @hide? - //((android.net.SSLCertificateSocketFactory)factory).setAlpnProtocols(new byte[][]{protocol.getBytes("UTF-8")}); - android.net.SSLCertificateSocketFactory.class.getMethod("setAlpnProtocols", byte[][].class).invoke(socket, new Object[]{new byte[][]{protocol.getBytes("UTF-8")}}); - } else { - final Method method = socket.getClass().getMethod("setAlpnProtocols", byte[].class); - // the concatenation of 8-bit, length prefixed protocol names, just one in our case... - // http://tools.ietf.org/html/draft-agl-tls-nextprotoneg-04#page-4 - final byte[] protocolUTF8Bytes = protocol.getBytes("UTF-8"); - final byte[] lengthPrefixedProtocols = new byte[protocolUTF8Bytes.length + 1]; - lengthPrefixedProtocols[0] = (byte) protocol.length(); // cannot be over 255 anyhow - System.arraycopy(protocolUTF8Bytes, 0, lengthPrefixedProtocols, 1, protocolUTF8Bytes.length); - method.invoke(socket, new Object[]{lengthPrefixedProtocols}); - } - } catch (Throwable e) { - // ignore any error, we just can't set the alpn protocol... - } - } - - public static SSLContext getSSLContext() throws NoSuchAlgorithmException { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { - return SSLContext.getInstance("TLSv1.2"); - } else { - return SSLContext.getInstance("TLS"); - } - } -} diff --git a/src/main/java/eu/siacs/conversations/utils/SerialSingleThreadExecutor.java b/src/main/java/eu/siacs/conversations/utils/SerialSingleThreadExecutor.java deleted file mode 100644 index 55489ee30..000000000 --- a/src/main/java/eu/siacs/conversations/utils/SerialSingleThreadExecutor.java +++ /dev/null @@ -1,51 +0,0 @@ -package eu.siacs.conversations.utils; - -import android.os.Looper; - -import java.util.ArrayDeque; -import java.util.Queue; -import java.util.concurrent.Executor; -import java.util.concurrent.Executors; - -public class SerialSingleThreadExecutor implements Executor { - - final Executor executor = Executors.newSingleThreadExecutor(); - protected final Queue<Runnable> tasks = new ArrayDeque(); - Runnable active; - - public SerialSingleThreadExecutor() { - this(false); - } - - public SerialSingleThreadExecutor(boolean prepareLooper) { - if (prepareLooper) { - execute(new Runnable() { - @Override - public void run() { - Looper.prepare(); - } - }); - } - } - - public synchronized void execute(final Runnable r) { - tasks.offer(new Runnable() { - public void run() { - try { - r.run(); - } finally { - scheduleNext(); - } - } - }); - if (active == null) { - scheduleNext(); - } - } - - protected synchronized void scheduleNext() { - if ((active = tasks.poll()) != null) { - executor.execute(active); - } - } -}
\ No newline at end of file diff --git a/src/main/java/eu/siacs/conversations/utils/SocksSocketFactory.java b/src/main/java/eu/siacs/conversations/utils/SocksSocketFactory.java deleted file mode 100644 index 768e9f17b..000000000 --- a/src/main/java/eu/siacs/conversations/utils/SocksSocketFactory.java +++ /dev/null @@ -1,57 +0,0 @@ -package eu.siacs.conversations.utils; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.Socket; -import java.nio.ByteBuffer; - -import eu.siacs.conversations.Config; - -public class SocksSocketFactory { - - public static void createSocksConnection(Socket socket, String destination, int port) throws IOException { - InputStream proxyIs = socket.getInputStream(); - OutputStream proxyOs = socket.getOutputStream(); - proxyOs.write(new byte[]{0x05, 0x01, 0x00}); - byte[] response = new byte[2]; - proxyIs.read(response); - byte[] dest = destination.getBytes(); - ByteBuffer request = ByteBuffer.allocate(7 + dest.length); - request.put(new byte[]{0x05, 0x01, 0x00, 0x03}); - request.put((byte) dest.length); - request.put(dest); - request.putShort((short) port); - proxyOs.write(request.array()); - response = new byte[7 + dest.length]; - proxyIs.read(response); - if (response[1] != 0x00) { - throw new SocksConnectionException(); - } - } - - public static Socket createSocket(InetSocketAddress address, String destination, int port) throws IOException { - Socket socket = new Socket(); - try { - socket.connect(address, Config.CONNECT_TIMEOUT * 1000); - } catch (IOException e) { - throw new SocksProxyNotFoundException(); - } - createSocksConnection(socket, destination, port); - return socket; - } - - public static Socket createSocketOverTor(String destination, int port) throws IOException { - return createSocket(new InetSocketAddress(InetAddress.getLocalHost(), 9050), destination, port); - } - - static class SocksConnectionException extends IOException { - - } - - public static class SocksProxyNotFoundException extends IOException { - - } -} diff --git a/src/main/java/eu/siacs/conversations/utils/UIHelper.java b/src/main/java/eu/siacs/conversations/utils/UIHelper.java deleted file mode 100644 index acc7f28c5..000000000 --- a/src/main/java/eu/siacs/conversations/utils/UIHelper.java +++ /dev/null @@ -1,289 +0,0 @@ -package eu.siacs.conversations.utils; - -import android.content.Context; -import android.text.format.DateFormat; -import android.text.format.DateUtils; -import android.util.Pair; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Calendar; -import java.util.Date; -import java.util.Locale; - -import eu.siacs.conversations.R; -import eu.siacs.conversations.entities.Contact; -import eu.siacs.conversations.entities.Conversation; -import eu.siacs.conversations.entities.ListItem; -import eu.siacs.conversations.entities.Message; -import eu.siacs.conversations.entities.Presence; -import eu.siacs.conversations.entities.Transferable; -import eu.siacs.conversations.xmpp.jid.Jid; - -public class UIHelper { - - private static String BLACK_HEART_SUIT = "\u2665"; - private static String HEAVY_BLACK_HEART_SUIT = "\u2764"; - private static String WHITE_HEART_SUIT = "\u2661"; - - public static final ArrayList<String> HEARTS = new ArrayList<>(Arrays.asList(BLACK_HEART_SUIT,HEAVY_BLACK_HEART_SUIT,WHITE_HEART_SUIT)); - - private static final ArrayList<String> LOCATION_QUESTIONS = new ArrayList<>(Arrays.asList( - "where are you", //en - "where are you now", //en - "where are you right now", //en - "whats your 20", //en - "what is your 20", //en - "what's your 20", //en - "whats your twenty", //en - "what is your twenty", //en - "what's your twenty", //en - "wo bist du", //de - "wo bist du jetzt", //de - "wo bist du gerade", //de - "wo seid ihr", //de - "wo seid ihr jetzt", //de - "wo seid ihr gerade", //de - "dónde estás", //es - "donde estas" //es - )); - - private static final int SHORT_DATE_FLAGS = DateUtils.FORMAT_SHOW_DATE - | DateUtils.FORMAT_NO_YEAR | DateUtils.FORMAT_ABBREV_ALL; - private static final int FULL_DATE_FLAGS = DateUtils.FORMAT_SHOW_TIME - | DateUtils.FORMAT_ABBREV_ALL | DateUtils.FORMAT_SHOW_DATE; - - public static String readableTimeDifference(Context context, long time) { - return readableTimeDifference(context, time, false); - } - - public static String readableTimeDifferenceFull(Context context, long time) { - return readableTimeDifference(context, time, true); - } - - private static String readableTimeDifference(Context context, long time, - boolean fullDate) { - if (time == 0) { - return context.getString(R.string.just_now); - } - Date date = new Date(time); - long difference = (System.currentTimeMillis() - time) / 1000; - if (difference < 60) { - return context.getString(R.string.just_now); - } else if (difference < 60 * 2) { - return context.getString(R.string.minute_ago); - } else if (difference < 60 * 15) { - return context.getString(R.string.minutes_ago, - Math.round(difference / 60.0)); - } else if (today(date)) { - java.text.DateFormat df = DateFormat.getTimeFormat(context); - return df.format(date); - } else { - if (fullDate) { - return DateUtils.formatDateTime(context, date.getTime(), - FULL_DATE_FLAGS); - } else { - return DateUtils.formatDateTime(context, date.getTime(), - SHORT_DATE_FLAGS); - } - } - } - - private static boolean today(Date date) { - return sameDay(date,new Date(System.currentTimeMillis())); - } - - public static boolean sameDay(long timestamp1, long timestamp2) { - return sameDay(new Date(timestamp1),new Date(timestamp2)); - } - - private static boolean sameDay(Date a, Date b) { - Calendar cal1 = Calendar.getInstance(); - Calendar cal2 = Calendar.getInstance(); - cal1.setTime(a); - cal2.setTime(b); - return cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) - && cal1.get(Calendar.DAY_OF_YEAR) == cal2 - .get(Calendar.DAY_OF_YEAR); - } - - public static String lastseen(Context context, boolean active, long time) { - long difference = (System.currentTimeMillis() - time) / 1000; - active = active && difference <= 300; - if (active || difference < 60) { - return context.getString(R.string.last_seen_now); - } else if (difference < 60 * 2) { - return context.getString(R.string.last_seen_min); - } else if (difference < 60 * 60) { - return context.getString(R.string.last_seen_mins, - Math.round(difference / 60.0)); - } else if (difference < 60 * 60 * 2) { - return context.getString(R.string.last_seen_hour); - } else if (difference < 60 * 60 * 24) { - return context.getString(R.string.last_seen_hours, - Math.round(difference / (60.0 * 60.0))); - } else if (difference < 60 * 60 * 48) { - return context.getString(R.string.last_seen_day); - } else { - return context.getString(R.string.last_seen_days, - Math.round(difference / (60.0 * 60.0 * 24.0))); - } - } - - public static int getColorForName(String name) { - if (name == null || name.isEmpty()) { - return 0xFF202020; - } - int colors[] = {0xFFe91e63, 0xFF9c27b0, 0xFF673ab7, 0xFF3f51b5, - 0xFF5677fc, 0xFF03a9f4, 0xFF00bcd4, 0xFF009688, 0xFFff5722, - 0xFF795548, 0xFF607d8b}; - return colors[(int) ((name.hashCode() & 0xffffffffl) % colors.length)]; - } - - public static Pair<String,Boolean> getMessagePreview(final Context context, final Message message) { - final Transferable d = message.getTransferable(); - if (d != null ) { - switch (d.getStatus()) { - case Transferable.STATUS_CHECKING: - return new Pair<>(context.getString(R.string.checking_x, - getFileDescriptionString(context,message)),true); - case Transferable.STATUS_DOWNLOADING: - return new Pair<>(context.getString(R.string.receiving_x_file, - getFileDescriptionString(context,message), - d.getProgress()),true); - case Transferable.STATUS_OFFER: - case Transferable.STATUS_OFFER_CHECK_FILESIZE: - return new Pair<>(context.getString(R.string.x_file_offered_for_download, - getFileDescriptionString(context,message)),true); - case Transferable.STATUS_DELETED: - return new Pair<>(context.getString(R.string.file_deleted),true); - case Transferable.STATUS_FAILED: - return new Pair<>(context.getString(R.string.file_transmission_failed),true); - case Transferable.STATUS_UPLOADING: - if (message.getStatus() == Message.STATUS_OFFERED) { - return new Pair<>(context.getString(R.string.offering_x_file, - getFileDescriptionString(context, message)), true); - } else { - return new Pair<>(context.getString(R.string.sending_x_file, - getFileDescriptionString(context, message)), true); - } - default: - return new Pair<>("",false); - } - } else if (message.getEncryption() == Message.ENCRYPTION_PGP) { - return new Pair<>(context.getString(R.string.pgp_message),true); - } else if (message.getEncryption() == Message.ENCRYPTION_DECRYPTION_FAILED) { - return new Pair<>(context.getString(R.string.decryption_failed), true); - } else if (message.getType() == Message.TYPE_FILE || message.getType() == Message.TYPE_IMAGE) { - if (message.getStatus() == Message.STATUS_RECEIVED) { - return new Pair<>(context.getString(R.string.received_x_file, - getFileDescriptionString(context, message)), true); - } else { - return new Pair<>(getFileDescriptionString(context,message),true); - } - } else { - String body = message.getBody(); - if (body.length() > 256) { - body = body.substring(0,256); - } - if (body.startsWith(Message.ME_COMMAND)) { - return new Pair<>(body.replaceAll("^" + Message.ME_COMMAND, - UIHelper.getMessageDisplayName(message) + " "), false); - } else if (GeoHelper.isGeoUri(message.getBody())) { - if (message.getStatus() == Message.STATUS_RECEIVED) { - return new Pair<>(context.getString(R.string.received_location), true); - } else { - return new Pair<>(context.getString(R.string.location), true); - } - } else if (message.treatAsDownloadable() == Message.Decision.MUST) { - return new Pair<>(context.getString(R.string.x_file_offered_for_download, - getFileDescriptionString(context,message)),true); - } else{ - return new Pair<>(body.trim(), false); - } - } - } - - public static String getFileDescriptionString(final Context context, final Message message) { - if (message.getType() == Message.TYPE_IMAGE) { - return context.getString(R.string.image); - } - final String mime = message.getMimeType(); - if (mime == null) { - return context.getString(R.string.file); - } else if (mime.startsWith("audio/")) { - return context.getString(R.string.audio); - } else if(mime.startsWith("video/")) { - return context.getString(R.string.video); - } else if (mime.startsWith("image/")) { - return context.getString(R.string.image); - } else if (mime.contains("pdf")) { - return context.getString(R.string.pdf_document) ; - } else if (mime.contains("application/vnd.android.package-archive")) { - return context.getString(R.string.apk) ; - } else if (mime.contains("vcard")) { - return context.getString(R.string.vcard) ; - } else { - return mime; - } - } - - public static String getMessageDisplayName(final Message message) { - final Conversation conversation = message.getConversation(); - if (message.getStatus() == Message.STATUS_RECEIVED) { - final Contact contact = message.getContact(); - if (conversation.getMode() == Conversation.MODE_MULTI) { - if (contact != null) { - return contact.getDisplayName(); - } else { - return getDisplayedMucCounterpart(message.getCounterpart()); - } - } else { - return contact != null ? contact.getDisplayName() : ""; - } - } else { - if (conversation.getMode() == Conversation.MODE_MULTI) { - return conversation.getMucOptions().getSelf().getName(); - } else { - final Jid jid = conversation.getAccount().getJid(); - return jid.hasLocalpart() ? jid.getLocalpart() : jid.toDomainJid().toString(); - } - } - } - - public static String getDisplayedMucCounterpart(final Jid counterpart) { - if (counterpart==null) { - return ""; - } else if (!counterpart.isBareJid()) { - return counterpart.getResourcepart().trim(); - } else { - return counterpart.toString().trim(); - } - } - - public static boolean receivedLocationQuestion(Message message) { - if (message == null - || message.getStatus() != Message.STATUS_RECEIVED - || message.getType() != Message.TYPE_TEXT) { - return false; - } - String body = message.getBody() == null ? null : message.getBody().trim().toLowerCase(Locale.getDefault()); - body = body.replace("?","").replace("¿",""); - return LOCATION_QUESTIONS.contains(body); - } - - public static ListItem.Tag getTagForStatus(Context context, Presence.Status status) { - switch (status) { - case CHAT: - return new ListItem.Tag(context.getString(R.string.presence_chat), 0xff259b24); - case AWAY: - return new ListItem.Tag(context.getString(R.string.presence_away), 0xffff9800); - case XA: - return new ListItem.Tag(context.getString(R.string.presence_xa), 0xfff44336); - case DND: - return new ListItem.Tag(context.getString(R.string.presence_dnd), 0xfff44336); - default: - return new ListItem.Tag(context.getString(R.string.presence_online), 0xff259b24); - } - } -} diff --git a/src/main/java/eu/siacs/conversations/utils/XmlHelper.java b/src/main/java/eu/siacs/conversations/utils/XmlHelper.java deleted file mode 100644 index 9e062f0da..000000000 --- a/src/main/java/eu/siacs/conversations/utils/XmlHelper.java +++ /dev/null @@ -1,13 +0,0 @@ -package eu.siacs.conversations.utils; - -public class XmlHelper { - public static String encodeEntities(String content) { - content = content.replace("&", "&"); - content = content.replace("<", "<"); - content = content.replace(">", ">"); - content = content.replace("\"", """); - content = content.replace("'", "'"); - content = content.replaceAll("[\\p{Cntrl}&&[^\n\t\r]]", ""); - return content; - } -} diff --git a/src/main/java/eu/siacs/conversations/utils/Xmlns.java b/src/main/java/eu/siacs/conversations/utils/Xmlns.java deleted file mode 100644 index de0a29ce2..000000000 --- a/src/main/java/eu/siacs/conversations/utils/Xmlns.java +++ /dev/null @@ -1,9 +0,0 @@ -package eu.siacs.conversations.utils; - -public final class Xmlns { - public static final String BLOCKING = "urn:xmpp:blocking"; - public static final String ROSTER = "jabber:iq:roster"; - public static final String REGISTER = "jabber:iq:register"; - public static final String BYTE_STREAMS = "http://jabber.org/protocol/bytestreams"; - public static final String HTTP_UPLOAD = "urn:xmpp:http:upload"; -} diff --git a/src/main/java/eu/siacs/conversations/utils/XmppUri.java b/src/main/java/eu/siacs/conversations/utils/XmppUri.java deleted file mode 100644 index 4039f8b0a..000000000 --- a/src/main/java/eu/siacs/conversations/utils/XmppUri.java +++ /dev/null @@ -1,101 +0,0 @@ -package eu.siacs.conversations.utils; - -import android.net.Uri; - -import java.io.UnsupportedEncodingException; -import java.net.URLDecoder; -import java.util.List; - -import eu.siacs.conversations.xmpp.jid.InvalidJidException; -import eu.siacs.conversations.xmpp.jid.Jid; - -public class XmppUri { - - protected String jid; - protected boolean muc; - protected String fingerprint; - - public XmppUri(String uri) { - try { - parse(Uri.parse(uri)); - } catch (IllegalArgumentException e) { - try { - jid = Jid.fromString(uri).toBareJid().toString(); - } catch (InvalidJidException e2) { - jid = null; - } - } - } - - public XmppUri(Uri uri) { - parse(uri); - } - - protected void parse(Uri uri) { - String scheme = uri.getScheme(); - String host = uri.getHost(); - List<String> segments = uri.getPathSegments(); - if ("https".equalsIgnoreCase(scheme) && "jabber.pix-art.de".equalsIgnoreCase(host)) { - if (segments.size() >= 2 && segments.get(1).contains("@")) { - // sample : https://conversations.im/i/foo@bar.com - try { - jid = Jid.fromString(segments.get(1)).toString(); - } catch (Exception e) { - jid = null; - } - } else if (segments.size() >= 3) { - // sample : https://conversations.im/i/foo/bar.com - jid = segments.get(1) + "@" + segments.get(2); - } - muc = segments.size() > 1 && "j".equalsIgnoreCase(segments.get(0)); - } else if ("xmpp".equalsIgnoreCase(scheme)) { - // sample: xmpp:foo@bar.com - muc = "join".equalsIgnoreCase(uri.getQuery()); - if (uri.getAuthority() != null) { - jid = uri.getAuthority(); - } else { - jid = uri.getSchemeSpecificPart().split("\\?")[0]; - } - fingerprint = parseFingerprint(uri.getQuery()); - } else if ("imto".equalsIgnoreCase(scheme)) { - // sample: imto://xmpp/foo@bar.com - try { - jid = URLDecoder.decode(uri.getEncodedPath(), "UTF-8").split("/")[1]; - } catch (final UnsupportedEncodingException ignored) { - jid = null; - } - } else { - try { - jid = Jid.fromString(uri.toString()).toBareJid().toString(); - } catch (final InvalidJidException ignored) { - jid = null; - } - } - } - - protected String parseFingerprint(String query) { - if (query == null) { - return null; - } else { - final String NEEDLE = "otr-fingerprint="; - int index = query.indexOf(NEEDLE); - if (index >= 0 && query.length() >= (NEEDLE.length() + index + 40)) { - return query.substring(index + NEEDLE.length(), index + NEEDLE.length() + 40); - } else { - return null; - } - } - } - - public Jid getJid() { - try { - return this.jid == null ? null :Jid.fromString(this.jid.toLowerCase()); - } catch (InvalidJidException e) { - return null; - } - } - - public String getFingerprint() { - return this.fingerprint; - } -} |