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 "file_reply.h"
00025 #include "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 /** @class WebStaticRequestProcessor "static_processor.h"
00038  * Static file web processor.
00039  * This processor provides access to static files.
00040  * @author Tim Niemueller
00041  */
00042 
00043 /** Constructor.
00044  * @param baseurl Base URL where the static processor is mounted
00045  * @param htdocs_dir directory in the file system where to look for static files
00046  * @param logger logger
00047  */
00048 WebStaticRequestProcessor::WebStaticRequestProcessor(const char *baseurl,
00049                                                      const char *htdocs_dir,
00050                                                      fawkes::Logger *logger)
00051 {
00052   __logger         = logger;
00053   __baseurl        = strdup(baseurl);
00054   __baseurl_len    = strlen(__baseurl);
00055   __htdocs_dir     = strdup(htdocs_dir);
00056   __htdocs_dir_len = strlen(__htdocs_dir);
00057
00058 }
00059 
00060 /** Destructor. */
00061 WebStaticRequestProcessor::~WebStaticRequestProcessor()
00062 {
00063   free(__baseurl);
00064   free(__htdocs_dir);
00065 }
00066
00067
00068 WebReply *
00069 WebStaticRequestProcessor::process_request(const char *url,
00070                                            const char *method,
00071                                            const char *version,
00072                                            const char *upload_data,
00073                                            size_t *upload_data_size,
00074                                            void **session_data)
00075 {
00076   if ( strncmp(__baseurl, url, __baseurl_len) == 0 ) {
00077     // It is in our URL prefix range
00078     std::string file_path = std::string(__htdocs_dir) + std::string(url).substr(__baseurl_len);
00079
00080     char rf[PATH_MAX];
00081     char *realfile = realpath(file_path.c_str(), rf);
00082     if (! realfile ) {
00083       if (errno == ENOENT) {
00084         return new WebErrorPageReply(WebReply::HTTP_NOT_FOUND, "File not found");
00085       } else if (errno == EACCES) {
00086         return new WebErrorPageReply(WebReply::HTTP_FORBIDDEN, "Access forbidden");
00087       } else {
00088         char tmp[1024];
00089         strerror_r(errno, tmp, sizeof(tmp));
00090         return new WebErrorPageReply(WebReply::HTTP_INTERNAL_SERVER_ERROR,
00091                                  std::string("File access failed: ") + tmp);
00092       }
00093     } else {
00094       if (strncmp(realfile, __htdocs_dir, __htdocs_dir_len) == 0) {
00095         try {
00096           DynamicFileWebReply *freply = new DynamicFileWebReply(file_path.c_str());
00097           return freply;
00098         } catch (fawkes::Exception &e) {
00099           __logger->log_error("WebStaticReqProc", "Cannot fulfill request for file %s,"
00100                               " exception follows", url);
00101           __logger->log_error("WebStaticReqProc", e);
00102           return new WebErrorPageReply(WebReply::HTTP_INTERNAL_SERVER_ERROR,
00103                                    *(e.begin()));
00104         }
00105       } else {
00106         // Someone tries to trick us to give away files we don't want to give
00107         return new WebErrorPageReply(WebReply::HTTP_FORBIDDEN,
00108                                      "Access forbidden, breakout detected.");
00109       }
00110     }
00111   } else {
00112     // wrong base url, why the heck are we called!?
00113     __logger->log_error("WebStaticReqProc", "Called for invalid base url "
00114                         "(url: %s, baseurl: %s)", url, __baseurl);
00115     return NULL;
00116   }
00117 }