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