Java tutorial
/* * Copyright (C) 2010 Felix Bechstein * * This file is part of WebSMS. * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation; either version 3 of the License, or (at your option) any later * version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program; If not, see <http://www.gnu.org/licenses/>. */ package org.herrlado.engeo; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.net.URI; import java.net.URISyntaxException; import java.net.URLEncoder; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.List; import java.util.zip.GZIPInputStream; import org.apache.http.Header; import org.apache.http.HeaderElement; import org.apache.http.HttpEntity; import org.apache.http.HttpException; import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; import org.apache.http.HttpResponseInterceptor; import org.apache.http.HttpStatus; import org.apache.http.client.CookieStore; import org.apache.http.client.HttpClient; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpRequestBase; import org.apache.http.conn.scheme.PlainSocketFactory; import org.apache.http.conn.scheme.Scheme; import org.apache.http.conn.scheme.SchemeRegistry; import org.apache.http.cookie.Cookie; import org.apache.http.cookie.CookieOrigin; import org.apache.http.cookie.MalformedCookieException; import org.apache.http.entity.HttpEntityWrapper; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager; import org.apache.http.impl.cookie.BrowserCompatSpec; import org.apache.http.impl.cookie.CookieSpecBase; import org.apache.http.message.BasicNameValuePair; import org.apache.http.params.BasicHttpParams; import org.apache.http.params.HttpParams; import org.apache.http.protocol.HttpContext; import android.content.Context; import android.content.SharedPreferences; import android.preference.PreferenceManager; import android.util.Log; /** * General Utils calls. * * @author flx */ public final class Utils { /** Tag for output. */ private static final String TAG = "utl"; /** Standard buffer size. */ public static final int BUFSIZE = 32768; /** HTTP Response 200. */ @Deprecated public static final int HTTP_SERVICE_OK = HttpStatus.SC_OK; /** HTTP Response 401. */ @Deprecated public static final int HTTP_SERVICE_UNAUTHORIZED = // . HttpStatus.SC_UNAUTHORIZED; /** HTTP Response 500. */ @Deprecated public static final int HTTP_SERVICE_500 = // . HttpStatus.SC_INTERNAL_SERVER_ERROR; /** HTTP Response 503. */ @Deprecated public static final int HTTP_SERVICE_UNAVAILABLE = // . HttpStatus.SC_SERVICE_UNAVAILABLE; /** Gzip. */ private static final String GZIP = "gzip"; /** Accept-Encoding. */ private static final String ACCEPT_ENCODING = "Accept-Encoding"; /** Default port for HTTP. */ private static final int PORT_HTTP = 80; /** Default port for HTTPS. */ private static final int PORT_HTTPS = 443; /** Preference's name: use default sender. */ public static final String PREFS_USE_DEFAULT_SENDER = "use_default_sender"; /** Preference's name: custom sender. */ public static final String PREFS_CUSTOM_SENDER = "custom_sender"; /** Resturn only matching line in stream2str(). */ public static final int ONLY_MATCHING_LINE = -2; /** Common {@link HttpClient}. */ private static DefaultHttpClient httpClient = null; /** * {@link HttpEntityWrapper} to wrap giziped content. * * @author flx */ public static final class GzipDecompressingEntity // . extends HttpEntityWrapper { /** * Default Constructor. * * @param entity * {@link HttpEntity} */ public GzipDecompressingEntity(final HttpEntity entity) { super(entity); } /** * {@inheritDoc} */ @Override public InputStream getContent() throws IOException { Log.d(TAG, "unzip content"); InputStream wrappedin = this.wrappedEntity.getContent(); return new GZIPInputStream(wrappedin); } /** * {@inheritDoc} */ @Override public long getContentLength() { return -1; } } /** * No Constructor needed here. */ private Utils() { return; } /** * Get custom sender from preferences by users choice. Else: default sender * is selected. * * @param context * {@link Context} * @param defSender * default Sender * @return selected Sender */ public static String getSender(final Context context, // . final String defSender) { if (context == null) { return defSender; } final SharedPreferences p = PreferenceManager.getDefaultSharedPreferences(context); if (p.getBoolean(PREFS_USE_DEFAULT_SENDER, true)) { return defSender; } final String s = p.getString(PREFS_CUSTOM_SENDER, ""); if (s == null || s.length() == 0) { return defSender; } return s; } /** * Get custom sender number from preferences by users choice. Else: default * sender is selected. * * @param context * {@link Context} * @param defSender * default Sender * @return selected Sender */ public static String getSenderNumber(final Context context, // . final String defSender) { if (context == null) { return defSender; } final SharedPreferences p = PreferenceManager.getDefaultSharedPreferences(context); if (p.getBoolean(PREFS_USE_DEFAULT_SENDER, true)) { return defSender; } final String s = p.getString(PREFS_CUSTOM_SENDER, ""); if (s == null || s.length() == 0) { return defSender; } final String sn = s.replaceAll("(\\+|[0-9])", ""); if (sn.length() > 0) { Log.d(TAG, "fall back to default numer: " + sn); return defSender; } return s; } /** * Parse a String of "name <number>, name <number>, number, ..." to an array * of "name <number>". * * @param recipients * recipients * @return array of recipients */ public static String[] parseRecipients(final String recipients) { String s = recipients.trim(); if (s.endsWith(",")) { s = s.substring(0, s.length() - 1); } ArrayList<String> ret = new ArrayList<String>(); String[] ss = s.split(","); final int l = ss.length; String r = null; String rr; for (int i = 0; i < l; i++) { rr = ss[i]; if (r == null) { r = rr; } else { r += "," + rr; } if (rr.contains("0") || rr.contains("1") || rr.contains("2") || rr.contains("3") || rr.contains("4") || rr.contains("5") || rr.contains("6") || rr.contains("7") || rr.contains("8") || rr.contains("9")) { r = r.trim(); final String na = getRecipientsName(r); final String nu = cleanRecipient(getRecipientsNumber(r)); if (na != null && na.trim().length() > 0) { r = na + " <" + nu + ">"; } else { r = nu; } ret.add(r); r = null; } } return ret.toArray(new String[0]); } /** * Join an array of recipients separated with separator. * * @param recipients * recipients * @param separator * separator * @return joined recipients */ public static String joinRecipients(final String[] recipients, final String separator) { if (recipients == null) { return null; } final int e = recipients.length; if (e == 0) { return null; } final StringBuilder buf = new StringBuilder(recipients[0]); for (int i = 1; i < e; i++) { buf.append(separator); buf.append(recipients[i]); } return buf.toString(); } /** * Join an array of recipients separated with separator, stripped to only * contain numbers. * * @param recipients * recipients * @param separator * separator * @param oldFormat * Use old international format. E.g. 0049, not +49. * @return joined recipients */ public static String joinRecipientsNumbers(final String[] recipients, final String separator, final boolean oldFormat) { if (recipients == null) { return null; } final int e = recipients.length; if (e == 0) { return null; } final StringBuilder buf = new StringBuilder(); if (oldFormat) { buf.append(international2oldformat(// . getRecipientsNumber(recipients[0]))); } else { buf.append(getRecipientsNumber(recipients[0])); } for (int i = 1; i < e; i++) { buf.append(separator); if (oldFormat) { buf.append(international2oldformat(// . getRecipientsNumber(recipients[i]))); } else { buf.append(getRecipientsNumber(recipients[i])); } } return buf.toString(); } /** * Get a recipient's number. * * @param recipient * recipient * @return recipient's number */ public static String getRecipientsNumber(final String recipient) { final int i = recipient.lastIndexOf('<'); if (i >= 0) { final int j = recipient.indexOf('>', i); if (j > 0) { return recipient.substring(i + 1, j); } } return recipient; } /** * Get a recipient's name. * * @param recipient * recipient * @return recipient's name */ public static String getRecipientsName(final String recipient) { final int i = recipient.lastIndexOf('<'); if (i > 0) { return recipient.substring(0, i - 1).trim(); } return recipient; } /** * Clean recipient's phone number from [ -.()<>]. * * @param recipient * recipient's mobile number * @return clean number */ public static String cleanRecipient(final String recipient) { if (recipient == null) { return ""; } return recipient.replaceAll("[^*#+0-9]", "") // . .replaceAll("^[*#][0-9]*#", ""); } /** * Convert international number to national. * * @param defPrefix * default prefix * @param number * international number * @return national number */ public static String international2national(final String defPrefix, final String number) { if (number.startsWith(defPrefix)) { return '0' + number.substring(defPrefix.length()); } else if (number.startsWith("00" + defPrefix.substring(1))) { return '0' + number.substring(defPrefix.length() + 1); } return number; } /** * Convert national number to international. Old format internationals were * converted to new format. * * @param defPrefix * default prefix * @param number * national number * @return international number */ public static String national2international(final String defPrefix, final String number) { if (number.startsWith("+")) { return number; } else if (number.startsWith("00")) { return "+" + number.substring(2); } else if (number.startsWith("0")) { return defPrefix + number.substring(1); } return defPrefix + number; } /** * Convert national number to international. * * @param defPrefix * default prefix * @param number * national numbers * @return international numbers */ public static String[] national2international(final String defPrefix, final String[] number) { final int l = number.length; String[] n = new String[l]; for (int i = 0; i < l; i++) { n[i] = national2international(defPrefix, getRecipientsNumber(number[i])); } return n; } /** * Convert international number to old format. Eg. +49123 to 0049123 * * @param number * international number starting with + * @return international number in old format starting with 00 */ public static String international2oldformat(final String number) { if (number.startsWith("+")) { return "00" + number.substring(1); } return number; } /** * Get a fresh HTTP-Connection. Please use getHttpClient(url, cookies, * postData, userAgent, referer, false). * * @param url * URL to open * @param cookies * cookies to transmit * @param postData * post data * @param userAgent * user agent * @param referer * referer * @return the connection * @throws IOException * IOException */ @Deprecated public static HttpResponse getHttpClient(final String url, final ArrayList<Cookie> cookies, final ArrayList<BasicNameValuePair> postData, final String userAgent, final String referer) throws IOException { return getHttpClient(url, cookies, postData, userAgent, referer, false); } /** * Print all cookies from {@link CookieStore} to {@link String}. * * @param client * {@link DefaultHttpClient} * @return {@link Cookie}s formated for debug out */ private static String getCookies(final DefaultHttpClient client) { String ret = "cookies:"; for (Cookie cookie : httpClient.getCookieStore().getCookies()) { ret += "\n" + cookie.getName() + ": " + cookie.getValue(); } ret += "\nend of cookies"; return ret; } /** * Print all {@link Header}s from {@link HttpRequest} to {@link String}. * * @param request * {@link HttpRequest} * @return {@link Header}s formated for debug out */ private static String getHeaders(final HttpRequest request) { String ret = "headers:"; for (Header h : request.getAllHeaders()) { ret += "\n" + h.getName() + ": " + h.getValue(); } ret += "\nend of headers"; return ret; } /** * Get {@link Cookie}s stored in static {@link CookieStore}. * * @return {@link ArrayList} of {@link Cookie}s */ public static ArrayList<Cookie> getCookies() { if (httpClient == null) { return null; } List<Cookie> cookies = httpClient.getCookieStore().getCookies(); if (cookies == null || cookies.size() == 0) { return null; } ArrayList<Cookie> ret = new ArrayList<Cookie>(cookies.size()); ret.addAll(cookies); return ret; } /** * Get the number of {@link Cookie}s stored in static {@link CookieStore}. * * @return number of {@link Cookie}s */ public static int getCookieCount() { if (httpClient == null) { return 0; } List<Cookie> cookies = httpClient.getCookieStore().getCookies(); if (cookies == null) { return 0; } return cookies.size(); } /** * Get cookies as {@link String}. * * @return cookies */ public static String getCookiesAsString() { if (httpClient == null) { return null; } return getCookies(httpClient); } /** * Clear internal cookie cache. */ public static void clearCookies() { if (httpClient != null) { final CookieStore cs = httpClient.getCookieStore(); if (cs != null) { cs.clear(); } } } /** * Get a fresh HTTP-Connection. * * @param url * URL to open * @param cookies * cookies to transmit * @param postData * post data * @param userAgent * user agent * @param referer * referer * @param trustAll * trust all SSL certificates; only used on first call! * @return the connection * @throws IOException * IOException */ @Deprecated public static HttpResponse getHttpClient(final String url, final ArrayList<Cookie> cookies, final ArrayList<BasicNameValuePair> postData, final String userAgent, final String referer, // . final boolean trustAll) throws IOException { return getHttpClient(url, cookies, postData, userAgent, referer, null, trustAll, (String[]) null); } /** * Get a fresh HTTP-Connection. * * @param url * URL to open * @param cookies * cookies to transmit * @param postData * post data * @param userAgent * user agent * @param referer * referer * @param encoding * encoding; default encoding: ISO-8859-15 * @param trustAll * trust all SSL certificates; only used on first call! * @return the connection * @throws IOException * IOException */ public static HttpResponse getHttpClient(final String url, final ArrayList<Cookie> cookies, final ArrayList<BasicNameValuePair> postData, final String userAgent, final String referer, final String encoding, final boolean trustAll) throws IOException { return getHttpClient(url, cookies, postData, userAgent, referer, encoding, trustAll, (String[]) null); } /** * Get a fresh HTTP-Connection. * * @param url * URL to open * @param cookies * cookies to transmit * @param postData * post data * @param userAgent * user agent * @param referer * referer * @param knownFingerprints * fingerprints that are known to be valid; only used on first * call! * @return the connection * @throws IOException * IOException */ @Deprecated public static HttpResponse getHttpClient(final String url, final ArrayList<Cookie> cookies, final ArrayList<BasicNameValuePair> postData, final String userAgent, final String referer, // . final String... knownFingerprints) throws IOException { return getHttpClient(url, cookies, postData, userAgent, referer, null, false, knownFingerprints); } /** * Get a fresh HTTP-Connection. * * @param url * URL to open * @param cookies * cookies to transmit * @param postData * post data * @param userAgent * user agent * @param referer * referer * @param encoding * encoding; default encoding: ISO-8859-15 * @param knownFingerprints * fingerprints that are known to be valid; only used on first * call! * @return the connection * @throws IOException * IOException */ public static HttpResponse getHttpClient(final String url, final ArrayList<Cookie> cookies, final ArrayList<BasicNameValuePair> postData, final String userAgent, final String referer, final String encoding, final String... knownFingerprints) throws IOException { return getHttpClient(url, cookies, postData, userAgent, referer, encoding, false, knownFingerprints); } /** * Get a fresh HTTP-Connection. * * @param url * URL to open * @param cookies * cookies to transmit * @param postData * post data * @param userAgent * user agent * @param referer * referer * @param encoding * encoding; default encoding: ISO-8859-15 * @param trustAll * trust all SSL certificates; only used on first call! * @param knownFingerprints * fingerprints that are known to be valid; only used on first * call! Only used if {@code trustAll == false} * @return the connection * @throws IOException * IOException */ private static HttpResponse getHttpClient(final String url, final ArrayList<Cookie> cookies, final ArrayList<BasicNameValuePair> postData, final String userAgent, final String referer, final String encoding, final boolean trustAll, final String... knownFingerprints) throws IOException { Log.d(TAG, "HTTPClient URL: " + url); SchemeRegistry registry = null; if (httpClient == null) { if (trustAll || (// . knownFingerprints != null && // . knownFingerprints.length > 0)) { registry = new SchemeRegistry(); registry.register(new Scheme("http", new PlainSocketFactory(), PORT_HTTP)); // final FakeSocketFactory httpsSocketFactory; // if (trustAll) { // httpsSocketFactory = new FakeSocketFactory(); // } else { // httpsSocketFactory = new FakeSocketFactory( // knownFingerprints); // } // registry.register(new Scheme("https", httpsSocketFactory, // PORT_HTTPS)); HttpParams params = new BasicHttpParams(); httpClient = new DefaultHttpClient(new ThreadSafeClientConnManager(params, registry), params); } else { httpClient = new DefaultHttpClient(); } httpClient.addResponseInterceptor(new HttpResponseInterceptor() { @Override public void process(final HttpResponse response, final HttpContext context) throws HttpException, IOException { HttpEntity entity = response.getEntity(); Header contentEncodingHeader = entity.getContentEncoding(); if (contentEncodingHeader != null) { HeaderElement[] codecs = contentEncodingHeader.getElements(); for (int i = 0; i < codecs.length; i++) { if (codecs[i].getName().equalsIgnoreCase(GZIP)) { response.setEntity(new GzipDecompressingEntity(response.getEntity())); return; } } } } }); } if (cookies != null && cookies.size() > 0) { final int l = cookies.size(); CookieStore cs = httpClient.getCookieStore(); for (int i = 0; i < l; i++) { cs.addCookie(cookies.get(i)); } } Log.d(TAG, getCookies(httpClient)); HttpRequestBase request; if (postData == null) { request = new HttpGet(url); } else { HttpPost pr = new HttpPost(url); if (encoding != null && encoding.length() > 0) { pr.setEntity(new UrlEncodedFormEntity(postData, encoding)); } else { pr.setEntity(new UrlEncodedFormEntity(postData, "ISO-8859-15")); } // Log.d(TAG, "HTTPClient POST: " + postData); request = pr; } request.addHeader(ACCEPT_ENCODING, GZIP); if (referer != null) { request.setHeader("Referer", referer); // Log.d(TAG, "HTTPClient REF: " + referer); } if (userAgent != null) { request.setHeader("User-Agent", userAgent); // Log.d(TAG, "HTTPClient AGENT: " + userAgent); } // Log.d(TAG, getHeaders(request)); return httpClient.execute(request); } /** * Update cookies from response. * * @param cookies * old {@link Cookie} list * @param headers * {@link Header}s from {@link HttpResponse} * @param url * requested URL * @throws URISyntaxException * malformed URI * @throws MalformedCookieException * malformed {@link Cookie} */ @Deprecated public static void updateCookies(final ArrayList<Cookie> cookies, final Header[] headers, final String url) throws URISyntaxException, MalformedCookieException { final URI uri = new URI(url); int port = uri.getPort(); if (port < 0) { if (url.startsWith("https")) { port = PORT_HTTPS; } else { port = PORT_HTTP; } } final CookieOrigin origin = new CookieOrigin(uri.getHost(), port, uri.getPath(), false); final CookieSpecBase cookieSpecBase = new BrowserCompatSpec(); String name; String value; for (final Header header : headers) { for (final Cookie cookie : cookieSpecBase.parse(header, origin)) { // THE cookie name = cookie.getName(); value = cookie.getValue(); if (value == null || value.equals("")) { continue; } for (final Cookie c : cookies) { if (name.equals(c.getName())) { cookies.remove(c); cookies.add(cookie); name = null; break; } } if (name != null) { cookies.add(cookie); } } } } /** * Read {@link InputStream} and convert it into {@link String}. * * @param is * {@link InputStream} to read from * @return {@link String} holding all the bytes from the {@link InputStream} * @throws IOException * IOException */ public static String stream2str(final InputStream is) throws IOException { return stream2str(is, 0, -1, null); } /** * Read {@link InputStream} and convert it into {@link String}. * * @param is * {@link InputStream} to read from param charset to read the * {@link InputStream}. Can be null. * @param charset * charset to be used to read {@link InputStream}. Can be null. * @return {@link String} holding all the bytes from the {@link InputStream} * @throws IOException * IOException */ public static String stream2str(final InputStream is, final String charset) throws IOException { return stream2str(is, 0, -1, null); } /** * Read {@link InputStream} and convert it into {@link String}. * * @param is * {@link InputStream} to read from * @param start * first characters of stream that should be fetched. Set to 0, * if nothing should be skipped. * @param end * last characters of stream that should be fetched. This method * might read some more characters. Set to -1 if all characters * should be read. * @return {@link String} holding all the bytes from the {@link InputStream} * @throws IOException * IOException */ public static String stream2str(final InputStream is, final int start, final int end) throws IOException { return stream2str(is, null, start, end); } /** * Read {@link InputStream} and convert it into {@link String}. * * @param is * {@link InputStream} to read from param charset to read the * {@link InputStream}. Can be null. * @param charset * charset to be used to read {@link InputStream}. Can be null. * @param start * first characters of stream that should be fetched. Set to 0, * if nothing should be skipped. * @param end * last characters of stream that should be fetched. This method * might read some more characters. Set to -1 if all characters * should be read. * @return {@link String} holding all the bytes from the {@link InputStream} * @throws IOException * IOException */ public static String stream2str(final InputStream is, final String charset, final int start, final int end) throws IOException { return stream2str(is, charset, start, end, null); } /** * Read {@link InputStream} and convert it into {@link String}. * * @param is * {@link InputStream} to read from * @param start * first characters of stream that should be fetched. Set to 0, * if nothing should be skipped. * @param end * last characters of stream that should be fetched. This method * might read some more characters. Set to -1 if all characters * should be read. * @param pattern * start reading at this pattern, set end = -2 to return only the * line, matching this pattern * @return {@link String} holding all the bytes from the {@link InputStream} * @throws IOException * IOException */ public static String stream2str(final InputStream is, final int start, final int end, final String pattern) throws IOException { return stream2str(is, null, start, end, pattern); } /** * Read {@link InputStream} and convert it into {@link String}. * * @param is * {@link InputStream} to read from * @param charset * charset to be used to read {@link InputStream}. Can be null. * @param start * first characters of stream that should be fetched. Set to 0, * if nothing should be skipped. * @param end * last characters of stream that should be fetched. This method * might read some more characters. Set to -1 if all characters * should be read. * @param pattern * start reading at this pattern, set end = -2 to return only the * line, matching this pattern * @return {@link String} holding all the bytes from the {@link InputStream} * @throws IOException * IOException */ public static String stream2str(final InputStream is, final String charset, final int start, final int end, final String pattern) throws IOException { boolean foundPattern = false; if (pattern == null) { foundPattern = true; } InputStreamReader r; if (charset == null) { r = new InputStreamReader(is); } else { r = new InputStreamReader(is, charset); } final BufferedReader bufferedReader = new BufferedReader(r, BUFSIZE); final StringBuilder data = new StringBuilder(); String line = null; long totalSkipped = 0; long skipped = 0; while (start > totalSkipped) { skipped = bufferedReader.skip(start - totalSkipped); if (skipped == 0) { break; } totalSkipped += skipped; } skipped = 0; while ((line = bufferedReader.readLine()) != null) { skipped += line.length() + 1; if (!foundPattern) { if (line.indexOf(pattern) >= 0) { if (end == ONLY_MATCHING_LINE) { return line; } foundPattern = true; Log.d(TAG, "skipped: " + skipped); } } if (foundPattern) { data.append(line + "\n"); } if (end >= 0 && skipped > (end - start)) { break; } } bufferedReader.close(); if (!foundPattern) { return null; } return data.toString(); } public static boolean isGeo(String w) { int c = w.charAt(0); return c > 4304 && c < 4337; } public static String urlEncode(String str, String enc) { try { return URLEncoder.encode(String.valueOf(str), enc); } catch (UnsupportedEncodingException ex) { throw new RuntimeException(ex); } } /** * Generate MD5 Hash from String. * * @param s * input * @return hash */ public static String md5(final String s) { try { // Create MD5 Hash final MessageDigest digest = java.security.MessageDigest.getInstance("MD5"); digest.update(s.getBytes()); final byte[] messageDigest = digest.digest(); // Create Hex String final StringBuilder hexString = new StringBuilder(32); int b; for (int i = 0; i < messageDigest.length; i++) { b = 0xFF & messageDigest[i]; if (b < 0x10) { hexString.append('0' + Integer.toHexString(b)); } else { hexString.append(Integer.toHexString(b)); } } return hexString.toString(); } catch (final NoSuchAlgorithmException e) { Log.e(TAG, null, e); } return ""; } }