All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ch.software_atelier.simpleflex.Request Maven / Gradle / Ivy

There is a newer version: 2.2.2
Show newest version
/*
 *
 * To change the template for this generated file go to
 * Window - Preferences - Java - Code Generation - Code and Comments
 */
package ch.software_atelier.simpleflex;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.StringTokenizer;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import xmlwise.XmlElement;
import xmlwise.XmlParseException;
import xmlwise.Xmlwise;

/**
 * Holds a request with all contents sent by a WebBrowser.
 */
public class Request {

    public static String CONTENT_TYPE_MULTIPART = "multipart/form-data";

    public static String CONTENT_TYPE_APPLICATION = "application/x-www-form-urlencoded";

    public static String CONTENT_TYPE_XML = "application/xml";

    public static String CONTENT_TYPE_JSON = "application/json";

    public static String CONTENT_TYPE_JSON_PATCH = "application/json-patch+json";

    private JSONObject _json = null;

    private JSONArray _jsonArr = null;

    private XmlElement _xml = null;

    private final ArrayList _recievedData;

    private String _protocoll;

    private String _method;

    private String _requestString;

    private final HashMap _headerContent;
    private HashMap _arrayCounter = new HashMap<>();
    
    private InetAddress _client;

    private boolean _secureConnection;

    private final ArrayList _arguments;

    private File _file;

    private String _fileName;

    ////
    // Some static Header-Specifiers
    ////
    public static final String HTTPHEADER_CONTENT_LENGTH = "Content-Length";

    public static final String HTTPHEADER_CONTENT_DISPOSITION = "Content-Disposition";

    public static final String HTTPHEADER_ACCEPT_LANGUAGE = "Accept-Language";

    public static final String HTTPHEADER_ACCEPT_ENCODING = "Accept-Encoding";

    public static final String HTTPHEADER_ACCEPT_CHARSET = "Accept-Charset";

    public static final String HTTPHEADER_ACCEPT = "Accept";

    public static final String HTTPHEADER_USER_AGENT = "User-Agent";

    public static final String HTTPHEADER_HOST = "Host";

    public static final String HTTPHEADER_REFERER = "Referer";

    public static final String HTTPHEADER_CONTENT_TYPE = "Content-Type";

    public static final String HTTPHEADER_CONNECTION = "Connection";

    public static final String METHOD_POST = "POST";

    public static final String METHOD_GET = "GET";

    public static final String METHOD_OPTIONS = "OPTIONS";

    public static final String METHOD_PUT = "PUT";

    public static final String METHOD_DELETE = "DELETE";

    public static final String METHOD_PATCH = "PATCH";

    static Logger LOG = LogManager.getLogger(RequestHandler.class);

    /**
     * 
     */
    public Request() {
        this._recievedData = new ArrayList();
        this._headerContent = new HashMap<>();
        this._arguments = new ArrayList();
    }

    ///////////////////////////////////
    // Setter
    ///////////////////////////////////

    /**
     * Adds a Header-Object to the Request-Object.
     * @param line The Headerline given by the Client
     * @return sucessfully added? yes/no
     */
    protected boolean addHeaderLine(String line) {
        StringTokenizer st = new StringTokenizer(line, ":");
        String key;
        String value;
        if (st.hasMoreElements())
            key = st.nextToken();
        else
            return false;

        if (line.length() > (key.length() + 1))
            value = line.substring(key.length() + 1, line.length()).trim();
        else
            return false;

        _headerContent.put(key, value);
        return true;
    }

    /**
     * 
     * @param secure
     */
    public void setSecure(boolean secure) {
        _secureConnection = secure;
    }

    /**
     * 
     * @param client
     */
    public void setClient(InetAddress client) {
        _client = client;
    }

    /**
     * 
     * @param protocoll
     */
    public void setProtocoll(String protocoll) {
        _protocoll = protocoll;
    }

    /**
     * 
     * @param method
     */
    public void setMethod(String method) {
        _method = method;
    }

