Fawkes API  Fawkes Development Version
static_processor.cpp
00001 
00002 /***************************************************************************
00003  *  static_processor.cpp - Web request processor for static files
00004  *
00005  *  Created: Mon Oct 13 23:41:24 2008
00006  *  Copyright  2006-2008  Tim Niemueller [www.niemueller.de]
00007  *
00008  ****************************************************************************/
00009 
00010 /*  This program is free software; you can redistribute it and/or modify
00011  *  it under the terms of the GNU General Public License as published by
00012  *  the Free Software Foundation; either version 2 of the License, or
00013  *  (at your option) any later version.
00014  *
00015  *  This program is distributed in the hope that it will be useful,
00016  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  *  GNU Library General Public License for more details.
00019  *
00020  *  Read the full text in the LICENSE.GPL file in the doc directory.
00021  */
00022 
00023 #include "static_processor.h"
00024 #include <webview/file_reply.h>
00025 #include <webview/error_reply.h>
00026 
00027 #include <core/exception.h>
00028 #include <utils/logging/logger.h>
00029 
00030 #include <cstring>
00031 #include <cstdlib>
00032 #include <string>
00033 #include <unistd.h>
00034 #include <cerrno>
00035 #include <climits>
00036 
00037 using namespace fawkes;
00038 
00039 /** @class WebviewStaticRequestProcessor "static_processor.h"
00040  * Static file web processor.
00041  * This processor provides access to static files.
00042  * @author Tim Niemueller
00043  */
00044 
00045 /** Constructor.
00046  * @param baseurl Base URL where the static processor is mounted
00047  * @param htdocs_dir directory in the file system where to look for static files
00048  * @param logger logger
00049  */
00050 WebviewStaticRequestProcessor::WebviewStaticRequestProcessor(const char *baseurl,
00051                                                      const char *htdocs_dir,
00052                                                      fawkes::Logger *logger)
00053 {
00054   __logger         = logger;
00055   __baseurl        = strdup(baseurl);
00056   __baseurl_len    = strlen(__baseurl);
00057   __htdocs_dir     = strdup(htdocs_dir);
00058   __htdocs_dir_len = strlen(__htdocs_dir);
00059 
00060 }
00061 
00062 /** Destructor. */
00063 WebviewStaticRequestProcessor::~WebviewStaticRequestProcessor()
00064 {
00065   free(__baseurl);
00066   free(__htdocs_dir);
00067 }
00068 
00069 
00070 WebReply *
00071 WebviewStaticRequestProcessor::process_request(const char *url,
00072                                            const char *method,
00073                                            const char *version,
00074                                            const char *upload_data,
00075                                            size_t *upload_data_size,
00076                                            void **session_data)
00077 {
00078   if ( strncmp(__baseurl, url, __baseurl_len) == 0 ) {
00079     // It is in our URL prefix range
00080     std::string file_path = std::string(__htdocs_dir) + std::string(url).substr(__baseurl_len);
00081 
00082     char rf[PATH_MAX];
00083     char *realfile = realpath(file_path.c_str(), rf);
00084     if (! realfile ) {
00085       if (errno == ENOENT) {
00086         return new WebErrorPageReply(WebReply::HTTP_NOT_FOUND, "File not found");
00087       } else if (errno == EACCES) {
00088         return new WebErrorPageReply(WebReply::HTTP_FORBIDDEN, "Access forbidden");
00089       } else {
00090         char tmp[1024];
00091         strerror_r(errno, tmp, sizeof(tmp));
00092         return new WebErrorPageReply(WebReply::HTTP_INTERNAL_SERVER_ERROR,
00093                                  std::string("File access failed: ") + tmp);
00094       }
00095     } else {
00096       if (strncmp(realfile, __htdocs_dir, __htdocs_dir_len) == 0) {
00097         try {
00098           DynamicFileWebReply *freply = new DynamicFileWebReply(file_path.c_str());
00099           return freply;
00100         } catch (fawkes::Exception &e) {
00101           __logger->log_error("WebStaticReqProc", "Cannot fulfill request for file %s,"
00102                               " exception follows", url);
00103           __logger->log_error("WebStaticReqProc", e);
00104           return new WebErrorPageReply(WebReply::HTTP_INTERNAL_SERVER_ERROR,
00105                                    *(e.begin()));
00106         }
00107       } else {
00108         // Someone tries to trick us to give away files we don't want to give
00109         return new WebErrorPageReply(WebReply::HTTP_FORBIDDEN,
00110                                      "Access forbidden, breakout detected.");
00111       }
00112     }
00113   } else {
00114     // wrong base url, why the heck are we called!?
00115     __logger->log_error("WebStaticReqProc", "Called for invalid base url "
00116                         "(url: %s, baseurl: %s)", url, __baseurl);
00117     return NULL;
00118   }
00119 }