svvitch
digital signage player
D:/vs_workspace/switch_sf/src/svvitch/HTTPServerBase.cpp
Go to the documentation of this file.
00001 #include "HTTPServerBase.h"
00002 
00003 #include <Poco/File.h>
00004 #include <Poco/DOM/AutoPtr.h>
00005 #include <Poco/DOM/Document.h>
00006 #include <Poco/DOM/Element.h>
00007 #include <Poco/DOM/Text.h>
00008 #include <Poco/DOM/AutoPtr.h>
00009 #include <Poco/DOM/DOMWriter.h>
00010 #include <Poco/XML/XMLWriter.h>
00011 #include <Poco/format.h>
00012 #include <Poco/NumberFormatter.h>
00013 #include <Poco/RegularExpression.h>
00014 #include <Poco/Net/HTMLForm.h>
00015 #include <Poco/FileStream.h>
00016 #include <Poco/Path.h>
00017 #include <Poco/StreamCopier.h>
00018 
00019 #include "Common.h"
00020 #include "Utils.h"
00021 
00022 using Poco::File;
00023 using Poco::RegularExpression;
00024 using Poco::XML::Document;
00025 using Poco::XML::Element;
00026 using Poco::XML::Text;
00027 using Poco::XML::AutoPtr;
00028 using Poco::XML::DOMWriter;
00029 using Poco::XML::XMLWriter;
00030 
00031 
00032 BasePartHandler::BasePartHandler(): _log(Poco::Logger::get("")) {
00033     _log.debug("create BasePartHandler");
00034 }
00035 
00036 BasePartHandler::‾BasePartHandler() {
00037     _log.debug("release BasePartHandler");
00038 }
00039 
00040 void BasePartHandler::handlePart(const MessageHeader& header, std::istream& is) {
00041     string type = header.get("Content-Type", "(unspecified)");
00042     if (header.has("Content-Disposition")) {
00043         string contentDisposition = header["Content-Disposition"]; // UTF-8ベースのページであればUTF-8になるようです
00044         string disp;
00045         Poco::Net::NameValueCollection params;
00046         MessageHeader::splitParameters(contentDisposition, disp, params);
00047         string name = params.get("name", "unnamed"); // formプロパティ名
00048         string fileName = params.get(name, "unnamed");
00049         _log.information(Poco::format("contentDisposition[%s] name[%s]", contentDisposition, name));
00050         Poco::RegularExpression re(".*filename=¥"((.+¥¥¥¥)*(.+))¥".*");
00051         if (re.match(contentDisposition)) {
00052             // IEのフルパス対策
00053             fileName = contentDisposition;
00054             re.subst(fileName, "$3");
00055             _log.information("fileName: " + fileName);
00056         }
00057 
00058         File uploadDir("uploads");
00059         if (!uploadDir.exists()) uploadDir.createDirectories();
00060         File f(uploadDir.path() + "/" + fileName + ".part");
00061         if (f.exists()) f.remove();
00062         try {
00063             Poco::FileOutputStream os(f.path());
00064             int size = Poco::StreamCopier::copyStream(is, os, 512 * 1024);
00065             os.close();
00066             File rename(uploadDir.path() + "/" + fileName);
00067             if (rename.exists()) rename.remove();
00068             f.renameTo(rename.path());
00069             _log.information(Poco::format("file %s %s %d", fileName, type, size));
00070         } catch (Poco::PathSyntaxException& ex) {
00071             _log.warning(Poco::format("failed download path[%s] %s", fileName, ex.displayText()));
00072         } catch (Poco::FileException& ex) {
00073             _log.warning(Poco::format("failed download file[%s] %s", fileName, ex.displayText()));
00074         }
00075     }
00076 }
00077 
00078 
00079 
00080 BaseRequestHandler::BaseRequestHandler():
00081     _log(Poco::Logger::get("")), _request(NULL), _response(NULL), _form(NULL) {
00082     _log.debug("create BaseRequestHandler");
00083 }
00084 
00085 BaseRequestHandler::‾BaseRequestHandler() {
00086     SAFE_DELETE(_form);
00087     _log.debug("release BaseRequestHandler");
00088 }
00089 
00090 inline HTTPServerRequest& BaseRequestHandler::request() {
00091     return *_request;
00092 }
00093 
00094 
00095 inline HTTPServerResponse& BaseRequestHandler::response() {
00096     return *_response;
00097 }
00098 
00099 HTMLForm& BaseRequestHandler::form() {
00100     if (!_form) {
00101         BasePartHandler partHandler;
00102         _form = new HTMLForm(request(), request().stream(), partHandler);
00103     }
00104     return *_form;
00105 }
00106 
00107 void BaseRequestHandler::handleRequest(HTTPServerRequest& request, HTTPServerResponse& response) {
00108     _request  = &request;
00109     _response = &response;
00110 
00111     _log.debug(Poco::format("contenttype %s", request.getContentType()));
00112     _log.debug(Poco::format("encoding %s", request.getTransferEncoding()));
00113     doRequest();
00114 }
00115 
00116 void BaseRequestHandler::doRequest() {
00117 }
00118 
00119 bool BaseRequestHandler::sendFile(Path& path) {
00120     try {
00121         Poco::FileInputStream is(path.toString());
00122         if (is.good()) {
00123             string ext = path.getExtension();
00124             File f(path);
00125             File::FileSize length = f.getSize();
00126             response().setContentLength(static_cast<int>(length));
00127             if (ext == "png") {
00128                 response().setContentType("image/png");
00129             } else if (ext == "jpg" || ext == "jpeg") {
00130                 response().setContentType("image/jpeg");
00131             } else if (ext == "bmp") {
00132                 response().setContentType("image/bmp");
00133             } else if (ext == "gif") {
00134                 response().setContentType("image/gif");
00135             } else if (ext == "mpg" || ext == "mpeg") {
00136                 response().setContentType("video/mpeg");
00137             } else if (ext == "mp4" || ext == "f4v" || ext == "264") {
00138                 response().setContentType("video/mp4");
00139             } else if (ext == "wmv") {
00140                 response().setContentType("video/x-ms-wmv"); 
00141             } else if (ext == "mov") {
00142                 response().setContentType("video/quicktime");
00143             } else if (ext == "flv") {
00144                 response().setContentType("video/x-flv");
00145             } else if (ext == "swf") {
00146                 response().setContentType("application/x-shockwave-flash");
00147             } else if (ext == "pdf") {
00148                 response().setContentType("application/pdf");
00149             } else if (ext == "txt") {
00150                 response().setContentType("text/plain");
00151             } else if (ext == "htm" || ext == "html") {
00152                 response().setContentType("text/html");
00153             } else if (ext == "xml") {
00154                 response().setContentType("text/xml");
00155             } else {
00156                 response().setContentType("application/octet-stream");
00157             }
00158             response().setChunkedTransferEncoding(false);
00159             Poco::StreamCopier::copyStream(is, response().send(), 512 * 1024);
00160             is.close();
00161             return true;
00162         } else {
00163             throw Poco::OpenFileException(path.toString());
00164         }
00165     } catch (Poco::FileException& ex) {
00166         _log.warning(ex.displayText());
00167         //sendResponse(HTTPResponse::HTTP_NOT_FOUND, ex.displayText());
00168     } catch (...) {
00169         _log.warning(Poco::format("failed sendFile(%s)", path.toString()));
00170     }
00171     return false;
00172 }
00173 
00174 void BaseRequestHandler::sendJSONP(const string& functionName, const map<string, string>& json) {
00175     //response().setChunkedTransferEncoding(true);
00176     string userAgent = request().get("User-Agent", "");
00177     if (!userAgent.empty() && userAgent.find("MSIE") != string::npos) {
00178         response().setContentType("text/plain");
00179     } else {
00180         response().setContentType("text/javascript; charset=UTF-8");
00181     }
00182     response().add("CacheControl", "no-cache");
00183     response().add("Expires", "-1");
00184     if (functionName.empty()) {
00185         // コールバック関数名が無い場合はJSONとして送信
00186         response().send() << svvitch::formatJSON(json);
00187     } else {
00188         response().send() << Poco::format("%s(%s);", functionName, svvitch::formatJSON(json));
00189     }
00190 }
00191 
00192 void BaseRequestHandler::writeResult(const int code, const string& description) {
00193     AutoPtr<Document> doc = new Document();
00194     AutoPtr<Element> remote = doc->createElement("remote");
00195     doc->appendChild(remote);
00196     AutoPtr<Element> result = doc->createElement("result");
00197     result->setAttribute("code", Poco::format("%d", code));
00198     AutoPtr<Text> resultText = doc->createTextNode(description);
00199     result->appendChild(resultText);
00200     remote->appendChild(result);
00201     DOMWriter writer;
00202     writer.setNewLine("¥r¥n");
00203     writer.setOptions(XMLWriter::WRITE_XML_DECLARATION | XMLWriter::PRETTY_PRINT);
00204 
00205     //response().setChunkedTransferEncoding(true);
00206     response().setContentType("text/xml; charset=UTF-8");
00207     writer.writeNode(response().send(), doc);
00208 }
00209 
00210 void BaseRequestHandler::sendResponse(HTTPResponse::HTTPStatus status, const string& message) {
00211     response().setStatusAndReason(status, message);
00212 
00213     string statusCode(Poco::NumberFormatter::format(static_cast<int>(response().getStatus())));
00214     //response().setChunkedTransferEncoding(true);
00215     if (message.find("<html>") == string::npos) {
00216         response().setContentType("text/plain; charset=UTF-8");
00217         if (status == HTTPResponse::HTTP_OK) {
00218             response().send() << message << std::endl;
00219         } else {
00220             response().send() << Poco::format("%s - %s", statusCode, message) << std::endl;
00221         }
00222     } else {
00223         response().setContentType("text/html; charset=UTF-8");
00224         response().send() << message;
00225     }
00226     response().send().flush();
00227 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines