/* * Util.java * * Created on November 20, 2007, 2:31 PM * * To change this template, choose Tools | Template Manager * and open the template in the editor. */ package net.oauth.j2me; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.IOException; import java.io.OutputStream; import java.util.Enumeration; import java.util.Hashtable; import java.util.Vector; import javax.microedition.io.Connector; import com.docomostar.io.ConnectionException; import com.docomostar.io.HttpConnection; /** * * @author Administrator */ public class Util { public Util() { } // if the same key occurs in h1 and h2, use the value from h1 public static final Hashtable hashtableMerge(Hashtable h1, Hashtable h2) { System.out.println("in hastableMerge"); Hashtable h = new Hashtable(); Enumeration keys = h1.keys(); while (keys.hasMoreElements()) { Object k = keys.nextElement(); if (h1.get(k) != null) { h.put(k, h1.get(k)); } } keys = h2.keys(); while (keys.hasMoreElements()) { Object k = keys.nextElement(); if (!h.containsKey(k) && h2.get(k) != null) { h.put(k, h2.get(k)); } } return h; } // sorts String values public static final Enumeration sort(Enumeration e) { Vector v = new Vector(); while (e.hasMoreElements()) { String s = (String) e.nextElement(); int i = 0; for (i = 0; i < v.size(); i++) { int c = s.compareTo((String) v.elementAt(i)); if (c < 0) { // s should go before i v.insertElementAt(s, i); break; } else if (c == 0) { // s already there break; } } if (i >= v.size()) { // add s at end v.addElement(s); } } return v.elements(); } /** * Split string into multiple strings * * @param original * Original string * @param separator * Separator string in original string * @return Splitted string array */ // TODO -- add in a max split param public static final String[] split(String original, String separator) { Vector nodes = new Vector(); // Parse nodes into vector int index = original.indexOf(separator); while (index >= 0) { nodes.addElement(original.substring(0, index)); original = original.substring(index + separator.length()); index = original.indexOf(separator); } // Get the last node nodes.addElement(original); // Create splitted string array String[] result = new String[nodes.size()]; if (nodes.size() > 0) { for (int loop = 0; loop < nodes.size(); loop++) result[loop] = (String) nodes.elementAt(loop); } return result; } // this is an OAuth-friendly url encode -- should work fine for ordniary // encoding also public static final String urlEncode(String s) { if (s == null) return s; StringBuffer sb = new StringBuffer(s.length() * 3); try { char c; for (int i = 0; i < s.length(); i++) { c = s.charAt(i); if (c == '&') { // sb.append("&"); // don't do this sb.append("%26"); // } else if (c == ' ') { // sb.append('+'); // maybe don't do this either } else if ( // safe characters c == '-' || c == '_' || c == '.' || c == '!' || c == '~' || c == '*' || c == '\'' || c == '(' || c == ')' || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) { sb.append(c); } else { sb.append('%'); if (c > 15) { // is it a non-control char, ie. >x0F so 2 // chars sb.append(Integer.toHexString((int) c).toUpperCase()); // just // add // % // and // the // string } else { sb.append("0" + Integer.toHexString((int) c).toUpperCase()); // otherwise need to add a leading 0 } } } } catch (Exception ex) { return (null); } return (sb.toString()); } public static final String postViaHttpsConnection(String fullUrl) throws IOException, OAuthServiceProviderException { String[] urlPieces = split(fullUrl, "?"); HttpConnection c = null; DataInputStream dis = null; OutputStream os = null; int rc; String respBody = new String(""); // return empty string on bad things // TODO -- better way to handle unexpected responses try { System.out.println("UTIL -- posting to " + urlPieces[0]); c = (HttpConnection) Connector.open(urlPieces[0], Connector.READ_WRITE); // hack for emulator? // Set the request method and headers c.setRequestMethod(HttpConnection.POST); c.setRequestProperty("User-Agent", "Profile/MIDP-2.0 Configuration/CLDC-1.0"); c.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); c.setRequestProperty("Content-Length", "" + urlPieces[1].length()); // TODO -- add'l headers for t-mobile? // Getting the output stream may flush the headers os = c.openOutputStream(); System.out.println("UTIL -- writing POST data: " + urlPieces[1]); os.write(urlPieces[1].getBytes()); os.flush(); // Optional, getResponseCode will flush // Getting the response code will open the connection, // send the request, and read the HTTP response headers. // The headers are stored until requested. rc = c.getResponseCode(); int len = (int) c.getLength(); System.out.println("content-length=" + len); dis = c.openDataInputStream(); byte[] data = new byte[len]; if (len == 0) { System.out .println("UTIL -- no length, reading individual characters..."); ByteArrayOutputStream tmp = new ByteArrayOutputStream(); int ch; while ((ch = dis.read()) != -1) { tmp.write(ch); } data = tmp.toByteArray(); } else { System.out.println("UTIL -- got a length, reading..."); dis.readFully(data); } respBody = new String(data); } catch (ClassCastException e) { throw new IllegalArgumentException("Not an HTTP URL"); } finally { if (dis != null) dis.close(); if (os != null) os.close(); if (c != null) c.close(); } if (rc != HttpConnection.HTTP_OK) { throw new OAuthServiceProviderException( "HTTP response code: " + rc, rc, respBody); } return respBody; } public static final String getViaHttpsConnection(String url) throws IOException, OAuthServiceProviderException { HttpConnection c = null; DataInputStream dis = null; OutputStream os = null; int rc = 0; String respBody = new String(""); // return empty string on bad things // TODO -- better way to handle unexpected responses try { System.out.println("UTIL -- opening connection"); c = (HttpConnection) Connector.open(url, Connector.READ); c.setRequestMethod(HttpConnection.GET); c.setRequestProperty("User-Agent", "Profile/MIDP-2.0 Configuration/CLDC-1.0"); c.setRequestProperty("Cache-Control", "no-store"); c.setRequestProperty("Connection", "close"); // not sure this is a good idea, but HTTP/1.0 might be less error-prone, // some clients have trouble with chunked responses System.out.println("UTIL -- connection open"); // Getting the response code will open the connection, // send the request, and read the HTTP response headers. // The headers are stored until requested. c.connect(); System.out.println("debug"); rc = c.getResponseCode(); System.out.println("UTIL -- got response code" + rc); // Get the length and process the data int len = (int) c.getLength(); System.out.println("content-length=" + len); dis = c.openDataInputStream(); byte[] data = null; if (len == -1L) { System.out.println("UTIL -- no length, reading individual characters..."); ByteArrayOutputStream tmp = new ByteArrayOutputStream(); int ch; while ((ch = dis.read()) != -1) { tmp.write(ch); } data = tmp.toByteArray(); } else { System.out.println("UTIL -- got a length, reading..."); data = new byte[len]; dis.read(data); } respBody = new String(data); } catch (ConnectionException e) { System.err.println(e.getStatus() + ", " + e.getMessage()); } catch (ClassCastException e) { throw new IllegalArgumentException("Not an HTTP URL"); } finally { if (dis != null) dis.close(); if (c != null) c.close(); } if (rc != HttpConnection.HTTP_OK) { throw new OAuthServiceProviderException( "HTTP response code: " + rc, rc, respBody); } return respBody; } private static char[] map1 = new char[64]; static { int i = 0; for (char c = 'A'; c <= 'Z'; c++) { map1[i++] = c; } for (char c = 'a'; c <= 'z'; c++) { map1[i++] = c; } for (char c = '0'; c <= '9'; c++) { map1[i++] = c; } map1[i++] = '+'; map1[i++] = '/'; } public static final String base64Encode(byte[] in) { int iLen = in.length; int oDataLen = (iLen * 4 + 2) / 3;// output length without padding int oLen = ((iLen + 2) / 3) * 4;// output length including padding char[] out = new char[oLen]; int ip = 0; int op = 0; int i0; int i1; int i2; int o0; int o1; int o2; int o3; while (ip < iLen) { i0 = in[ip++] & 0xff; i1 = ip < iLen ? in[ip++] & 0xff : 0; i2 = ip < iLen ? in[ip++] & 0xff : 0; o0 = i0 >>> 2; o1 = ((i0 & 3) << 4) | (i1 >>> 4); o2 = ((i1 & 0xf) << 2) | (i2 >>> 6); o3 = i2 & 0x3F; out[op++] = map1[o0]; out[op++] = map1[o1]; out[op] = op < oDataLen ? map1[o2] : '='; op++; out[op] = op < oDataLen ? map1[o3] : '='; op++; } return new String(out); } }