2016-02-19 20:28:26 +01:00
|
|
|
/*
|
|
|
|
|
* The MIT License (MIT)
|
|
|
|
|
*
|
|
|
|
|
* Copyright (c) 2015 Ziver Koc
|
|
|
|
|
*
|
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
|
|
|
* in the Software without restriction, including without limitation the rights
|
|
|
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
|
|
|
* furnished to do so, subject to the following conditions:
|
|
|
|
|
*
|
|
|
|
|
* The above copyright notice and this permission notice shall be included in
|
|
|
|
|
* all copies or substantial portions of the Software.
|
|
|
|
|
*
|
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
|
* THE SOFTWARE.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
package zutil.net.http;
|
|
|
|
|
|
|
|
|
|
import zutil.parser.URLDecoder;
|
|
|
|
|
|
|
|
|
|
import java.io.BufferedReader;
|
|
|
|
|
import java.io.IOException;
|
|
|
|
|
import java.io.StringReader;
|
|
|
|
|
import java.util.regex.Pattern;
|
|
|
|
|
|
|
|
|
|
public class HttpHeaderParser {
|
|
|
|
|
public static final String HEADER_COOKIE = "COOKIE";
|
|
|
|
|
|
|
|
|
|
private static final Pattern PATTERN_COLON = Pattern.compile(":");
|
|
|
|
|
private static final Pattern PATTERN_EQUAL = Pattern.compile("=");
|
|
|
|
|
private static final Pattern PATTERN_AND = Pattern.compile("&");
|
|
|
|
|
private static final Pattern PATTERN_SEMICOLON = Pattern.compile(";");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private BufferedReader in;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Parses the HTTP header information from a stream
|
|
|
|
|
*
|
|
|
|
|
* @param in is the stream
|
|
|
|
|
*/
|
|
|
|
|
public HttpHeaderParser(BufferedReader in){
|
|
|
|
|
this.in = in;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Parses the HTTP header information from a String
|
|
|
|
|
*
|
|
|
|
|
* @param in is the String
|
|
|
|
|
*/
|
|
|
|
|
public HttpHeaderParser(String in){
|
|
|
|
|
this.in = new BufferedReader(new StringReader(in));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public HttpHeader read() throws IOException {
|
|
|
|
|
HttpHeader header = null;
|
|
|
|
|
String line = null;
|
|
|
|
|
if( (line=in.readLine()) != null && !line.isEmpty() ){
|
|
|
|
|
header = new HttpHeader();
|
|
|
|
|
parseStatusLine(header, line);
|
|
|
|
|
while( (line=in.readLine()) != null && !line.isEmpty() ){
|
|
|
|
|
parseLine(header, line);
|
|
|
|
|
}
|
|
|
|
|
parseCookies(header);
|
|
|
|
|
}
|
|
|
|
|
return header;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Parses the first header line and ads the values to
|
|
|
|
|
* the map and returns the file name and path
|
|
|
|
|
*
|
|
|
|
|
* @param line The header String
|
|
|
|
|
* @return The path and file name as a String
|
|
|
|
|
*/
|
|
|
|
|
protected static void parseStatusLine(HttpHeader header, String line){
|
|
|
|
|
// Server Response
|
|
|
|
|
if( line.startsWith("HTTP/") ){
|
2016-05-31 16:55:08 +02:00
|
|
|
header.setIsRequest(false);
|
2016-02-19 20:28:26 +01:00
|
|
|
header.setHTTPVersion( Float.parseFloat( line.substring( 5 , 8)));
|
|
|
|
|
header.setHTTPCode( Integer.parseInt( line.substring( 9, 12 )));
|
|
|
|
|
}
|
|
|
|
|
// Client Request
|
|
|
|
|
else if(line.contains("HTTP/")){
|
2016-05-31 16:55:08 +02:00
|
|
|
header.setIsRequest(true);
|
2016-02-19 20:28:26 +01:00
|
|
|
header.setRequestType( line.substring(0, line.indexOf(" ")));
|
|
|
|
|
header.setHTTPVersion( Float.parseFloat( line.substring(line.lastIndexOf("HTTP/")+5 , line.length()).trim()));
|
|
|
|
|
line = (line.substring(header.getRequestType().length()+1, line.lastIndexOf("HTTP/")));
|
|
|
|
|
|
|
|
|
|
// parse URL and attributes
|
|
|
|
|
int index = line.indexOf('?');
|
|
|
|
|
if(index > -1){
|
|
|
|
|
header.setRequestURL( line.substring(0, index));
|
|
|
|
|
line = line.substring( index+1, line.length());
|
|
|
|
|
parseURLParameters(header, line);
|
|
|
|
|
}
|
|
|
|
|
else{
|
|
|
|
|
header.setRequestURL(line);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Parses the rest of the header
|
|
|
|
|
*
|
|
|
|
|
* @param line is the next line in the header
|
|
|
|
|
*/
|
|
|
|
|
protected void parseLine(HttpHeader header, String line){
|
|
|
|
|
String[] data = PATTERN_COLON.split( line, 2 );
|
|
|
|
|
header.putHeader(
|
|
|
|
|
data[0].trim().toUpperCase(), // Key
|
|
|
|
|
(data.length>1 ? data[1] : "").trim()); //Value
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Parses the header "Cookie" and stores all cookies in the HttpHeader object
|
|
|
|
|
*/
|
|
|
|
|
protected void parseCookies(HttpHeader header){
|
|
|
|
|
String cookieHeader = header.getHeader(HEADER_COOKIE);
|
|
|
|
|
if(cookieHeader != null && !cookieHeader.isEmpty()){
|
|
|
|
|
String[] tmp = PATTERN_SEMICOLON.split(cookieHeader);
|
|
|
|
|
for(String cookie : tmp){
|
|
|
|
|
String[] tmp2 = PATTERN_EQUAL.split(cookie, 2);
|
|
|
|
|
header.putCookie(
|
|
|
|
|
tmp2[0].trim(), // Key
|
|
|
|
|
(tmp2.length>1 ? tmp2[1] : "").trim()); //Value
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Parses a String with variables from a get or post
|
|
|
|
|
* that was sent from a client
|
|
|
|
|
*
|
|
|
|
|
* @param attributes is the String containing all the attributes
|
|
|
|
|
*/
|
|
|
|
|
protected static void parseURLParameters(HttpHeader header, String attributes){
|
|
|
|
|
String[] tmp;
|
|
|
|
|
attributes = URLDecoder.decode(attributes);
|
|
|
|
|
// get the variables
|
|
|
|
|
String[] data = PATTERN_AND.split( attributes );
|
|
|
|
|
for(String element : data){
|
|
|
|
|
tmp = PATTERN_EQUAL.split(element, 2);
|
|
|
|
|
header.putURLAttribute(
|
|
|
|
|
tmp[0].trim(), // Key
|
|
|
|
|
(tmp.length>1 ? tmp[1] : "").trim()); //Value
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|