↑ 1 #include <stdio.h>
↑ 2 #include <stdlib.h>
↑ 3 #include <fcntl.h>
↑ 4 #include <unistd.h>
↑ 5 #include "config.h"
↑ 6 #include "client.h"
↑ 7 #include "server.h"
↑ 8 #include "rh_string.h"
↑ 9 #include "handler.h"
↑ 10 #include "http_request.h"
↑ 11 #include "rh_chunk.h"
↑ 12
↑ 13 /*
↑ 14 *
↑ 15 * dir
↑ 16 *
↑ 17 *
↑ 18 * if the requested uri points to a directory but the uri
↑ 19 * has no "/" at the end, then a Location: is send
↑ 20 * with the correct uri.
↑ 21 *
↑ 22 * rewrites the filename if there are "DirectoryIndex" files defined
↑ 23 * in configuration and the filename exists and is a regular file.
↑ 24 *
↑ 25 * otherwise this handler returns FAILURE
↑ 26 *
↑ 27 */
↑ 28
↑ 29 static int add_missing_directory_slash (http_request_t *request)
↑ 30 {
↑ 31 const http_header_entry_t *server;
↑ 32 http_header_entry_t *location;
↑ 33
↑ 34 server = HTTP_HEADER_KEY_GET(&request->header_in, HOST);
↑ 35 if (NULL == server)
↑ 36 return -1;
↑ 37
↑ 38 request->header_out.status = 301;
↑ 39
↑ 40 HTTP_HEADER_KEY_CLEAR(&request->header_out, LOCATION);
↑ 41
↑ 42 location = HTTP_HEADER_KEY_GET(&request->header_out, LOCATION);
↑ 43
↑ 44 rh_buffer_append (&location->value, CONST_STR_LEN("http://"));
↑ 45
↑ 46 rh_buffer_append_encode_uri (&location->value,
↑ 47 server->value.data,
↑ 48 server->value.used );
↑ 49
↑ 50 rh_buffer_append_encode_uri (&location->value,
↑ 51 request->header_in.uri.path.data,
↑ 52 request->header_in.uri.path.used );
↑ 53
↑ 54 /* the "/" .. thats why all this stuff */
↑ 55 HTTP_HEADER_KEY_APPEND_CONST (&request->header_out, LOCATION, "/");
↑ 56
↑ 57 /* "?" query? */
↑ 58 if (URI_HAVE_QUERY(&request->header_in.uri)) {
↑ 59 HTTP_HEADER_KEY_APPEND_CONST (&request->header_out,
↑ 60 LOCATION, "?");
↑ 61
↑ 62 rh_buffer_append_encode_uri (&location->value,
↑ 63 request->header_in.uri.query.data,
↑ 64 request->header_in.uri.query.used );
↑ 65 }
↑ 66
↑ 67 return 0;
↑ 68 }
↑ 69
↑ 70
↑ 71 DECLARE_HANDLER_FUNCTION (dir,exec)
↑ 72 {
↑ 73 http_request_t *request;
↑ 74 const config_entry_t *config_entry;
↑ 75 const config_value_t *config_value;
↑ 76 size_t initial_length;
↑ 77 rh_buffer_t *filename;
↑ 78 int retcode;
↑ 79
↑ 80 #ifdef RHTTPD_DUMP_HANDLER_CALL
↑ 81 printf ("%s(%p)\n", __FUNCTION__, (void*)handler);
↑ 82 #endif
↑ 83
↑ 84 request = handler->request;
↑ 85
↑ 86
↑ 87 /*
↑ 88 * "fast" skipping this
↑ 89 *
↑ 90 */
↑ 91
↑ 92 if (RH_STAT_ISREG(request->st))
↑ 93 return HANDLER_SUCCESS;
↑ 94
↑ 95 if (!RH_STAT_ISDIR(request->st)) {
↑ 96 request->header_out.status = 403;
↑ 97 return HANDLER_FAILURE;
↑ 98 }
↑ 99
↑100 /*
↑101 * its a directory, try the index files
↑102 *
↑103 */
↑104
↑105 filename = &request->header_in.uri.filename;
↑106 initial_length = filename->used;
↑107
↑108 if (0 == initial_length)
↑109 return HANDLER_FAILURE;
↑110
↑111 /*
↑112 * did the uri ends with a '/'?
↑113 *
↑114 * if not: send Location: old_uri + '/'
↑115 *
↑116 */
↑117 if ('/' != filename->data[filename->used-1]) {
↑118 if (0 != add_missing_directory_slash (request))
↑119 return HANDLER_FAILURE;
↑120
↑121 return HANDLER_STOP;
↑122 }
↑123
↑124 config_entry = CONFIG_POP(request->client->server->config,
↑125 DIRECTORYINDEX);
↑126
↑127 if (NULL == config_entry)
↑128 return HANDLER_SUCCESS;
↑129
↑130 retcode = HANDLER_FAILURE;
↑131
↑132 CONFIG_ENTRY_FOREACH_VALUE(config_value, config_entry) {
↑133 filename->used = initial_length;
↑134
↑135 if (RH_BUFFER_APPEND_BUFFER(filename,&config_value->value))
↑136 break;
↑137
↑138 RH_BUFFER_NUL(filename);
↑139
↑140 if (0 != http_request_stat_symlink (request))
↑141 break;
↑142
↑143 if ( !RH_STAT_ISERROR(request->st) &&
↑144 RH_STAT_ISREG(request->st))
↑145 {
↑146 initial_length = filename->used;
↑147 retcode = HANDLER_SUCCESS;
↑148 break;
↑149 }
↑150 }
↑151
↑152 config_push (config_entry);
↑153
↑154 /* no "index.html" found */
↑155 if (HANDLER_SUCCESS != retcode) {
↑156 filename->used = initial_length;
↑157 RH_BUFFER_NUL(filename);
↑158 //request->header_out.status = 403;
↑159
↑160 retcode = HANDLER_SUCCESS;
↑161 }
↑162 #if 0
↑163 printf ("%s(): ret(%d) filename[%.*s]\n",
↑164 __FUNCTION__, retcode,
↑165 filename->used, filename->data);
↑166 #endif
↑167 return retcode;
↑168 }
↑169
↑170
↑171 DECLARE_HANDLER_BEGIN (dir, CONTENT)
↑172 .DECLARE_HANDLER_NULL (dir, setup),
↑173 .DECLARE_HANDLER_NULL (dir, init),
↑174 .DECLARE_HANDLER_NULL (dir, init_global),
↑175 .DECLARE_HANDLER_NULL (dir, free),
↑176 .DECLARE_HANDLER_NULL (dir, free_global),
↑177 .DECLARE_HANDLER_SYMBOL (dir, exec),
↑178 DECLARE_HANDLER_END
syntax highlighted by Code2HTML, v. 0.9.1