    /**
     * 
     * @param requestString
     */
    public void setRequestString(String requestString) {
        StringTokenizer st = new StringTokenizer(requestString, "?");
        _requestString = decode(st.nextToken());
        if (st.hasMoreTokens()) {
            String arguments = st.nextToken();
            StringTokenizer argumentTokenizer = new StringTokenizer(arguments, "&");
            while (argumentTokenizer.hasMoreTokens()) {
                String argVal = argumentTokenizer.nextToken();
                String key = null;
                String val = null;
                StringTokenizer argValTokenizer = new StringTokenizer(argVal, "=");
                if (argValTokenizer.hasMoreTokens())
                    key = argValTokenizer.nextToken();
                if (argValTokenizer.hasMoreTokens())
                    val = argValTokenizer.nextToken();
                if ((key != null) && (val != null))
                    _arguments.add(new RequestArgument(decode(key), decode(val)));
                else if (argVal.length() > 0)
                    _arguments.add(new RequestArgument(decode(argVal), ""));
            }
        }

    }

    /**
     * 
     * @return
     */
    public RequestArgument[] arguments() {
        RequestArgument[] args = new RequestArgument[_arguments.size()];
        args = (RequestArgument[]) _arguments.toArray(args);
        return args;
    }

    /**
     * 
     * @param key
     * @return
     */
    public String getArgument(String key) {
        for (int i = 0; i < _arguments.size(); i++) {
            RequestArgument arg = (RequestArgument) _arguments.get(i);
            if (arg.key().equals(key))
                return arg.value();
        }
        return null;
    }

    /**
     * 
     * @param str
     * @return
     */
    private String decode(String str) {
        try {
            return URLDecoder.decode(str, "UTF-8");
        }
        catch (UnsupportedEncodingException uee) {
            // never thrown if host supports UTF-8
            return str;
        }
    }

    ///////////////////////////////////
    // Getter
    ///////////////////////////////////

    /**
     * Returns the version of the used protocol. Example: HTTP/1.0
     */
    public String getProtocoll() {
        return _protocoll;
    }

    /**
     * This method returns GET or POST
     * @return
     */
    public String getMethod() {
        return _method;
    }

    /**
     * Returns the Request-String. It is a Path to a File.
     * @return a path to a File like /index.htm or /something/abc.mpg
     */
    public String getReqestString() {
        return _requestString;
    }

    /**
     * 
     * @return
     */
    public String getLastRequestStringComponent() {
        List path = Utils.tokenize(this.getReqestString(), "/");
        return path.get(path.size() - 1);

    }

    /**
     * 
     * @return
     */
    public HashMap getHeaders() {
        HashMap headers = new HashMap();
        Set keys = _headerContent.keySet();
        for (String key : keys) {
            String value = _headerContent.get(key);
            headers.put(key, value);
        }
        return headers;
    }

    /**
     * 
     * @param key
     * @return
     */
    public String getHeaderValue(String key) {
        if (_headerContent.containsKey(key)) {
            return _headerContent.get(key);
        }
        // This is a hack! In some cases, apache converts the headers to lower case...
        else if (_headerContent.containsKey(key.toLowerCase())) {
            return _headerContent.get(key.toLowerCase());
        } else
            return null;
    }

    /**
     * Returns true, if the connnection is secure. (HTTPS)
     * @return
     */
    public boolean isSecureConnection() {
        return _secureConnection;
    }

    /**
     * 
     * @return
     */
    public String getHost() {
        return extractCalledHostByHeaderValue(getHeaderValue(HTTPHEADER_HOST));
    }

    /**
     * 
     * @return
     */
    public int getPort() {
        String port = extractCalledPortByHeaderValue(getHeaderValue(HTTPHEADER_HOST));
        return Integer.parseInt(port);
    }

    /**
     * @return
     */
    private String extractCalledHostByHeaderValue(String headerValue) {
        StringTokenizer st = new StringTokenizer(headerValue, ":");
        if (st.hasMoreTokens())
            return st.nextToken().trim();
        else
            return null;
    }

