Files
poco/WebWidgets/src/DataRetriever.cpp
2008-05-12 13:12:39 +00:00

199 lines
6.5 KiB
C++

//
// 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 <fstream>
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("<HTML><HEAD><TITLE>Not Allowed</TITLE></HEAD><BODY><H1>Browsing of directories not allowed</H1></BODY></HTML>");
const std::string DataRetriever::MSG_NOT_FOUND("<HTML><HEAD><TITLE>Not Allowed</TITLE></HEAD><BODY><H1>File Not Found</H1></BODY></HTML>");
std::map<std::string, std::string> 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<std::string, std::string>::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<std::string, std::string> DataRetriever::initExtensions()
{
std::map<std::string, std::string> 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