/* * @(#)HTTPRequest.cpp * * This file is part of webCDwriter - Network CD/DVD Writing. * * Copyright (C) 2002-2005 Jörg P. M. Haeger * * webCDwriter is free software. See CDWserver.cpp for details. * * Jörg Haeger, 30.04.2002 */ #include "BufferedReader.h" #include "Error.h" #include "HTTPRequest.h" #include "Log.h" #include "StreamTokenizer.h" HTTPRequest::HTTPRequest(BufferedReader &reader) { contentLength = 0; ifModifiedSince = 0; StreamTokenizer tokenizer(reader); if (tokenizer.nextToken() != tokenizer.TT_WORD) throw new Exception("method expected"); method = tokenizer.sval; if (!method.equalsIgnoreCase("GET") && !method.equalsIgnoreCase("HEAD") && !method.equalsIgnoreCase("POST")) return; if (tokenizer.nextToken() != tokenizer.TT_WORD) throw new Exception("URI expected"); uri = tokenizer.sval; int res; while (true) { // deal with ":" in URIs res = tokenizer.nextToken(); if (res != tokenizer.TT_WORD || !tokenizer.sval.equals(":")) break; uri = uri + ":"; res = tokenizer.nextToken(); if (res != tokenizer.TT_WORD) break; uri = uri + tokenizer.sval; } if (res != tokenizer.TT_WORD) throw new Exception("protocol expected"); protocol = tokenizer.sval; if (tokenizer.nextToken() != tokenizer.TT_EOL) throw new Exception("EOL expected"); // parse fields while (1) { if (tokenizer.nextToken() == tokenizer.TT_EOL) break; String fieldName = tokenizer.sval; if (tokenizer.nextToken() != tokenizer.TT_WORD || !tokenizer.sval.equals(":")) throw new Exception(": expected"); String field = ""; if (tokenizer.nextToken() != tokenizer.TT_EOL) { field = field + tokenizer.sval; if (fieldName.equalsIgnoreCase("Host")) host = new String(field); int acceptLanguage = fieldName.equalsIgnoreCase( "Accept-Language"); if (acceptLanguage) languages.add(tokenizer.sval); else if (fieldName.equalsIgnoreCase("If-Modified-Since")) { if (tokenizer.sval.length() == 3) { // drop day of week if (tokenizer.nextToken() == tokenizer.TT_EOL) continue; field = field + " " + tokenizer.sval; if (tokenizer.nextToken() == tokenizer.TT_EOL) continue; field = field + " " + tokenizer.sval; } int day = Integer::getInt(tokenizer.sval.getBytes()); if (tokenizer.nextToken() == tokenizer.TT_EOL) continue; field = field + " " + tokenizer.sval; const char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; int month; for (month = 0; month < 11; month++) if (tokenizer.sval.equals(months[month])) break; if (tokenizer.nextToken() == tokenizer.TT_EOL) continue; field = field + " " + tokenizer.sval; int year = Integer::getInt(tokenizer.sval.getBytes()); if (tokenizer.nextToken() == tokenizer.TT_EOL) continue; field = field + " " + tokenizer.sval; int hour = Integer::getInt(tokenizer.sval.getBytes()); if (tokenizer.nextToken() == tokenizer.TT_EOL) continue; field = field + " " + tokenizer.sval; if (tokenizer.nextToken() == tokenizer.TT_EOL) continue; field = field + " " + tokenizer.sval; int min = Integer::getInt(tokenizer.sval.getBytes()); if (tokenizer.nextToken() == tokenizer.TT_EOL) continue; field = field + " " + tokenizer.sval; if (tokenizer.nextToken() == tokenizer.TT_EOL) continue; field = field + " " + tokenizer.sval; int sec = Integer::getInt(tokenizer.sval.getBytes()); if (year >= 1970) { int days0[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; int years = year - 1970; int days = years * 365 + (years + 1) / 4 + days0[month] + (month > 1 && (years + 2) % 4 == 0? 1 : 0) + (day - 1); ifModifiedSince = ((days * 24 + hour) * 60 + min) * 60 + sec; } /* struct tm tm; tm.tm_sec = sec; tm.tm_min = min; tm.tm_hour = hour; tm.tm_mday = day; tm.tm_mon = month; tm.tm_year = year - 1900; tm.tm_isdst = 0; int t = mktime(&tm); if (t != ifModifiedSince) log.debug("HTTPRequest", "ifModifiedSince %d %d %d", ifModifiedSince, t, ifModifiedSince - t); */ } int i = 0; while (tokenizer.nextToken() != tokenizer.TT_EOL) if (i++ < 1000) { field = field + " " + tokenizer.sval; if (acceptLanguage && !tokenizer.sval.equals(",")) languages.add(tokenizer.sval); } if (fieldName.equalsIgnoreCase("Content-Length")) contentLength = Integer::getInt(field.getBytes()); } log.debug("HTTPRequest", "- <%s> <%s>", fieldName.getBytes(), field.getBytes()); } } HTTPRequest::HTTPRequest(HTTPRequest *request) { method = request->method; uri = request->uri; protocol = request->protocol; host = request->host; languages = request->languages; contentLength = request->contentLength; ifModifiedSince = request->ifModifiedSince; delete request; } HTTPRequest::~HTTPRequest() { }