Fawkes API  Fawkes Development Version
static_processor.cpp
1 
2 /***************************************************************************
3  * static_processor.cpp - Web request processor for static files
4  *
5  * Created: Mon Oct 13 23:41:24 2008
6  * Copyright 2006-2008 Tim Niemueller [www.niemueller.de]
7  *
8  ****************************************************************************/
9 
10 /* This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU Library General Public License for more details.
19  *
20  * Read the full text in the LICENSE.GPL file in the doc directory.
21  */
22 
23 #include "static_processor.h"
24 #include <webview/file_reply.h>
25 #include <webview/error_reply.h>
26 
27 #include <core/exception.h>
28 #include <logging/logger.h>
29 
30 #include <cstring>
31 #include <cstdlib>
32 #include <string>
33 #include <unistd.h>
34 #include <cerrno>
35 #include <climits>
36 
37 using namespace fawkes;
38 
39 /** @class WebviewStaticRequestProcessor "static_processor.h"
40  * Static file web processor.
41  * This processor provides access to static files.
42  * @author Tim Niemueller
43  */
44 
45 /** Constructor.
46  * @param baseurl Base URL where the static processor is mounted
47  * @param htdocs_dirs directories in the file system where to look for static files
48  * @param logger logger
49  */
51  std::vector<const char *> htdocs_dirs,
52  fawkes::Logger *logger)
53 {
54  __logger = logger;
55  //store all htdocs_dirs
56  if(htdocs_dirs.size() <= 0)
57  {
58  throw Exception(errno, "htdocs_dirs is empty");
59  }
60  __htdocs_dirs = std::vector<char *>(htdocs_dirs.size());
61  __htdocs_dirs_len = std::vector<size_t>(htdocs_dirs.size());
62  for(unsigned int i = 0; i < htdocs_dirs.size(); i++)
63  {
64  char htdocs_rp[PATH_MAX];
65  if (realpath(htdocs_dirs[i], htdocs_rp) != NULL)
66  {
67  __htdocs_dirs[i] = strdup(htdocs_rp);
68  __htdocs_dirs_len[i] = strlen(__htdocs_dirs[i]);
69  } else
70  {
71  throw Exception(errno, "Failed to resolve htdocs path '%s'", htdocs_dirs[i]);
72  }
73  }
74 
75  __baseurl = strdup(baseurl);
76  __baseurl_len = strlen(__baseurl);
77 }
78 
79 /** Destructor. */
81 {
82  free(__baseurl);
83  for(unsigned int i = 0; i < __htdocs_dirs.size(); i++)
84  {
85  free(__htdocs_dirs[i]);
86  }
87 }
88 
89 
90 WebReply *
92 {
93  if ( strncmp(__baseurl, request->url().c_str(), __baseurl_len) == 0 ) {
94  // It is in our URL prefix range
95 
96  // Try all htdocs_dirs
97  for(unsigned int i = 0; i < __htdocs_dirs.size(); i++)
98  {
99  std::string file_path = std::string(__htdocs_dirs[i]) + request->url().substr(__baseurl_len);
100 
101  char rf[PATH_MAX];
102  char *realfile = realpath(file_path.c_str(), rf);
103 
104  if(realfile)
105  {
106  if (strncmp(realfile, __htdocs_dirs[i], __htdocs_dirs_len[i]) == 0) {
107  try {
108  DynamicFileWebReply *freply = new DynamicFileWebReply(file_path.c_str());
109  return freply;
110  } catch (fawkes::Exception &e) {
111  __logger->log_error("WebStaticReqProc",
112  "Cannot fulfill request for file %s,"
113  " exception follows", request->url().c_str());
114  __logger->log_error("WebStaticReqProc", e);
116  *(e.begin()));
117  }
118  } else {
119  // Someone tries to trick us to give away files we don't want to give
121  "Access forbidden, breakout detected.");
122  }
123  }
124  }
125  //file not found or access forbidden
126  if (errno == ENOENT) {
127  return new WebErrorPageReply(WebReply::HTTP_NOT_FOUND, "File not found");
128  } else if (errno == EACCES) {
129  return new WebErrorPageReply(WebReply::HTTP_FORBIDDEN, "Access forbidden");
130  } else {
131  char tmp[1024];
132  if (strerror_r(errno, tmp, sizeof(tmp)) == 0) {
134  "File access failed: %s", tmp);
135  } else {
137  "File access failed: Unknown error");
138  }
139  }
140  } else {
141  // wrong base url, why the heck are we called!?
142  __logger->log_error("WebStaticReqProc", "Called for invalid base url "
143  "(url: %s, baseurl: %s)", request->url().c_str(), __baseurl);
144  return NULL;
145  }
146 }
Dynamic raw file transfer reply.
Definition: file_reply.h:34
virtual fawkes::WebReply * process_request(const fawkes::WebRequest *request)
Process a request.
Fawkes library namespace.
Base class for exceptions in Fawkes.
Definition: exception.h:36
iterator begin()
Get iterator for messages.
Definition: exception.cpp:700
Web request meta data carrier.
Definition: request.h:42
WebviewStaticRequestProcessor(const char *baseurl, std::vector< const char *> htdocs_dir, fawkes::Logger *logger)
Constructor.
Basic web reply.
Definition: reply.h:36
virtual ~WebviewStaticRequestProcessor()
Destructor.
const std::string & url() const
Get URL.
Definition: request.h:69
Static error page reply.
Definition: error_reply.h:33
Interface for logging.
Definition: logger.h:34