// // DataRetriever.cpp // // $Id: //poco/Main/WebWidgets/src/DataRetriever.cpp#1 $ // // // Copyright (c) 2006, Applied Informatics Software Engineering GmbH. // and Contributors. // // Permission is hereby granted, free of charge, to any person or organization // obtaining a copy of the software and accompanying documentation covered by // this license (the "Software") to use, reproduce, display, distribute, // execute, and transmit the Software, and to prepare derivative works of the // Software, and to permit third-parties to whom the Software is furnished to // do so, all subject to the following: // // The copyright notices in the Software and this entire statement, including // the above license grant, this restriction and the following disclaimer, // must be included in all copies of the Software, in whole or in part, and // all derivative works of the Software, unless such copies or derivative // works are solely in the form of machine-executable object code generated by // a source language processor. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT // SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE // FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. // #include "Poco/WebWidgets/DataRetriever.h" #include "Poco/Net/HTTPServerRequest.h" #include "Poco/Net/HTTPServerResponse.h" #include "Poco/Logger.h" #include "Poco/StringTokenizer.h" #include "Poco/StreamCopier.h" #include namespace Poco { namespace WebWidgets { const std::string DataRetriever::INDEX_HTM("/index.htm"); const std::string DataRetriever::INDEX_HTML("/index.html"); const std::string DataRetriever::MSG_LISTING_NOT_ALLOWED("Not Allowed

Browsing of directories not allowed

"); const std::string DataRetriever::MSG_NOT_FOUND("Not Allowed

File Not Found

"); std::map DataRetriever::EXTENSIONMAPPING(DataRetriever::initExtensions()); DataRetriever::DataRetriever(const DataRetriever::Aliases& alias, Poco::Logger* pLogger): _aliases(alias), _pLogger(pLogger) { // a root must exist! poco_assert_dbg (_aliases.find("") != _aliases.end()); } DataRetriever::~DataRetriever() { } void DataRetriever::handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response) { std::string path = request.getURI(); if (path.empty() || path == "/") { path = INDEX_HTML; } if (!path.empty() && path[0] == '/') { path = path.substr(1); } path = resolveAliases(path); Poco::File aFile(path); if (!aFile.exists()) { if (_pLogger) _pLogger->warning("File not found: " + path); handleNotFound(response); } else if (aFile.isDirectory()) { if (_pLogger) _pLogger->warning("Illegal directory access: " + path); handleBrowsingNotAllowed(response); } else { sendFile(path, response); } } std::string DataRetriever::resolveAliases(const std::string& path) { Poco::StringTokenizer tok(path, "/", Poco::StringTokenizer::TOK_IGNORE_EMPTY | Poco::StringTokenizer::TOK_TRIM); // the path is either only / : tok.count == 0 // or /file : note if we have an alias for the same name we assume it is a directory that is requested // or /dir // or /dir/subdir/ Aliases::const_iterator itRoot = _aliases.find(""); if(tok.count() > 0) { Poco::StringTokenizer::Iterator itTok = tok.begin(); Poco::StringTokenizer::Iterator itTokEnd = tok.end(); Aliases::const_iterator it = _aliases.find(*tok.begin()); if (it != _aliases.end()) { // set the new root itRoot = it; // remove the resolved first path ++itTok; } Poco::Path aPath(itRoot->second); aPath.makeDirectory(); for (; itTok != itTokEnd; ++itTok) { aPath.pushDirectory(*itTok); } std::string result = aPath.toString(); if (path[path.size()-1] != '/' && path[path.size()-1] != '\\') return result.substr(0, result.size() - 1); return result; } return itRoot->second.toString()+path; } void DataRetriever::handleBrowsingNotAllowed(Poco::Net::HTTPServerResponse& response) { response.setChunkedTransferEncoding(true); response.setStatusAndReason(Poco::Net::HTTPResponse::HTTP_FORBIDDEN); std::ostream& out = response.send(); out << MSG_LISTING_NOT_ALLOWED; } void DataRetriever::handleNotFound(Poco::Net::HTTPServerResponse& response) { response.setChunkedTransferEncoding(true); response.setStatusAndReason(Poco::Net::HTTPResponse::HTTP_NOT_FOUND); std::ostream& out = response.send(); out << MSG_NOT_FOUND; } void DataRetriever::sendFile(const std::string& path, Poco::Net::HTTPServerResponse& response) { //Poco::Util::Application::instance().logger().information("Sent file: " + path); Poco::Path aPath(path); std::string ext = Poco::toLower(aPath.getExtension()); std::map::const_iterator it = EXTENSIONMAPPING.find(ext); if (it != EXTENSIONMAPPING.end()) { response.setContentType(it->second); } else response.setContentType("text/html"); response.setChunkedTransferEncoding(true); std::ifstream file(path.c_str(), std::ios::binary); std::ostream& out = response.send(); Poco::StreamCopier::copyStream(file, out); } std::map DataRetriever::initExtensions() { std::map ext; ext.insert(std::make_pair("", "text/html")); ext.insert(std::make_pair("htm", "text/html")); ext.insert(std::make_pair("html", "text/html")); ext.insert(std::make_pair("bmp", "image/bmp")); ext.insert(std::make_pair("gif", "image/gif")); ext.insert(std::make_pair("jpe", "image/jpeg")); ext.insert(std::make_pair("jpg", "image/jpeg")); ext.insert(std::make_pair("jpeg", "image/jpeg")); ext.insert(std::make_pair("log", "text/plain")); ext.insert(std::make_pair("txt", "text/plain")); ext.insert(std::make_pair("png", "image/png")); ext.insert(std::make_pair("ico", "image/x-icon")); ext.insert(std::make_pair("xml", "text/xml")); ext.insert(std::make_pair("css", "text/css")); ext.insert(std::make_pair("rss", "application/rss+xml")); ext.insert(std::make_pair("js", "text/javascript")); return ext; } } } // namespace Poco::WebWidgets