00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <webview/request_dispatcher.h>
00024 #include <webview/request_processor.h>
00025 #include <webview/page_reply.h>
00026 #include <webview/error_reply.h>
00027
00028 #include <utils/misc/string_urlescape.h>
00029
00030 #include <sys/types.h>
00031 #include <sys/socket.h>
00032 #include <cstdarg>
00033 #include <microhttpd.h>
00034 #include <cstring>
00035 #include <cstdlib>
00036
00037 namespace fawkes {
00038 #if 0
00039 }
00040 #endif
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054 WebRequestDispatcher::WebRequestDispatcher(WebPageHeaderGenerator *headergen,
00055 WebPageFooterGenerator *footergen)
00056 {
00057 __page_header_generator = headergen;
00058 __page_footer_generator = footergen;
00059 }
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073 int
00074 WebRequestDispatcher::process_request_cb(void *callback_data,
00075 struct MHD_Connection * connection,
00076 const char *url,
00077 const char *method,
00078 const char *version,
00079 const char *upload_data,
00080 size_t *upload_data_size,
00081 void **session_data)
00082 {
00083 WebRequestDispatcher *rd = static_cast<WebRequestDispatcher *>(callback_data);
00084 return rd->process_request(connection, url, method, version,
00085 upload_data, upload_data_size, session_data);
00086 }
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097 #if MHD_VERSION >= 0x00090200
00098 static ssize_t
00099 dynamic_reply_data_cb(void *reply, uint64_t pos, char *buf, size_t max)
00100 #else
00101 static int
00102 dynamic_reply_data_cb(void *reply, uint64_t pos, char *buf, int max)
00103 #endif
00104 {
00105 DynamicWebReply *dreply = static_cast<DynamicWebReply *>(reply);
00106 return dreply->next_chunk(pos, buf, max);
00107 }
00108
00109
00110
00111
00112
00113 static void
00114 dynamic_reply_free_cb(void *reply)
00115 {
00116 DynamicWebReply *dreply = static_cast<DynamicWebReply *>(reply);
00117 delete dreply;
00118 }
00119
00120
00121
00122
00123
00124
00125
00126 int
00127 WebRequestDispatcher::queue_static_reply(struct MHD_Connection * connection,
00128 StaticWebReply *sreply)
00129 {
00130 struct MHD_Response *response;
00131 WebPageReply *wpreply = dynamic_cast<WebPageReply *>(sreply);
00132 if (wpreply) {
00133 wpreply->pack(__active_baseurl,
00134 __page_header_generator, __page_footer_generator);
00135 } else {
00136 sreply->pack();
00137 }
00138 if (sreply->body_length() > 0) {
00139 response = MHD_create_response_from_data(sreply->body_length(),
00140 (void*) sreply->body().c_str(),
00141 MHD_YES,
00142 MHD_YES);
00143 } else {
00144 response = MHD_create_response_from_data(0, (void*) "",
00145 MHD_NO,
00146 MHD_NO);
00147 }
00148
00149 const WebReply::HeaderMap &headers = sreply->headers();
00150 for (WebReply::HeaderMap::const_iterator i = headers.begin(); i != headers.end(); ++i) {
00151 MHD_add_response_header(response, i->first.c_str(), i->second.c_str());
00152 }
00153
00154 int rv = MHD_queue_response(connection, sreply->code(), response);
00155 MHD_destroy_response(response);
00156 return rv;
00157 }
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170 int
00171 WebRequestDispatcher::process_request(struct MHD_Connection * connection,
00172 const char *url,
00173 const char *method,
00174 const char *version,
00175 const char *upload_data,
00176 size_t *upload_data_size,
00177 void **session_data)
00178 {
00179 std::string surl = url;
00180 static int dummy;
00181 int ret;
00182
00183 if ((0 != strcmp(method, "GET")) && (0 != strcmp(method, "POST")))
00184 return MHD_NO;
00185
00186 WebRequestProcessor *proc = NULL;
00187 std::map<std::string, WebRequestProcessor *>::iterator __pit;
00188 for (__pit = __processors.begin(); (proc == NULL) && (__pit != __processors.end()); ++__pit) {
00189 if (surl.find(__pit->first) == 0) {
00190 __active_baseurl = __pit->first;
00191 proc = __pit->second;
00192 }
00193 }
00194
00195 if ( surl == "/" ) {
00196 if ( __startpage_processor ) {
00197 proc = __startpage_processor;
00198 } else {
00199 WebPageReply preply("Fawkes", "<h1>Welcome to Fawkes.</h1><hr />");
00200 ret = queue_static_reply(connection, &preply);
00201 }
00202 }
00203
00204 if (proc) {
00205 char *urlc = strdup(url);
00206 fawkes::hex_unescape(urlc);
00207 std::string urls = urlc;
00208 free(urlc);
00209
00210 if (! proc->handles_session_data()) {
00211 if ( *session_data == NULL) {
00212
00213
00214 *session_data = &dummy;
00215 return MHD_YES;
00216 }
00217 *session_data = NULL;
00218 } else {
00219 if ( *session_data == NULL) {
00220 WebReply *reply = proc->process_request(urls.c_str(), method, version, upload_data, upload_data_size, session_data);
00221 if ((reply != NULL) || (*session_data == NULL)) {
00222 return MHD_NO;
00223 } else {
00224 return MHD_YES;
00225 }
00226 }
00227 }
00228
00229 struct MHD_Response *response;
00230
00231
00232 WebReply *reply = proc->process_request(urls.c_str(), method, version, upload_data, upload_data_size, session_data);
00233
00234 if ( reply ) {
00235 StaticWebReply *sreply = dynamic_cast<StaticWebReply *>(reply);
00236 DynamicWebReply *dreply = dynamic_cast<DynamicWebReply *>(reply);
00237 if (sreply) {
00238 ret = queue_static_reply(connection, sreply);
00239 delete reply;
00240 } else if (dreply) {
00241 response = MHD_create_response_from_callback(dreply->size(),
00242 dreply->chunk_size(),
00243 dynamic_reply_data_cb,
00244 dreply,
00245 dynamic_reply_free_cb);
00246 ret = MHD_queue_response (connection, dreply->code(), response);
00247 MHD_destroy_response (response);
00248 } else {
00249 WebErrorPageReply ereply(WebReply::HTTP_INTERNAL_SERVER_ERROR);
00250 ret = queue_static_reply(connection, &ereply);
00251 delete reply;
00252 }
00253 } else {
00254 if (proc->handles_session_data()) {
00255 return MHD_YES;
00256 } else {
00257 WebErrorPageReply ereply(WebReply::HTTP_NOT_FOUND);
00258 ret = queue_static_reply(connection, &ereply);
00259 }
00260 }
00261 } else {
00262 WebErrorPageReply ereply(WebReply::HTTP_NOT_FOUND);
00263 ret = queue_static_reply(connection, &ereply);
00264 }
00265 return ret;
00266 }
00267
00268
00269
00270
00271
00272 void
00273 WebRequestDispatcher::add_processor(const char *url_prefix,
00274 WebRequestProcessor *processor)
00275 {
00276 if (std::string(url_prefix) == "/") {
00277 __startpage_processor = processor;
00278 } else {
00279 __processors[url_prefix] = processor;
00280 }
00281 }
00282
00283
00284
00285
00286
00287 void
00288 WebRequestDispatcher::remove_processor(const char *url_prefix)
00289 {
00290 if (std::string(url_prefix) == "/") {
00291 __startpage_processor = NULL;
00292 } else {
00293 __processors.erase(url_prefix);
00294 }
00295 }
00296
00297 }