    /**
     * Returns the connected Port (Serverside!) by the host headervalue
     * @return the port used serverside extracted from the headevalue
     */
    private String extractCalledPortByHeaderValue(String headerValue) {
        StringTokenizer st = new StringTokenizer(headerValue, ":");
        if (st.hasMoreTokens())
            st.nextToken();
        else
            return null;
        if (st.hasMoreTokens())
            return st.nextToken().trim();
        else {
            if (isSecureConnection())
                return "443";
            else
                return "80";
        }
    }

    /**
     * Returns an InetAddress-Object that holds the IP-Address of the Client
     * @return
     */
    public InetAddress getClient() {
        return _client;
    }

    public void appendSinglePart(BufferedInputStream bis, long length) throws IOException {
        _file = File.createTempFile("tmp", "bin");
        try (FileOutputStream fos = new FileOutputStream(_file)) {

            int maxBuffer = 1024 * 32;
            int buffersize = (length < maxBuffer) ? (int) length : maxBuffer;
            byte[] buffer = new byte[buffersize];
            int len;
            while (length > 0) {
                len = bis.read(buffer);
                fos.write(buffer, 0, len);
                length = length - buffersize;
                buffersize = (length < maxBuffer) ? (int) length : maxBuffer;
            }
            fos.flush();
        }

    }

    /**
     * 
     * @param bis
     * @throws IOException
     */
    public void apendMultipart(BufferedInputStream bis, long length) throws IOException {
        LOG.info("Adding multipart... " + length + "bytes");
        long l = length;
        long total_l = length;
        
        String boundaryString = getBoundary();
        String boundaryStringEnd = boundaryString+ "--";
        String line = "";
        
        File tmp = File.createTempFile("file", ".tmp");

        try (FileOutputStream fos = new FileOutputStream(tmp)) {
            int maxBuffer = 1024 * 32;
            int buffersize = (length < maxBuffer) ? (int) length : maxBuffer;
            byte[] buffer = new byte[buffersize];
            int len;
            while (length > 0) {
                len = bis.read(buffer);
                fos.write(buffer, 0, len);
                length = length - len;
            }
            fos.flush();
        }

        LOG.info("File saved. " + tmp.length() + "bytes");

        try (FileInputStream fis = new FileInputStream(tmp)) {

            HashMap headers = new HashMap();
            RecievedData recievedData = null;
            boolean isHeader = true;
            boolean headerSaved = false;
            boolean isFirstBoundary = true;
            
            UntilNewlineReader unReader = new UntilNewlineReader(fis, 1024);
            
            byte[] data = unReader.read();
            line = new String(data);
            LOG.info("First line read: " + data.length + "bytes");
            
            long counter = 0;
            // While its not the end of The Multipart
            while (!(line.trim().endsWith(boundaryStringEnd))) {
                // If its a boundary, header follows
                if (line.trim().endsWith(boundaryString)) {
                    // if its the first boundary, where is no pre data.
                    // Theres nothing to save,
                    if (isFirstBoundary)
                        isFirstBoundary = false;
                    // if its not the first boundary, there is a pre data.
                    // save it.
                    else {
                        _recievedData.add(recievedData);
                        recievedData.done();
                    }
                    // Header follows
                    isHeader = true;
                    // New Header is not saved
                    headerSaved = false;
                }
                // If headercontent is expected and there is a plain line,
                // there is no more headercontent.
                else if (((isHeader) && line.trim().equals(""))) {
                    isHeader = false;
                }
                // If headercontent is expected...
                if (isHeader) {
                    // ...split it
                    String[] keyNValue = Utils.splitHeader(line);
                    // If the header has valid key and value...
                    if (keyNValue != null) {
                        // ...save it.
                        headers.put(keyNValue[0].toUpperCase(), keyNValue[1]);
                    }

                }
                // If no Headercontent is expected...
                else {

                    if (!headerSaved) {
                        recievedData = saveHeaders(headers);

                        headerSaved = true;
                    } else {
                        if (recievedData.type() == RecievedData.TYPE_FILE) {
                            ((RecievedFile) recievedData).apendToFile(data);
                        } else if (recievedData.type() == RecievedData.TYPE_TEXT) {
                            ((RecievedText) recievedData).apendText(line);
                        }
                    }
                }

                data = unReader.read();
                
                counter ++;

                l = l - data.length;

                if (counter%100 == 0){
                    System.out.println((int)(100.0/total_l*l)+"%");
                }
                line = new String(data);
            }
            _recievedData.add(recievedData);
            recievedData.done();

            LOG.info("Received Data added: " + recievedData.fieldName());

        }
        tmp.delete();
    }

