/* * 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 javax.microedition.io.HttpConnection; import javax.microedition.io.HttpsConnection; /** * * @author Administrator */ public class Util { /** Creates a new instance of 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, "?"); HttpsConnection 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 = (HttpsConnection)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 = c.getHeaderFieldInt("Content-Length", 0); //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 { HttpsConnection 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 -- opening connection"); c= (HttpsConnection) 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. rc = c.getResponseCode(); System.out.println("UTIL -- got response code" + rc); // Get the length and process the data int len = c.getHeaderFieldInt("Content-Length", 0); 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 (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 ); } }