/** * OnionCoffee - Anonymous Communication through TOR Network * Copyright (C) 2005-2007 RWTH Aachen University, Informatik IV * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. * * 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, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ package TorJava.Common; import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintStream; import java.net.InetSocketAddress; import java.net.Socket; import java.net.UnknownHostException; import TorJava.TCPStream; /** * this class contains general utility functions * * @author Lexi Pimenidis * @author Andriy Panchenko * @author Michael Koellejan * @author Connell Gauld */ public class StreamsAndHTTP { /** * read http-request/response from input stream */ public static String readHTTPFromStream(InputStream in) { // DataInputStream.readLine() is depreacated BufferedReader sin = new BufferedReader(new InputStreamReader(in), 16384); StringBuffer header = new StringBuffer(); StringBuffer body = new StringBuffer(); try { // read header String str = sin.readLine(); while ((str != null) && (str.length() > 0)) { header.append(str + "\n"); str = sin.readLine(); } ; header.append("\n"); // check length of body str = header.toString(); if (str.startsWith("HTTP/") || str.startsWith("POST ")) { int content_length_start = str.indexOf("Content-Length: ") + 16; int content_length_end = str.indexOf("\n", content_length_start); // System.out.println("Parsing HTTP:\n"+str+"Start // "+content_length_start+" End "+content_length_end); // parse body only, if legitimate HTTP if (content_length_start >= 16) { int content_length = Integer.parseInt(str.substring( content_length_start, content_length_end)); // System.out.println("Length "+content_length); // read body char[] body_bytes = new char[content_length]; int filled = 0; int t=0; do { t = sin.read(body_bytes, filled, content_length - filled); filled += t; } while ((filled < content_length)&&(t>=0)); // until buffer filled or EOF body.append(body_bytes); } else { // if no content-length is given, just read all try{ char[] body_bytes = new char[512]; int filled = 0; do { filled = sin.read(body_bytes, 0, body_bytes.length); if(filled>0) body.append(body_bytes,0,filled); } while (filled>=0); // detect EOF } catch (IOException e) { /* eof, reset, ... */ } } } } catch (IOException e) { /* eof, reset, ... */ } catch (NumberFormatException e) { /* * throwed by Integer.parseInt() in * case some practical prank is * played on us */ } return header.toString() + body.toString(); } /** * reads all data from an inputstream */ public static String readAllFromStream(InputStream in) { // DataInputStream.readLine() is depreacated BufferedReader sin = new BufferedReader(new InputStreamReader(in), 16384); StringBuffer buf = new StringBuffer(); try { String str = sin.readLine(); while (str != null) { buf.append(str); buf.append("\n"); str = sin.readLine(); } ; } catch (IOException e) { /* eof, reset, ... */ } return buf.toString(); } /** does a HTTP-request */ public static String HTTPRequest(OutputStream out, InputStream in, String req) { PrintStream sout = new PrintStream(out); sout.print(req); sout.flush(); String data = readHTTPFromStream(in); sout.close(); return data; } /** does a HTTP-request */ public static String HTTPRequest(String host, int port, String req) throws UnknownHostException,IOException { Socket s = new Socket(host,port); String response = HTTPRequest(s.getOutputStream(),s.getInputStream(),req); s.close(); return response; } /** does a HTTP-request, timeout is in milliseconds? */ public static String HTTPRequest(String host, int port, String req, int timeout) throws UnknownHostException,IOException { Socket s = new Socket(); s.connect(new InetSocketAddress(host,port),timeout); String response = HTTPRequest(s.getOutputStream(),s.getInputStream(),req); s.close(); return response; } /** * gets service descriptor of the hidden service */ public static byte[] retrieveServiceDescriptor(TCPStream stream, String z) throws IOException { byte[] answer = BinaryHTTPRequest(stream.getOutputStream(), stream .getInputStream(), "GET /tor/rendezvous/" + z + " HTTP/1.0\r\n\r\n"); stream.close(); return answer; } /** does a HTTP-request */ public static String HTTPBinaryRequest(OutputStream out, InputStream in, byte[] req) throws IOException { out.write(req); out.flush(); String data = readHTTPFromStream(in); return data; } /// ADDED TO FIX HIDDEN SERVICES /** * Read all of the data available * @param in the input to read from * @return the data read */ public static byte[] binaryReadHTTPFromStream(InputStream in) { ByteArrayOutputStream out = new ByteArrayOutputStream(); try { // Read all in int read = 0; byte[] buffer = new byte[1024]; while(read > -1) { out.write(buffer, 0, read); read = in.read(buffer); } return out.toByteArray(); } catch (IOException e) { // Just return an empty array return new byte[0]; } } /** * Performs an HTTP request and returns binary data (including headers) * @param out Outgoing stream * @param in Incoming stream * @param req The HTTP request line (e.g. "GET ...") * @return the data received (including headers) */ public static byte[] BinaryHTTPRequest(OutputStream out, InputStream in, String req) { PrintStream sout = new PrintStream(out); sout.print(req); sout.flush(); byte[] data = binaryReadHTTPFromStream(in); sout.close(); return data; } }