/* * @(#)HTTPResponse.cpp * * This file is part of webCDwriter - Network CD Writing. * * Copyright (C) 2002-2004 Jörg P. M. Haeger * * webCDwriter is free software. See CDWserver.cpp for details. * * Jörg Haeger, 30.04.2002 */ #include #include "Config.h" #include "File.h" #include "HTTPResponse.h" #include "Log.h" #include "PrintWriter.h" #include "Version.h" const char CRLF[] = "\r\n"; HTTPResponse::HTTPResponse() { setStatusCode(200); contentType = "application/octet-stream"; entityBytesTransferred = 0; lastModified = ""; } HTTPResponse::HTTPResponse(HTTPResponse *response) { *this = *response; delete response; } HTTPResponse::~HTTPResponse() { } String *operator+(const char *str1, String &str2) { String *str = new String(str1); *str + str2; return str; } String *HTTPResponse::getErrorHTML() { String str = ""; str = str + "\n" + "" + reasonPhrase + "\n" + "

Error " + statusCode + ": " + reasonPhrase + "

\n" + "\n"; return new String(str); } HTTPResponse *HTTPResponse::movedPermanently(String &location) { HTTPResponse *response = new HTTPResponse(); response->setStatusCode(301); response->setLocation(location); String entity = response->getErrorHTML(); String type = "text/html"; response->setEntity(entity, type); return response; } HTTPResponse *HTTPResponse::notFound() { HTTPResponse *response = new HTTPResponse(); response->setStatusCode(404); String entity = response->getErrorHTML(); String type = "text/html"; response->setEntity(entity, type); return response; } HTTPResponse *HTTPResponse::notImplemented() { HTTPResponse *response = new HTTPResponse(); response->setStatusCode(501); String entity = response->getErrorHTML(); String type = "text/html"; response->setEntity(entity, type); return response; } void HTTPResponse::setEntity(File &file, int ifModifiedSince) { if (file.exists() && ifModifiedSince >= file.lastModified()) { setStatusCode(304); contentLength = ""; contentType = ""; entityBody = ""; return; } entityStream = new FileInputStream(file); contentLength = "Content-Length: "; contentLength = contentLength + file.getSize() + CRLF; String type = ""; if (file.getPath().endsWith(".html")) type = "text/html"; else if (file.getPath().endsWith(".css")) type = "text/css"; else if (file.getPath().endsWith(".jar")) type = "application/x-jar"; else if (file.getPath().endsWith(".jnlp")) type = "application/x-java-jnlp-file"; else if (file.getPath().endsWith(".properties")) type = "text/plain"; else if (file.getPath().indexOf(".") < 0) type = "text/plain"; else type = config.getMimeType(file); contentType = "Content-Type: "; contentType = contentType + type + CRLF; time_t t = file.lastModified(); struct tm *tm = gmtime(&t); const char *days[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; const char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; lastModified = "Last-Modified: "; lastModified = lastModified + days[tm->tm_wday] + ", " + (tm->tm_mday < 10? "0": "") + tm->tm_mday + " " + months[tm->tm_mon] + " " + (1900 + tm->tm_year) + " " + (tm->tm_hour < 10? "0": "") + tm->tm_hour + ":" + (tm->tm_min < 10? "0": "") + tm->tm_min + ":" + (tm->tm_sec < 10? "0": "") + tm->tm_sec + " GMT" + CRLF; } void HTTPResponse::setEntity(String &body, String &type) { contentLength = "Content-Length: "; contentLength = contentLength + body.length() + CRLF; contentType = "Content-Type: "; contentType = contentType + type + CRLF; entityBody = body; } void HTTPResponse::setLocation(String &aLocation) { location = "Location: "; location = location + aLocation + CRLF; } void HTTPResponse::setStatusCode(int code) { statusCode = code; switch (code) { case 200: reasonPhrase = "OK"; break; case 301: reasonPhrase = "Moved Permanently"; break; case 304: reasonPhrase = "Not Modified"; break; case 404: reasonPhrase = "Not Found"; break; case 501: reasonPhrase = "Not Implemented"; break; } } void HTTPResponse::write(class PrintWriter &writer) { writeHead(writer); writer.write(entityBody); entityBytesTransferred = entityBody.length(); while (1) { char buf[4096]; int n = entityStream.read(buf, 0, sizeof buf); if (n <= 0) break; writer.write(buf, 0, n); entityBytesTransferred += n; } writer.flush(); } void HTTPResponse::writeHead(class PrintWriter &writer) { String s = ""; s = s + "HTTP/1.0 " + statusCode + " " + reasonPhrase + CRLF // Response-Header + location + "Server: " + Version.product + "/" + Version.version + CRLF + "Connection: close" + CRLF // Entity Header Fields + contentLength + contentType + lastModified + CRLF; writer.write(s); writer.flush(); }