    private RecievedData saveHeaders(HashMap headers) {
        String dispositionValue = (String) headers.get(RecievedData._HEADER_CONTENT_DISPOSITION);
        StringTokenizer dispPartTokenizer = new StringTokenizer(dispositionValue, ";");
        String fieldName = null;
        String fileName = null;
        while (dispPartTokenizer.hasMoreTokens()) {
            String dispPart = dispPartTokenizer.nextToken().trim();

            if (dispPart.startsWith("name=\"")) {
                fieldName = dispPart.substring(6, dispPart.length() - 1).trim();
            } else if (dispPart.startsWith("filename=\"")) {
                fileName = dispPart.substring(10, dispPart.length() - 1).trim();
            }
        }
        
        // array handling if there is a field ending with []
        
        if (fieldName.endsWith("[]")){
            fieldName = fieldName.substring(0, fieldName.length()-2);
            int pos = -1;
            if (_arrayCounter.containsKey(fieldName)){
                pos = _arrayCounter.get(fieldName);
            }
            pos++;
            _arrayCounter.put(fieldName, pos);
            fieldName = fieldName+"["+pos+"]";
        }
        
        
        System.out.println(fieldName+": "+fileName);
        RecievedData recievedData;
        if (fileName == null) {
            recievedData = new RecievedText();
        } else {
            recievedData = new RecievedFile();
            ((RecievedFile) recievedData).setFileName(fileName);
        }
        recievedData.setFieldName(fieldName);
        return recievedData;
    }

    /**
     * 
     * @param bfis
     * @param length
     * @throws IOException
     */
    public void apendURLEncoded(BufferedInputStream bfis, long length) throws IOException {
        StringBuilder sb = new StringBuilder();
        sb.append(new String(load(bfis, length)));
        StringTokenizer postTokenizer = new StringTokenizer(sb.toString(), "&");
        while (postTokenizer.hasMoreTokens()) {
            String element = postTokenizer.nextToken();
            StringTokenizer elementTokenizer = new StringTokenizer(element, "=");
            String key = null;
            String value = null;
            if (elementTokenizer.hasMoreTokens())
                key = elementTokenizer.nextToken();
            if (elementTokenizer.hasMoreTokens())
                value = elementTokenizer.nextToken();
            if ((key != null) && (value != null)) {
                RecievedText recievedText = new RecievedText();
                recievedText.setFieldName(key);
                recievedText.apendText(value);
                this.addRecievedData(recievedText);
            }
        }
    }

    /**
     * 
     * @param bfis
     * @param charset
     * @param length
     * @throws IOException
     */
    public void apendJSON(BufferedInputStream bfis, String charset, long length) throws IOException {
        String content = new String(load(bfis, length), charset);
        try {
            _json = new JSONObject(content);
        }
        catch (JSONException jsone) {
            try {
                this._jsonArr = new JSONArray(content);
            }
            catch (JSONException je) {

            }
        }
    }

    /**
     * 
     * @param bfis
     * @param charset
     * @param length
     * @throws IOException
     */
    public void apendJSONArray(BufferedInputStream bfis, String charset, long length) throws IOException {
        try {
            _jsonArr = new JSONArray(new String(load(bfis, length), charset));
        }
        catch (JSONException jsone) {

        }
    }

    /**
     * 
     * @param bfis
     * @param charset
     * @param length
     * @throws IOException
     */
    public void apendXML(BufferedInputStream bfis, String charset, long length) throws IOException {

        try {
            _xml = Xmlwise.createXml(new String(load(bfis, length), charset));
        }
        catch (XmlParseException xe) {

        }
    }

