package org.fnppl.opensdx.http; /* * Copyright (C) 2010-2015 * fine people e.V. <opensdx@fnppl.org> * Henning Thieß <ht@fnppl.org> * * http://fnppl.org */ /* * Software license * * As far as this file or parts of this file is/are software, rather than documentation, this software-license applies / shall be applied. * * This file is part of openSDX * openSDX is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * openSDX 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 Lesser General Public License * and GNU General Public License along with openSDX. * If not, see <http://www.gnu.org/licenses/>. * */ /* * Documentation license * * As far as this file or parts of this file is/are documentation, rather than software, this documentation-license applies / shall be applied. * * This file is part of openSDX. * Permission is granted to copy, distribute and/or modify this document * under the terms of the GNU Free Documentation License, Version 1.3 * or any later version published by the Free Software Foundation; * with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. * A copy of the license is included in the section entitled "GNU * Free Documentation License" resp. in the file called "FDL.txt". * */ import java.io.*; import java.net.*; import java.util.*; import org.fnppl.opensdx.xml.Document; //http://de.wikipedia.org/wiki/Hypertext_Transfer_Protocol public class HTTPServerRequest { public final static String XMLDOCPARAMNAME = "xmldocument"; public Hashtable<String, String> headers = new Hashtable<String, String>(); public Hashtable<String, String> parameters = new Hashtable<String, String>(); public Document xml; public byte[] contentData; public String cmd = null; public String method = null; private String ipv4_from_socket = null; private String ipv4_from_header = null; public long datetime = -1L; private HTTPServerRequest() { datetime = System.currentTimeMillis(); } public static HTTPServerRequest fromInputStream(BufferedInputStream in, String ipv4) throws Exception { HTTPServerRequest ret = new HTTPServerRequest(); ret.ipv4_from_socket = ipv4; String zeile = null; zeile = readLineASCII(in, 4096); //cmdline if (zeile!=null) { //System.out.println("zeile cmdline: "+zeile); StringTokenizer st = new StringTokenizer(zeile, " "); ret.method = st.nextToken(); ret.cmd = st.nextToken(); try { String proto = st.nextToken(); } catch (Exception ex) { //this happens for a PUT request } if(st.hasMoreTokens()) { System.out.println((new Date())+" :: "+ret.ipv4_from_socket+" :: KeyServerRequest | Method: "+ret.method+"\tCmd: "+ret.cmd); throw new Exception("INVALID HTTP _ MORE TOKEN AS _ "+st.nextToken()); } readHeader(in, ret); System.out.println((new Date())+" :: "+ret.getRealIP()+" :: KeyServerRequest | Method: "+ret.method+"\tCmd: "+ret.cmd); //System.out.println("::header end::"); if (ret.method.equals("POST") && ret.headers.get("Content-Type").equals("text/xml")) { readXMLPostContent(in, ret); } else if(ret.method.equals("POST") && ret.headers.get("Content-Type").equals("application/x-www-form-urlencoded")) { // Content-Type: application/x-www-form-urlencoded readPostParams(in, ret); } else if(ret.method.equals("POST") && ret.headers.get("Content-Type").equals("application/osdx-encrypted")) { readContentData(in, ret); } else if(ret.method.equals("GET")) { readGetParams(ret); } else if(ret.method.equals("PUT")) { readContentData(in, ret); } } return ret; } private static void readXMLPostContent(InputStream in, HTTPServerRequest re) throws Exception { System.out.println("KeyServerRequest::reading xml POST content"); // while(in.available() == 0) { //wait for data // Thread.sleep(100); // } ByteArrayOutputStream bout = new ByteArrayOutputStream(); int read = 0; int toread = Integer.parseInt(re.headers.get("Content-Length")); //System.out.println("KeyServerRequest::Content-length: "+toread); byte[] buff = new byte[4096]; //while((read=in.read(buff))!=-1) { while((read = in.read(buff,0, Math.min(buff.length, toread))) != -1) { // read = in.read(buff); bout.write(buff, 0, read); toread -= read; if(toread == 0) { break; } } String s = new String(bout.toByteArray(), "UTF-8"); //String s = new String(bout.toByteArray(), "ASCII"); //s = URLDecoder.decode(s, "UTF-8"); //urlencoded-form-data System.out.println("KeyServerRequest::GOT THIS AS DOC: ::START::"+s+"::END::"); re.xml = Document.fromStream(new ByteArrayInputStream(s.getBytes("UTF-8"))); } private static void readPostParams(InputStream in, HTTPServerRequest re) throws Exception { //System.out.println("KeyServerRequest::reading POST params"); ByteArrayOutputStream bout = new ByteArrayOutputStream(); int read = 0; int toread = Integer.parseInt(re.headers.get("Content-Length")); //System.out.println("KeyServerRequest::Content-length: "+toread); byte[] buff = new byte[4096]; //while((read=in.read(buff))!=-1) { while((read = in.read(buff,0, Math.min(buff.length, toread))) != -1) { // read = in.read(buff); bout.write(buff, 0, read); toread -= read; if(toread == 0) { break; } } String s = new String(bout.toByteArray(), "ASCII");//alles ascii StringTokenizer trenn = new StringTokenizer(s, "&"); while (trenn.hasMoreTokens()) { StringTokenizer st = new StringTokenizer(trenn.nextToken(), "="); while(st.hasMoreTokens()) { String pn = URLDecoder.decode(st.nextToken(), "UTF-8"); String pv = URLDecoder.decode(st.nextToken(), "UTF-8"); //System.out.println("***"+pn+"::::"+pv+"::::"); if(pn.equalsIgnoreCase(XMLDOCPARAMNAME)) { re.xml = Document.fromStream(new ByteArrayInputStream(pv.getBytes("UTF-8"))); re.xml.output(System.out); } else { re.parameters.put(pn, pv); System.out.println("parameter: "+pn+" = "+pv); } } } } private static void readGetParams(HTTPServerRequest re) throws Exception { String me = null; if(re.cmd.indexOf("?")>0) { me = re.cmd.substring(re.cmd.indexOf("?")+1); re.cmd = re.cmd.substring(0, re.cmd.indexOf("?")); StringTokenizer st = new StringTokenizer(me, "="); while(st.hasMoreTokens()) { String pn = URLDecoder.decode(st.nextToken(), "UTF-8"); String pv = URLDecoder.decode(st.nextToken(), "UTF-8"); if(pn.equalsIgnoreCase(XMLDOCPARAMNAME)) { re.xml = Document.fromStream(new ByteArrayInputStream(pv.getBytes("UTF-8"))); } else { re.parameters.put(pn, pv); } } } } private static void readContentData(InputStream in, HTTPServerRequest re) throws Exception { ByteArrayOutputStream bout = new ByteArrayOutputStream(); int toread = Integer.parseInt(re.headers.get("Content-Length")); int read; byte[] buff = new byte[4096]; while((read = in.read(buff,0, Math.min(buff.length, toread))) != -1) { bout.write(buff, 0, read); toread -= read; if(toread == 0) { break; } } re.contentData = bout.toByteArray(); } public String getRealIP() { if(ipv4_from_header!=null) { return ipv4_from_header; } return ipv4_from_socket; } private static void readHeader(BufferedInputStream in, HTTPServerRequest re) throws Exception { String zeile = null; while ((zeile=readLineASCII(in, 4096)) != null) { if(zeile.length() == 0) { return;//heade-ende } //header // String[] p = parseHeader(zeile); // re.headers.put(p[0], p[1]); // StringTokenizer st = new StringTokenizer(zeile, " "); // re.headers.put(st.nextToken(), st.nextToken()); String n = zeile.substring(0, zeile.indexOf(": ")); String v = zeile.substring(zeile.indexOf(": ")+2); // re.headers.put(URLDecoder.decode(n, "UTF-8"), URLDecoder.decode(v, "UTF_8")); re.headers.put(n, v); System.out.println("header: "+zeile); if(n.equalsIgnoreCase("X-Real-IP")) { re.ipv4_from_header = v; } } } // private static String[] parseHeader(String zeile) { // StringTokenizer st = new StringTokenizer(zeile, " "); // String[] ret = new String[2]; // ret[0] = st.nextToken(); // ret[0] = ret[0].substring(0, ret[0].length()-1);//cut off ":" // // ret[1] = st.nextToken(); // // return ret; // } private static String readLineASCII(BufferedInputStream in, int maxbytes) throws Exception { //if (in.available()<=0) return null; ByteArrayOutputStream bout = new ByteArrayOutputStream(); //HEADERS are ASCII byte[] b = new byte[1]; int r = 0; char last='\r'; while((r=in.read(b)) > 0 && bout.size()<maxbytes) { char m = (char)b[0]; if(m == '\n') { break; } else if(m != '\r') { bout.write(b[0]); } } if(r<0 && bout.size() == 0) { return null; } String s = new String(bout.toByteArray(), "ASCII"); // System.out.println("OSDXKeyServerClient | "+s); return s; } public String getHeaderValue(String headerName) { return headers.get(headerName); } public String getParamValue(String paramName) { return parameters.get(paramName); } }