Mega Code Archive

 
Categories / Java / Network Protocol
 

Http Parser

/** Copyright (C) 2004  Juho Vähä-Herttua This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. */ import java.io.*; import java.util.*; import java.text.*; import java.net.URLDecoder; public class HttpParser {   private static final String[][] HttpReplies = {{"100", "Continue"},                                                  {"101", "Switching Protocols"},                                                  {"200", "OK"},                                                  {"201", "Created"},                                                  {"202", "Accepted"},                                                  {"203", "Non-Authoritative Information"},                                                  {"204", "No Content"},                                                  {"205", "Reset Content"},                                                  {"206", "Partial Content"},                                                  {"300", "Multiple Choices"},                                                  {"301", "Moved Permanently"},                                                  {"302", "Found"},                                                  {"303", "See Other"},                                                  {"304", "Not Modified"},                                                  {"305", "Use Proxy"},                                                  {"306", "(Unused)"},                                                  {"307", "Temporary Redirect"},                                                  {"400", "Bad Request"},                                                  {"401", "Unauthorized"},                                                  {"402", "Payment Required"},                                                  {"403", "Forbidden"},                                                  {"404", "Not Found"},                                                  {"405", "Method Not Allowed"},                                                  {"406", "Not Acceptable"},                                                  {"407", "Proxy Authentication Required"},                                                  {"408", "Request Timeout"},                                                  {"409", "Conflict"},                                                  {"410", "Gone"},                                                  {"411", "Length Required"},                                                  {"412", "Precondition Failed"},                                                  {"413", "Request Entity Too Large"},                                                  {"414", "Request-URI Too Long"},                                                  {"415", "Unsupported Media Type"},                                                  {"416", "Requested Range Not Satisfiable"},                                                  {"417", "Expectation Failed"},                                                  {"500", "Internal Server Error"},                                                  {"501", "Not Implemented"},                                                  {"502", "Bad Gateway"},                                                  {"503", "Service Unavailable"},                                                  {"504", "Gateway Timeout"},                                                  {"505", "HTTP Version Not Supported"}};   private BufferedReader reader;   private String method, url;   private Hashtable headers, params;   private int[] ver;   public HttpParser(InputStream is) {     reader = new BufferedReader(new InputStreamReader(is));     method = "";     url = "";     headers = new Hashtable();     params = new Hashtable();     ver = new int[2];   }   public int parseRequest() throws IOException {     String initial, prms[], cmd[], temp[];     int ret, idx, i;     ret = 200; // default is OK now     initial = reader.readLine();     if (initial == null || initial.length() == 0) return 0;     if (Character.isWhitespace(initial.charAt(0))) {       // starting whitespace, return bad request       return 400;     }     cmd = initial.split("\\s");     if (cmd.length != 3) {       return 400;     }     if (cmd[2].indexOf("HTTP/") == 0 && cmd[2].indexOf('.') > 5) {       temp = cmd[2].substring(5).split("\\.");       try {         ver[0] = Integer.parseInt(temp[0]);         ver[1] = Integer.parseInt(temp[1]);       } catch (NumberFormatException nfe) {         ret = 400;       }     }     else ret = 400;     if (cmd[0].equals("GET") || cmd[0].equals("HEAD")) {       method = cmd[0];       idx = cmd[1].indexOf('?');       if (idx < 0) url = cmd[1];       else {         url = URLDecoder.decode(cmd[1].substring(0, idx), "ISO-8859-1");         prms = cmd[1].substring(idx+1).split("&");         params = new Hashtable();         for (i=0; i<prms.length; i++) {           temp = prms[i].split("=");           if (temp.length == 2) {             // we use ISO-8859-1 as temporary charset and then             // String.getBytes("ISO-8859-1") to get the data             params.put(URLDecoder.decode(temp[0], "ISO-8859-1"),                        URLDecoder.decode(temp[1], "ISO-8859-1"));           }           else if(temp.length == 1 && prms[i].indexOf('=') == prms[i].length()-1) {             // handle empty string separatedly             params.put(URLDecoder.decode(temp[0], "ISO-8859-1"), "");           }         }       }       parseHeaders();       if (headers == null) ret = 400;     }     else if (cmd[0].equals("POST")) {       ret = 501; // not implemented     }     else if (ver[0] == 1 && ver[1] >= 1) {       if (cmd[0].equals("OPTIONS") ||           cmd[0].equals("PUT") ||           cmd[0].equals("DELETE") ||           cmd[0].equals("TRACE") ||           cmd[0].equals("CONNECT")) {         ret = 501; // not implemented       }     }     else {       // meh not understand, bad request       ret = 400;     }     if (ver[0] == 1 && ver[1] >= 1 && getHeader("Host") == null) {       ret = 400;     }     return ret;   }   private void parseHeaders() throws IOException {     String line;     int idx;     // that fscking rfc822 allows multiple lines, we don't care now     line = reader.readLine();     while (!line.equals("")) {       idx = line.indexOf(':');       if (idx < 0) {         headers = null;         break;       }       else {         headers.put(line.substring(0, idx).toLowerCase(), line.substring(idx+1).trim());       }       line = reader.readLine();     }   }   public String getMethod() {     return method;   }   public String getHeader(String key) {     if (headers != null)       return (String) headers.get(key.toLowerCase());     else return null;   }   public Hashtable getHeaders() {     return headers;   }   public String getRequestURL() {     return url;   }   public String getParam(String key) {     return (String) params.get(key);   }   public Hashtable getParams() {     return params;   }   public String getVersion() {     return ver[0] + "." + ver[1];   }   public int compareVersion(int major, int minor) {     if (major < ver[0]) return -1;     else if (major > ver[0]) return 1;     else if (minor < ver[1]) return -1;     else if (minor > ver[1]) return 1;     else return 0;   }   public static String getHttpReply(int codevalue) {     String key, ret;     int i;     ret = null;     key = "" + codevalue;     for (i=0; i<HttpReplies.length; i++) {       if (HttpReplies[i][0].equals(key)) {         ret = codevalue + " " + HttpReplies[i][1];         break;       }     }     return ret;   }   public static String getDateHeader() {     SimpleDateFormat format;     String ret;     format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss", Locale.US);     format.setTimeZone(TimeZone.getTimeZone("GMT"));     ret = "Date: " + format.format(new Date()) + " GMT";     return ret;   } }