package org.awesomeapp.messenger.util; import android.net.Uri; import android.text.TextUtils; import java.util.HashMap; import java.util.List; import java.util.Map; /** * Make it easy to build URIs that are compliant with RFC5122/XEP-0147 * * @author hans * */ public class XmppUriHelper { private static final String TAG = "XmppUriHelper"; public static final String SCHEME = "xmpp"; // http://xmpp.org/registrar/querytypes.html public static final String ACTION_COMMAND = "command"; public static final String ACTION_DISCO = "disco"; public static final String ACTION_INVITE = "invite"; public static final String ACTION_JOIN = "join"; public static final String ACTION_MESSAGE = "message"; public static final String ACTION_PUBSUB = "pubsub"; public static final String ACTION_RECVFILE = "recvfile"; public static final String ACTION_REGISTER = "register"; public static final String ACTION_REMOVE = "remove"; public static final String ACTION_ROSTER = "roster"; public static final String ACTION_SENDFILE = "sendfile"; public static final String ACTION_SUBSCRIBE = "subscribe"; public static final String ACTION_UNREGISTER = "unregister"; public static final String ACTION_UNSUBSCRIBE = "unsubscribe"; public static final String ACTION_VCARD = "vcard"; // public static final String OTR_QUERY_PARAM = "otr-fingerprint"; // public static final String KEY_ACTION = "action"; public static final String KEY_ADDRESS = "address"; public static final String KEY_RESOURCE = "resource"; public static final String KEY_FRAGMENT = "fragment"; public static final String KEY_OTR_FINGERPRINT = OTR_QUERY_PARAM; /** * This creates a format that aims to be as compatible and standards- * compliant as possible. * * @param address * @param otrFingerprint * @return a String representation of the {@link Uri} */ public static String getUri(String address, String otrFingerprint) { Uri.Builder builder = new Uri.Builder(); builder.scheme(SCHEME); String opaquePart = address + "?" + ACTION_SUBSCRIBE; if (!TextUtils.isEmpty(otrFingerprint)) opaquePart += ";" + OTR_QUERY_PARAM + "=" + otrFingerprint; builder.encodedOpaquePart(opaquePart); return builder.toString(); } public static String getOtrFingerprint(String uriString) { return getOtrFingerprint(Uri.parse(uriString)); } public static String getOtrFingerprint(Uri uri) { return parse(uri).get(KEY_OTR_FINGERPRINT); } public static final Map<String, String> parse(Uri uri) { Map<String, String> map = new HashMap<String, String>(); try { if (TextUtils.equals(uri.getScheme(), "im")) { if (uri.isHierarchical()) uri = Uri.parse(uri.toString().replaceAll("://*", ":")); String opaquePart = uri.getSchemeSpecificPart(); String query[] = opaquePart.split("[/\\?]"); map.put(KEY_ADDRESS, query[0]); String[] parameters = null; if (query.length > 1) { parameters = query[1].split("[;&]"); for (String t : parameters) { String[] parameter = t.split("="); if (parameter.length > 1) map.put(parameter[0], parameter[1]); else map.put(parameter[0], ""); } } } else if (TextUtils.equals(uri.getScheme(), "xmpp")) { if (uri.isOpaque()) { String opaquePart = uri.getSchemeSpecificPart(); if (!TextUtils.isEmpty(opaquePart)) { String f[] = opaquePart.split("#"); if (f.length > 1) map.put(KEY_FRAGMENT, f[1]); String s[] = f[0].split("\\?"); String a[] = s[0].split("/"); // split off XMPP Resource map.put(KEY_ADDRESS, a[0]); if (a.length > 1) map.put(KEY_RESOURCE, a[1]); String[] parameters = null; if (s.length > 1) { parameters = s[1].split("[;&]"); for (String t : parameters) { String[] parameter = t.split("="); if (parameter.length > 1) map.put(parameter[0], parameter[1]); else map.put(parameter[0], ""); } } } } else if (uri.isHierarchical()) { String authority = uri.getAuthority(); List<String> path = uri.getPathSegments(); if (TextUtils.isEmpty(authority) || path.size() > 0) { // totally ignore the "authority" part map.put(KEY_ADDRESS, path.get(0)); if (path.size() > 1) map.put(KEY_RESOURCE, path.get(1)); } else { /* this supports the original ChatSecure xmpp://to@address.com URLs. * Those URLs are technically incorrect according to RFC5122 since the * "authority" part directly after the // is meant to be the local * sending account, not the remote, receiving account. */ map.put(KEY_ADDRESS, authority); } map.put(KEY_OTR_FINGERPRINT, uri.getQueryParameter(XmppUriHelper.OTR_QUERY_PARAM)); } else { throw new Exception("Uri is neither opaque nor hierarchical!"); } } } catch (Exception e) { e.printStackTrace(); } return map; } }