svvitch
digital signage player
|
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 }