diff --git a/src/org/torproject/android/service/NanoHTTPD.java b/src/org/torproject/android/service/NanoHTTPD.java deleted file mode 100644 index 59a4bf70..00000000 --- a/src/org/torproject/android/service/NanoHTTPD.java +++ /dev/null @@ -1,733 +0,0 @@ -package org.torproject.android.service; - -import java.io.*; -import java.util.*; -import java.net.*; - -/** - * A simple, tiny, nicely embeddable HTTP 1.0 server in Java - * - *

NanoHTTPD version 1.12, - * Copyright © 2001,2005-2010 Jarno Elonen (elonen@iki.fi, http://iki.fi/elonen/) - * - *

Features + limitations:

- * - *

Ways to use:

- * - * See the end of the source file for distribution license - * (Modified BSD licence) - */ -public class NanoHTTPD -{ - // ================================================== - // API parts - // ================================================== - - private boolean keepRunning = true; - private Thread t = null; - - public void stop () - { - keepRunning = false; - t.interrupt(); - } - - /** - * Override this to customize the server.

- * - * (By default, this delegates to serveFile() and allows directory listing.) - * - * @parm uri Percent-decoded URI without parameters, for example "/index.cgi" - * @parm method "GET", "POST" etc. - * @parm parms Parsed, percent decoded parameters from URI and, in case of POST, data. - * @parm header Header entries, percent decoded - * @return HTTP response, see class Response for details - */ - public Response serve( String uri, String method, Properties header, Properties parms ) - { - System.out.println( method + " '" + uri + "' " ); - - Enumeration e = header.propertyNames(); - while ( e.hasMoreElements()) - { - String value = (String)e.nextElement(); - System.out.println( " HDR: '" + value + "' = '" + - header.getProperty( value ) + "'" ); - } - e = parms.propertyNames(); - while ( e.hasMoreElements()) - { - String value = (String)e.nextElement(); - System.out.println( " PRM: '" + value + "' = '" + - parms.getProperty( value ) + "'" ); - } - - return serveFile( uri, header, new File("."), true ); - } - - /** - * HTTP response. - * Return one of these from serve(). - */ - public class Response - { - /** - * Default constructor: response = HTTP_OK, data = mime = 'null' - */ - public Response() - { - this.status = HTTP_OK; - } - - /** - * Basic constructor. - */ - public Response( String status, String mimeType, InputStream data ) - { - this.status = status; - this.mimeType = mimeType; - this.data = data; - } - - /** - * Convenience method that makes an InputStream out of - * given text. - */ - public Response( String status, String mimeType, String txt ) - { - this.status = status; - this.mimeType = mimeType; - this.data = new ByteArrayInputStream( txt.getBytes()); - } - - /** - * Adds given line to the header. - */ - public void addHeader( String name, String value ) - { - header.put( name, value ); - } - - /** - * HTTP status code after processing, e.g. "200 OK", HTTP_OK - */ - public String status; - - /** - * MIME type of content, e.g. "text/html" - */ - public String mimeType; - - /** - * Data of the response, may be null. - */ - public InputStream data; - - /** - * Headers for the HTTP response. Use addHeader() - * to add lines. - */ - public Properties header = new Properties(); - } - - /** - * Some HTTP response status codes - */ - public static final String - HTTP_OK = "200 OK", - HTTP_REDIRECT = "301 Moved Permanently", - HTTP_FORBIDDEN = "403 Forbidden", - HTTP_NOTFOUND = "404 Not Found", - HTTP_BADREQUEST = "400 Bad Request", - HTTP_INTERNALERROR = "500 Internal Server Error", - HTTP_NOTIMPLEMENTED = "501 Not Implemented"; - - /** - * Common mime types for dynamic content - */ - public static final String - MIME_PLAINTEXT = "text/plain", - MIME_HTML = "text/html", - MIME_DEFAULT_BINARY = "application/octet-stream"; - - // ================================================== - // Socket & server code - // ================================================== - - /** - * Starts a HTTP server to given port.

- * Throws an IOException if the socket is already in use - */ - public NanoHTTPD( int port ) throws IOException - { - myTcpPort = port; - - final ServerSocket ss = new ServerSocket( myTcpPort ); - t = new Thread( new Runnable() - { - public void run() - { - try - { - while( keepRunning ) - new HTTPSession( ss.accept()); - } - catch ( IOException ioe ) - {} - } - }); - t.setDaemon( true ); - t.start(); - } - - /** - * Starts as a standalone file server and waits for Enter. - */ - public static void main( String[] args ) - { - System.out.println( "NanoHTTPD 1.12 (C) 2001,2005-2010 Jarno Elonen\n" + - "(Command line options: [port] [--licence])\n" ); - - // Show licence if requested - int lopt = -1; - for ( int i=0; i 0 && lopt != 0 ) - port = Integer.parseInt( args[0] ); - - if ( args.length > 1 && - args[1].toLowerCase().endsWith( "licence" )) - System.out.println( LICENCE + "\n" ); - - NanoHTTPD nh = null; - try - { - nh = new NanoHTTPD( port ); - } - catch( IOException ioe ) - { - System.err.println( "Couldn't start server:\n" + ioe ); - System.exit( -1 ); - } - nh.myFileDir = new File(""); - - System.out.println( "Now serving files in port " + port + " from \"" + - new File("").getAbsolutePath() + "\"" ); - System.out.println( "Hit Enter to stop.\n" ); - - try { System.in.read(); } catch( Throwable t ) {}; - } - - /** - * Handles one session, i.e. parses the HTTP request - * and returns the response. - */ - private class HTTPSession implements Runnable - { - public HTTPSession( Socket s ) - { - mySocket = s; - Thread t = new Thread( this ); - t.setDaemon( true ); - t.start(); - } - - public void run() - { - try - { - InputStream is = mySocket.getInputStream(); - if ( is == null) return; - BufferedReader in = new BufferedReader( new InputStreamReader( is )); - - // Read the request line - String inLine = in.readLine(); - if (inLine == null) return; - StringTokenizer st = new StringTokenizer( inLine ); - if ( !st.hasMoreTokens()) - sendError( HTTP_BADREQUEST, "BAD REQUEST: Syntax error. Usage: GET /example/file.html" ); - - String method = st.nextToken(); - - if ( !st.hasMoreTokens()) - sendError( HTTP_BADREQUEST, "BAD REQUEST: Missing URI. Usage: GET /example/file.html" ); - - String uri = st.nextToken(); - - // Decode parameters from the URI - Properties parms = new Properties(); - int qmi = uri.indexOf( '?' ); - if ( qmi >= 0 ) - { - decodeParms( uri.substring( qmi+1 ), parms ); - uri = decodePercent( uri.substring( 0, qmi )); - } - else uri = decodePercent(uri); - - - // If there's another token, it's protocol version, - // followed by HTTP headers. Ignore version but parse headers. - // NOTE: this now forces header names uppercase since they are - // case insensitive and vary by client. - Properties header = new Properties(); - if ( st.hasMoreTokens()) - { - String line = in.readLine(); - while ( line.trim().length() > 0 ) - { - int p = line.indexOf( ':' ); - header.put( line.substring(0,p).trim().toLowerCase(), line.substring(p+1).trim()); - line = in.readLine(); - } - } - - // If the method is POST, there may be parameters - // in data section, too, read it: - if ( method.equalsIgnoreCase( "POST" )) - { - long size = 0x7FFFFFFFFFFFFFFFl; - String contentLength = header.getProperty("content-length"); - if (contentLength != null) - { - try { size = Integer.parseInt(contentLength); } - catch (NumberFormatException ex) {} - } - String postLine = ""; - char buf[] = new char[512]; - int read = in.read(buf); - while ( read >= 0 && size > 0 && !postLine.endsWith("\r\n") ) - { - size -= read; - postLine += String.valueOf(buf, 0, read); - if ( size > 0 ) - read = in.read(buf); - } - postLine = postLine.trim(); - decodeParms( postLine, parms ); - } - - // Ok, now do the serve() - Response r = serve( uri, method, header, parms ); - if ( r == null ) - sendError( HTTP_INTERNALERROR, "SERVER INTERNAL ERROR: Serve() returned a null response." ); - else - sendResponse( r.status, r.mimeType, r.header, r.data ); - - in.close(); - } - catch ( IOException ioe ) - { - try - { - sendError( HTTP_INTERNALERROR, "SERVER INTERNAL ERROR: IOException: " + ioe.getMessage()); - } - catch ( Throwable t ) {} - } - catch ( InterruptedException ie ) - { - // Thrown by sendError, ignore and exit the thread. - } - } - - /** - * Decodes the percent encoding scheme.
- * For example: "an+example%20string" -> "an example string" - */ - private String decodePercent( String str ) throws InterruptedException - { - try - { - StringBuffer sb = new StringBuffer(); - for( int i=0; i= 0 ) - uri = uri.substring(0, uri.indexOf( '?' )); - - // Prohibit getting out of current directory - if ( uri.startsWith( ".." ) || uri.endsWith( ".." ) || uri.indexOf( "../" ) >= 0 ) - return new Response( HTTP_FORBIDDEN, MIME_PLAINTEXT, - "FORBIDDEN: Won't serve ../ for security reasons." ); - - File f = new File( homeDir, uri ); - if ( !f.exists()) - return new Response( HTTP_NOTFOUND, MIME_PLAINTEXT, - "Error 404, file not found." ); - - // List the directory, if necessary - if ( f.isDirectory()) - { - // Browsers get confused without '/' after the - // directory, send a redirect. - if ( !uri.endsWith( "/" )) - { - uri += "/"; - Response r = new Response( HTTP_REDIRECT, MIME_HTML, - "Redirected: " + - uri + ""); - r.addHeader( "Location", uri ); - return r; - } - - // First try index.html and index.htm - if ( new File( f, "index.html" ).exists()) - f = new File( homeDir, uri + "/index.html" ); - else if ( new File( f, "index.htm" ).exists()) - f = new File( homeDir, uri + "/index.htm" ); - - // No index file, list the directory - else if ( allowDirectoryListing ) - { - String[] files = f.list(); - String msg = "

Directory " + uri + "


"; - - if ( uri.length() > 1 ) - { - String u = uri.substring( 0, uri.length()-1 ); - int slash = u.lastIndexOf( '/' ); - if ( slash >= 0 && slash < u.length()) - msg += "..
"; - } - - for ( int i=0; i" + - files[i] + ""; - - // Show file size - if ( curFile.isFile()) - { - long len = curFile.length(); - msg += "  ("; - if ( len < 1024 ) - msg += curFile.length() + " bytes"; - else if ( len < 1024 * 1024 ) - msg += curFile.length()/1024 + "." + (curFile.length()%1024/10%100) + " KB"; - else - msg += curFile.length()/(1024*1024) + "." + curFile.length()%(1024*1024)/10%100 + " MB"; - - msg += ")"; - } - msg += "
"; - if ( dir ) msg += ""; - } - return new Response( HTTP_OK, MIME_HTML, msg ); - } - else - { - return new Response( HTTP_FORBIDDEN, MIME_PLAINTEXT, - "FORBIDDEN: No directory listing." ); - } - } - - try - { - // Get MIME type from file name extension, if possible - String mime = null; - int dot = f.getCanonicalPath().lastIndexOf( '.' ); - if ( dot >= 0 ) - mime = (String)theMimeTypes.get( f.getCanonicalPath().substring( dot + 1 ).toLowerCase()); - if ( mime == null ) - mime = MIME_DEFAULT_BINARY; - - // Support (simple) skipping: - long startFrom = 0; - String range = header.getProperty( "Range" ); - if ( range != null ) - { - if ( range.startsWith( "bytes=" )) - { - range = range.substring( "bytes=".length()); - int minus = range.indexOf( '-' ); - if ( minus > 0 ) - range = range.substring( 0, minus ); - try { - startFrom = Long.parseLong( range ); - } - catch ( NumberFormatException nfe ) {} - } - } - - FileInputStream fis = new FileInputStream( f ); - fis.skip( startFrom ); - Response r = new Response( HTTP_OK, mime, fis ); - r.addHeader( "Content-length", "" + (f.length() - startFrom)); - r.addHeader( "Content-range", "" + startFrom + "-" + - (f.length()-1) + "/" + f.length()); - return r; - } - catch( IOException ioe ) - { - return new Response( HTTP_FORBIDDEN, MIME_PLAINTEXT, "FORBIDDEN: Reading file failed." ); - } - } - - /** - * Hashtable mapping (String)FILENAME_EXTENSION -> (String)MIME_TYPE - */ - private static Hashtable theMimeTypes = new Hashtable(); - static - { - StringTokenizer st = new StringTokenizer( - "htm text/html "+ - "html text/html "+ - "txt text/plain "+ - "asc text/plain "+ - "gif image/gif "+ - "jpg image/jpeg "+ - "jpeg image/jpeg "+ - "png image/png "+ - "mp3 audio/mpeg "+ - "m3u audio/mpeg-url " + - "pdf application/pdf "+ - "doc application/msword "+ - "ogg application/x-ogg "+ - "zip application/octet-stream "+ - "exe application/octet-stream "+ - "class application/octet-stream " ); - while ( st.hasMoreTokens()) - theMimeTypes.put( st.nextToken(), st.nextToken()); - } - - /** - * GMT date formatter - */ - private static java.text.SimpleDateFormat gmtFrmt; - static - { - gmtFrmt = new java.text.SimpleDateFormat( "E, d MMM yyyy HH:mm:ss 'GMT'", Locale.US); - gmtFrmt.setTimeZone(TimeZone.getTimeZone("GMT")); - } - - /** - * The distribution licence - */ - private static final String LICENCE = - "Copyright (C) 2001,2005-2008 by Jarno Elonen \n"+ - "\n"+ - "Redistribution and use in source and binary forms, with or without\n"+ - "modification, are permitted provided that the following conditions\n"+ - "are met:\n"+ - "\n"+ - "Redistributions of source code must retain the above copyright notice,\n"+ - "this list of conditions and the following disclaimer. Redistributions in\n"+ - "binary form must reproduce the above copyright notice, this list of\n"+ - "conditions and the following disclaimer in the documentation and/or other\n"+ - "materials provided with the distribution. The name of the author may not\n"+ - "be used to endorse or promote products derived from this software without\n"+ - "specific prior written permission. \n"+ - " \n"+ - "THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n"+ - "IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n"+ - "OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n"+ - "IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n"+ - "INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n"+ - "NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"+ - "DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"+ - "THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"+ - "(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"+ - "OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."; -} \ No newline at end of file diff --git a/src/org/torproject/android/service/TorService.java b/src/org/torproject/android/service/TorService.java index 583c75ee..50e47842 100644 --- a/src/org/torproject/android/service/TorService.java +++ b/src/org/torproject/android/service/TorService.java @@ -42,9 +42,6 @@ public class TorService extends Service implements TorServiceConstants, Runnable private static final int NOTIFY_ID = 1; - /* removing this for now - it is a work in progress and a security risk - 3/17/2010 */ - //private static TorWebProxy _webProxy; - /** Called when the activity is first created. */ @Override @@ -418,14 +415,7 @@ public class TorService extends Service implements TorServiceConstants, Runnable } }.start(); - /* - //removing this for now - nf - 3/17/2010 - if (_webProxy == null) - { - _webProxy = new TorWebProxy(); - - }*/ - + } private void runTorShellCmd() throws Exception diff --git a/src/org/torproject/android/service/TorWebProxy.java b/src/org/torproject/android/service/TorWebProxy.java deleted file mode 100644 index 6ca10a54..00000000 --- a/src/org/torproject/android/service/TorWebProxy.java +++ /dev/null @@ -1,254 +0,0 @@ -package org.torproject.android.service; - -import java.io.IOException; -import java.io.InputStream; -import java.net.MalformedURLException; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URL; -import java.util.Iterator; -import java.util.Properties; -import java.util.Map.Entry; - -import org.apache.http.HttpHost; -import org.apache.http.HttpResponse; -import org.apache.http.HttpVersion; -import org.apache.http.client.ClientProtocolException; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.client.methods.HttpUriRequest; -import org.apache.http.conn.ClientConnectionManager; -import org.apache.http.conn.params.ConnRoutePNames; -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.conn.ssl.SSLSocketFactory; -import org.apache.http.impl.client.DefaultHttpClient; -import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager; -import org.apache.http.params.BasicHttpParams; -import org.apache.http.params.HttpParams; -import org.apache.http.params.HttpProtocolParams; -import org.torproject.android.Utils; - -import android.util.Log; - -public class TorWebProxy extends NanoHTTPD implements TorServiceConstants -{ - private final static String BASE_URI = "http://localhost:8888/"; - - private final static String DEFAULT_URI = "https://check.torproject.org/"; - private java.net.URLDecoder decoder; - - private String lastPage = null; - - private final static int PORT = 8888; - - public TorWebProxy() throws IOException - { - super(PORT); - - decoder = new java.net.URLDecoder(); - - Log.i(TAG,"TorWebProxy started on port: " + PORT); - } - - public Response serve( String uri, String method, Properties header, Properties params ) - { - Log.i(TAG,"TorWebProxy serve(): " + method + " '" + uri + "' " ); - - - InputStream contentStream = null; - - String requestUrl = null; - - if (uri.toLowerCase().startsWith("/http")) - { - //okay this is cool - requestUrl = uri.substring(1); - requestUrl = decoder.decode(requestUrl); - } - else if (params.getProperty("url")!=null) - { - requestUrl = params.getProperty("url"); - } - else if (uri.equals("/")) - { - requestUrl = DEFAULT_URI; - } - else //must be a relative path - { - if (lastPage != null) - { - - if (!uri.startsWith("/")) - uri = "/" + uri; - - try { - URL lastPageUrl = new URL(lastPage); - - StringBuilder sb = new StringBuilder(); - sb.append(lastPageUrl.getProtocol()); - sb.append("://"); - sb.append(lastPageUrl.getHost()); - - if (lastPageUrl.getPort()!=-1) - { - sb.append(":"); - sb.append(lastPageUrl.getPort()); - } - - sb.append(uri); - - requestUrl = sb.toString(); - - } catch (MalformedURLException e) { - Log.i(TAG, "TorWebProxy: " + e.getLocalizedMessage(),e); - - return new NanoHTTPD.Response(NanoHTTPD.HTTP_INTERNALERROR,"text/plain","Something bad happened: " + e.getLocalizedMessage()); - - } - - - } - } - - HttpUriRequest request = null; - HttpHost host = null; - - - URI rURI = null; - try { - rURI = new URI(requestUrl); - } catch (URISyntaxException e) { - Log.e(TAG,"error parsing uri: " + requestUrl,e); - return new NanoHTTPD.Response(NanoHTTPD.HTTP_INTERNALERROR,"text/plain","error"); - - } - - int port = rURI.getPort(); - - if (port == -1) - { - if (rURI.getScheme().equalsIgnoreCase("http")) - port = 80; - else if (rURI.getScheme().equalsIgnoreCase("https")) - port = 443; - } - - host = new HttpHost(rURI.getHost(),port, rURI.getScheme()); - - Log.i(TAG,"TorWebProxy server(): host=" + host.getSchemeName() + "://" + host.getHostName() + ":" + host.getPort()); - - if (method.equalsIgnoreCase("get")) - { - Log.i(TAG,"TorWebProxy serve(): GET: " + rURI.getPath() ); - request = new HttpGet (rURI.getPath()); - } - else if (method.equalsIgnoreCase("post")) - { - Log.i(TAG,"TorWebProxy serve(): POST: " + rURI.getPath() ); - - request = new HttpPost(rURI.getPath()); - - - //request = new HttpPost (requestUrl); - - Iterator> itSet = params.entrySet().iterator(); - - Entry entry = null; - - HttpParams hParams = request.getParams(); - - while (itSet.hasNext()) - { - entry = itSet.next(); - - hParams.setParameter((String)entry.getKey(), entry.getValue()); - } - - request.setParams(hParams); - - } - else - { - return new NanoHTTPD.Response(NanoHTTPD.HTTP_NOTIMPLEMENTED,"text/plain","No support for the method: " + method); - - } - - // SOCKSHttpClient client = new SOCKSHttpClient(); - - HttpHost proxy = new HttpHost("127.0.0.1", 8118, "http"); - SchemeRegistry supportedSchemes = new SchemeRegistry(); - // Register the "http" and "https" protocol schemes, they are - // required by the default operator to look up socket factories. - supportedSchemes.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); - supportedSchemes.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443)); - // prepare parameters - HttpParams hparams = new BasicHttpParams(); - HttpProtocolParams.setVersion(hparams, HttpVersion.HTTP_1_1); - HttpProtocolParams.setContentCharset(hparams, "UTF-8"); - HttpProtocolParams.setUseExpectContinue(hparams, true); - ClientConnectionManager ccm = new ThreadSafeClientConnManager(hparams, supportedSchemes); - - DefaultHttpClient client = new DefaultHttpClient(ccm, hparams); - client.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy); - - - try { - HttpResponse response = client.execute(host, request); - - if (response.getEntity() == null || response.getEntity().getContentType() == null) - { - return new NanoHTTPD.Response(NanoHTTPD.HTTP_INTERNALERROR,"text/plain","Something bad happened"); - - } - - String contentType = response.getEntity().getContentType().getValue(); - - int respCode = response.getStatusLine().getStatusCode(); - - Log.i(TAG,"TorWebProxy server(): resp=" + respCode + ";" + contentType); - - contentStream = response.getEntity().getContent(); - - if (contentType.indexOf("text/html")!=-1) - { - response.getEntity().getContentLength(); - - lastPage = requestUrl; - - String page = Utils.readString(contentStream); - - page = page.replace("href=\"", "href=\"" + BASE_URI); - page = page.replace("src=\"", "src=\"" + BASE_URI); - page = page.replace("action=\"", "action=\"" + BASE_URI); - - page = page.replace("HREF=\"", "href=\"" + BASE_URI); - page = page.replace("SRC=\"", "src=\"" + BASE_URI); - page = page.replace("ACTION=\"", "action=\"" + BASE_URI); - - - return new NanoHTTPD.Response( HTTP_OK, contentType, page ); - } - else - return new NanoHTTPD.Response( HTTP_OK, contentType, contentStream ); - - } catch (ClientProtocolException e) { - Log.w(TAG,"TorWebProxy",e); - - } catch (IOException e) { - Log.w(TAG,"TorWebProxy",e); - - } - catch (NullPointerException e) - { - Log.w(TAG,"TorWebProxy",e); - } - - return new NanoHTTPD.Response(NanoHTTPD.HTTP_INTERNALERROR,"text/plain","Something bad happened"); - - } - - - -} \ No newline at end of file