    private byte[] load(BufferedInputStream bis, long length) throws IOException {
        try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
            int buffersize = (length < 512) ? (int) length : 512;
            byte[] buffer = new byte[buffersize];
            int len;
            while (length > 0) {
                len = bis.read(buffer);
                bos.write(buffer, 0, len);
                length = length - buffersize;
                buffersize = (length < 512) ? (int) length : 512;
            }
            bos.flush();
            byte[] data = bos.toByteArray();
            return data;
        }
    }

    private void addRecievedData(RecievedData rd) {
        _recievedData.add(rd);
    }

    /**
     * 
     * @return
     */
    public RecievedData[] getRecievedData() {
        RecievedData[] rd = new RecievedData[_recievedData.size()];
        rd = (RecievedData[]) _recievedData.toArray(rd);
        return rd;
    }

    /**
     * 
     * @param field
     * @return
     */
    public RecievedText getRecievedText(String field) {
        for (RecievedData rd : _recievedData) {
            if (rd.fieldName().equals(field)) {
                if (rd instanceof RecievedText)
                    return ((RecievedText) rd);
            }
        }
        return null;
    }

    /**
     * 
     * @param field
     * @return
     */
    public RecievedFile getRecievedFile(String field) {
        for (RecievedData rd : _recievedData) {
            if (rd.fieldName().equals(field)) {
                if (rd instanceof RecievedFile)
                    return ((RecievedFile) rd);
            }
        }
        return null;
    }

    /**
     * 
     * @return
     */
    public boolean isJSONReq() {
        return (this._json != null);
    }

    /**
     * 
     * @return
     */
    public JSONObject getJSONReq() {
        return _json;
    }

    /**
     * 
     * @return
     */
    public boolean isJSONArrReq() {
        return (this._jsonArr != null);
    }

    /**
     * 
     * @return
     */
    public JSONArray getJSONArrReq() {
        return _jsonArr;
    }

    /**
     * 
     * @return
     */
    public boolean isXMLReq() {
        return (this._xml != null);
    }

    /**
     * 
     * @return
     */
    public XmlElement getXMLReq() {
        return _xml;
    }

    /**
     * 
     * @return
     */
    public boolean isFormPostReq() {
        return _recievedData.size() > 0;
    }

    /**
     * 
     * @return
     */
    public boolean isSinglePartReq() {
        return _file != null;
    }

    /**
     * 
     * @return
     */
    public String getSinglePartFilename() {
        String headerValue = getHeaderValue(HTTPHEADER_CONTENT_DISPOSITION);
        if (headerValue != null) {
            List pairs = Utils.tokenize(headerValue, ";");
            for (String pair : pairs) {
                List pairList = Utils.tokenize(pair, "=");
                if (pairList.size() == 2) {
                    if (pairList.get(0).equals("filename")) {
                        return pairList.get(1).substring(1, pairList.get(1).length() - 1);
                    }
                }
            }
        }
        return null;
    }

    /**
     * 
     * @return
     */
    public String getSinglePartMimeType() {
        String headerValue = getHeaderValue(HTTPHEADER_CONTENT_TYPE);
        if (headerValue == null)
            return null;
        List pairs = Utils.tokenize(headerValue, ";");
        if (pairs.isEmpty())
            return null;
        return pairs.get(0);
    }

    /**
     * 
     * @return
     */
    public File getSinglePartFile() {
        return _file;
    }

    /**
     * 
     * @return
     */
    public String getBoundary() {
        return extractBoundaryByHeaderValue(this.getHeaderValue(this.HTTPHEADER_CONTENT_TYPE));
    }

    /**
     * Extracts the Boundary String by the value of the Content-Type header.
     * @param headerValue The value of the Content-Type header.
     * @return The Boundary String
     */
    private String extractBoundaryByHeaderValue(String headerValue) {
        StringTokenizer st = new StringTokenizer(headerValue, ";");
        while (st.hasMoreTokens()) {
            String token = st.nextToken().trim();
            if (token.startsWith("boundary=")) {
                return token.substring(9, token.length()).trim();
            }
        }
        return null;
    }

    /**
     * 
     */
    public void cleanup() {
        if (_file != null) {
            if (!_file.delete()) {
                _file.deleteOnExit();
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy