| 1: | ||
| 2: | /** | |
| 3: | * class HttpProtocol. | |
| 4: | * | |
| 5: | * Pfff....c'est quoi exactement un protocol | |
| 6: | * | |
| 7: | * @author Laurent Dehoey I177416 | |
| 8: | * @version 23/01/2003 | |
| 9: | */ | |
| 10: | public class HttpProtocol implements Protocol | |
| 11: | { | |
| 12: | /** | |
| 13: | * Socket of a request. | |
| 14: | */ | |
| 15: | protected java.net.Socket s = null; | |
| 16: | ||
| 17: | /** | |
| 18: | * Document root. | |
| 19: | */ | |
| 20: | protected static java.io.File docRoot; | |
| 21: | ||
| 22: | /** | |
| 23: | * Canonical document root. | |
| 24: | */ | |
| 25: | protected static String canonicalDocRoot; | |
| 26: | ||
| 27: | /** | |
| 28: | * The port the server will listen to | |
| 29: | */ | |
| 30: | public final static int HTTP_PORT = 8080; | |
| 31: | ||
| 32: | /** | |
| 33: | * CRLF | |
| 34: | */ | |
| 35: | public final static String CRLF = "\r\n"; | |
| 36: | ||
| 37: | /** | |
| 38: | * Protocol out server understands. | |
| 39: | */ | |
| 40: | public final static String PROTOCOL = "HTTP/1.0 "; | |
| 41: | ||
| 42: | /** | |
| 43: | * Status code: All OK. | |
| 44: | */ | |
| 45: | public final static String SC_OK = "200 OK"; | |
| 46: | ||
| 47: | /** | |
| 48: | * Status code: Bad request. | |
| 49: | */ | |
| 50: | public final static String SC_BAD_REQUEST = "400 Bad Request"; | |
| 51: | ||
| 52: | /** | |
| 53: | * Status code: Forbidden request. | |
| 54: | */ | |
| 55: | public final static String SC_FORBIDDEN = "403 Forbidden"; | |
| 56: | ||
| 57: | /** | |
| 58: | * Status code: Resource not found. | |
| 59: | */ | |
| 60: | public final static String SC_NOT_FOUND = "404 Not Found"; | |
| 61: | ||
| 62: | /** | |
| 63: | * Current status code. | |
| 64: | */ | |
| 65: | protected String statusCode = SC_OK; | |
| 66: | ||
| 67: | /** | |
| 68: | * Current header. | |
| 69: | */ | |
| 70: | protected java.util.Hashtable myHeaders = new java.util.Hashtable(); | |
| 71: | ||
| 72: | /** | |
| 73: | * Da String Constructor | |
| 74: | */ | |
| 75: | public HttpProtocol(String doc_root) | |
| 76: | { | |
| 77: | // this.docRoot=doc_root; | |
| 78: | } | |
| 79: | public void service(java.net.Socket s) throws java.lang.Exception | |
| 80: | { | |
| 81: | this.s=s; | |
| 82: | } | |
| 83: | ||
| 84: | ||
| 85: | /** | |
| 86: | * Reads the file, specified in <code>request</code> and writes it to | |
| 87: | * the OutputStream.<br> | |
| 88: | * If the file could not be found, the error message 404, | |
| 89: | * <code>Not Found</code>, is returned. | |
| 90: | * | |
| 91: | * @exception IOException in case writing to the <code>DataOutputStream</code> | |
| 92: | * fails. | |
| 93: | * @param os Stream, where the requested object is to be copied to. | |
| 94: | * @param file file to copy. | |
| 95: | */ | |
| 96: | protected void sendDocument(java.io.DataOutputStream os, java.io.File file) throws java.io.IOException | |
| 97: | { | |
| 98: | try | |
| 99: | { | |
| 100: | java.io.BufferedInputStream in = new java.io.BufferedInputStream(new java.io.FileInputStream(file)); | |
| 101: | sendStatusLine(os); | |
| 102: | setHeader("Content-Length",(new Long(file.length())).toString()); | |
| 103: | setHeader("Content-Type",guessType(file.getPath())); | |
| 104: | sendHeader(os); | |
| 105: | os.writeBytes(CRLF); | |
| 106: | byte[] buf = new byte[1024]; | |
| 107: | int len; | |
| 108: | while((len = in.read(buf,0,1024)) != -1) | |
| 109: | { | |
| 110: | os.write(buf,0,len); | |
| 111: | } | |
| 112: | in.close(); | |
| 113: | } | |
| 114: | catch(java.io.FileNotFoundException fnfe) | |
| 115: | { | |
| 116: | sendError(SC_NOT_FOUND,os); | |
| 117: | } | |
| 118: | } | |
| 119: | ||
| 120: | /** | |
| 121: | * Sets a status code. | |
| 122: | * | |
| 123: | * @param statusCode status code | |
| 124: | */ | |
| 125: | protected void setStatusCode(String statusCode) | |
| 126: | { | |
| 127: | this.statusCode = statusCode; | |
| 128: | } | |
| 129: | ||
| 130: | /** | |
| 131: | * Gets the status code. | |
| 132: | * | |
| 133: | * @return status code | |
| 134: | */ | |
| 135: | protected String getStatusCode() | |
| 136: | { | |
| 137: | return statusCode; | |
| 138: | } | |
| 139: | ||
| 140: | /** | |
| 141: | * Writes the status line to the consigned <code>DataOutputStream</code>. | |
| 142: | * | |
| 143: | * @param out DataOutputStream where the line is to be written. | |
| 144: | * @exception IOException in case writing fails. | |
| 145: | */ | |
| 146: | protected void sendStatusLine(java.io.DataOutputStream out) throws java.io.IOException | |
| 147: | { | |
| 148: | out.writeBytes(PROTOCOL + getStatusCode() + CRLF); | |
| 149: | } | |
| 150: | ||
| 151: | /** | |
| 152: | * Sets an header value. | |
| 153: | * | |
| 154: | * @param key key of the header value. | |
| 155: | * @param value the header value. | |
| 156: | */ | |
| 157: | protected void setHeader(String key, String value) | |
| 158: | { | |
| 159: | myHeaders.put(key,value); | |
| 160: | } | |
| 161: | ||
| 162: | /** | |
| 163: | * Writes the header to the consigned <code>DataOutputStream</code>. | |
| 164: | * | |
| 165: | * @param out DataOutputStream where the header is to be written. | |
| 166: | * @exception IOException in case writing fails. | |
| 167: | */ | |
| 168: | protected void sendHeader(java.io.DataOutputStream out) throws java.io.IOException | |
| 169: | { | |
| 170: | String line; | |
| 171: | String key; | |
| 172: | java.util.Enumeration e = myHeaders.keys(); | |
| 173: | while(e.hasMoreElements()) | |
| 174: | { | |
| 175: | key = (String)e.nextElement(); | |
| 176: | out.writeBytes(key + ": " + myHeaders.get(key) + CRLF); | |
| 177: | } | |
| 178: | } | |
| 179: | ||
| 180: | /** | |
| 181: | * Writes an error message to the consigned <code>DataOutputStream</code>. | |
| 182: | * | |
| 183: | * @param out DataOutputStream where the error message is to be written. | |
| 184: | * @param statusCode status code. | |
| 185: | * @exception IOException in case writing fails. | |
| 186: | */ | |
| 187: | protected void sendError(String statusCode, java.io.DataOutputStream out) throws java.io.IOException | |
| 188: | { | |
| 189: | setStatusCode(statusCode); | |
| 190: | sendStatusLine(out); | |
| 191: | out.writeBytes(CRLF + "<html>" + "<head><title>" + getStatusCode() + "</title></head>" + "<body><h1>" + getStatusCode() + "</h1></body>" + "</html>"); | |
| 192: | System.err.println(getStatusCode()); | |
| 193: | } | |
| 194: | ||
| 195: | /** | |
| 196: | * Surmise the <code>Content-Type</code> of the file by means | |
| 197: | * of the file extension. | |
| 198: | * | |
| 199: | * @param filename file name | |
| 200: | * @return Content-Type or "unknown/unknown" in case no | |
| 201: | * appropriate type is found. | |
| 202: | */ | |
| 203: | public String guessType(String filename) | |
| 204: | { | |
| 205: | String type = null; | |
| 206: | int i = filename.lastIndexOf("."); | |
| 207: | // if(i > 0) | |
| 208: | // type = typeMap.getProperty(filename.substring(i)); | |
| 209: | // if(type == null) | |
| 210: | type = "unknown/unknown"; | |
| 211: | return type; | |
| 212: | } | |
| 213: | ||
| 214: | public static void main(String argv[]) | |
| 215: | { | |
| 216: | try | |
| 217: | { | |
| 218: | // typeMap.load(new FileInputStream("mime.types")); | |
| 219: | docRoot = new java.io.File("."); | |
| 220: | canonicalDocRoot = docRoot.getCanonicalPath(); | |
| 221: | java.net.ServerSocket listen = new java.net.ServerSocket(HTTP_PORT); | |
| 222: | while(true) | |
| 223: | { | |
| 224: | SimpleHttpd2 aRequest = new SimpleHttpd2(listen.accept()); | |
| 225: | } | |
| 226: | } | |
| 227: | catch(java.io.IOException e) | |
| 228: | { | |
| 229: | System.err.println("Error: " + e.toString()); | |
| 230: | } | |
| 231: | } | |
| 232: | public void run() | |
| 233: | { | |
| 234: | try | |
| 235: | { | |
| 236: | setHeader("Server","SimpleHttpd2"); | |
| 237: | java.io.BufferedReader is = new java.io.BufferedReader(new java.io.InputStreamReader(s.getInputStream())); | |
| 238: | java.io.DataOutputStream os = new java.io.DataOutputStream(s.getOutputStream()); | |
| 239: | String request = is.readLine(); | |
| 240: | System.out.println("Request: " + request); | |
| 241: | java.util.StringTokenizer st = new java.util.StringTokenizer(request); | |
| 242: | if((st.countTokens() == 3) && st.nextToken().equals("GET")) | |
| 243: | { | |
| 244: | String filename = docRoot.getPath() + st.nextToken(); | |
| 245: | if(filename.endsWith("/") || filename.equals("")) | |
| 246: | filename += "index.html"; | |
| 247: | java.io.File file = new java.io.File(filename); | |
| 248: | if(file.getCanonicalPath().startsWith(canonicalDocRoot)) | |
| 249: | sendDocument(os,file); | |
| 250: | else | |
| 251: | sendError(SC_FORBIDDEN,os); | |
| 252: | } | |
| 253: | else | |
| 254: | { | |
| 255: | sendError(SC_BAD_REQUEST,os); | |
| 256: | } | |
| 257: | is.close(); | |
| 258: | os.close(); | |
| 259: | s.close(); | |
| 260: | } | |
| 261: | catch(java.io.IOException ioe) | |
| 262: | { | |
| 263: | System.err.println("Error: " + ioe.toString()); | |
| 264: | } | |
| 265: | } | |
| 266: | } |
This page was automatically generated by SharpDevelop.