00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00023 #include "common.h"
00024
00025 #include <errno.h>
00026 #include <fcntl.h>
00027 #include <limits.h>
00028 #include <stdlib.h>
00029 #include <string.h>
00030 #include <sys/types.h>
00031 #include <sys/stat.h>
00032 #include <unistd.h>
00033
00034 #include "reqhandler_file.h"
00035
00036 #include "buffer.h"
00037 #include "conftable.h"
00038 #include "http.h"
00039 #include "logger.h"
00040 #include "mime.h"
00041 #include "misc.h"
00042 #include "xmalloc.h"
00043
00044
00046 #define ALLOW "GET HEAD"
00047
00048
00049
00050 struct ReqHandlerFile
00051 {
00052 HttpProtHandler parent;
00053
00054
00055 char *abs_path;
00056 int source;
00057 int status;
00058 size_t src_size;
00059 time_t mod_time;
00060 char *extension;
00061
00062 char *allow;
00063
00064
00065 struct Buffer buf;
00066 int data_pending;
00067 int error;
00068 };
00069
00070
00071
00072 int getAbsPath(char **abs_path, const char *path);
00073 int getSrcInfo(ReqHandlerFile this);
00074
00075
00076
00077
00078 static size_t send_buf_size;
00079
00080 static const char * doc_root;
00081 static size_t doc_root_len;
00082
00083 static const char * index_file;
00084 static size_t index_file_len;
00085
00086
00087 int rhfModulePreInit()
00088 {
00089
00090 send_buf_size = getEntryDeflUI(CONFENTRY_KEY_SENDBUFFER, STD_CONFENTRY_VAL_SENDBUFFER);
00091
00092 doc_root = getEntry(CONFENTRY_KEY_ROOTDIR);
00093 doc_root_len = strlen(doc_root);
00094
00095 index_file = getEntryDefl(CONFENTRY_KEY_INDEXHTML, STD_CONFENTRY_VAL_INDEXHTML);
00096 index_file_len = strlen(index_file);
00097
00098 return 0;
00099 }
00100
00101
00102 int rhfModuleTerminate()
00103 {
00104 return 0;
00105 }
00106
00107
00108
00109
00110 ReqHandlerFile rhfInit(HttpProtHandler parent, const char *path_buf, int change_path)
00111 {
00112 ReqHandlerFile this = (ReqHandlerFile) pd_malloc(sizeof(struct ReqHandlerFile));
00113
00114 memset(this, 0, sizeof(struct ReqHandlerFile));
00115 this->parent = parent;
00116 this->source = -1;
00117 this->allow = ALLOW;
00118
00119
00120 if (change_path)
00121 {
00122 if (getAbsPath(&this->abs_path, path_buf) == -1)
00123 this->error = errno;
00124 }
00125 else
00126 {
00127 char* new_buf = (char*) pd_malloc(strlen(path_buf)+1);
00128 strcpy(new_buf, path_buf);
00129 this->abs_path = new_buf;
00130 }
00131
00132 if (getSrcInfo(this) == 0)
00133 {
00134 this->source = open(this->abs_path, O_RDONLY);
00135 if (this->source == -1)
00136 {
00137 logerr(REQUEST_HANDLER, ERROR, errno, "could not open requested file");
00138 this->error = errno;
00139 }
00140 else
00141 {
00142
00143 if (this->src_size < send_buf_size)
00144 {
00145
00146
00147 this->buf.data = (char*) pd_malloc(MAX(this->src_size, 1));
00148 this->buf.len = this->src_size;
00149 }
00150 else
00151 {
00152 this->buf.data = (char*) pd_malloc(send_buf_size);
00153 this->buf.len = send_buf_size;
00154 }
00155 this->buf.pos = 0;
00156 this->data_pending = true;
00157 }
00158 }
00159 else if (this->error == 0)
00160 this->error = errno;
00161
00162 return this;
00163 }
00164
00166 int rhfReceive(__attribute__ ((unused)) ReqHandlerFile this,
00167 __attribute__ ((unused)) struct Buffer *buf )
00168 {
00169 return 0;
00170 }
00171
00172 int rhfSend(ReqHandlerFile this, struct Buffer **buf)
00173 {
00174 int cnt = 0;
00175 do {
00176 cnt = read(this->source, this->buf.data, this->buf.len);
00177 } while (cnt == -1 && errno == EINTR);
00178
00179 this->buf.len = cnt;
00180 this->buf.pos = 0;
00181 if (cnt <= 0)
00182 {
00183 int errno_bak = errno;
00184
00185 pd_free(this->buf.data);
00186 this->buf.data = NULL;
00187 this->data_pending = false;
00188
00189 if (cnt != 0)
00190 {
00191 logerr(REQUEST_HANDLER, ERROR, errno_bak, "data could not be read");
00192 this->error = errno;
00193 return -1;
00194 }
00195 }
00196 else
00197 this->data_pending = true;
00198
00199 *buf = &this->buf;
00200
00201
00202
00203 return 0;
00204 }
00205
00207 int rhfProcess( __attribute__ ((unused))ReqHandlerFile this)
00208 {
00209 return 0;
00210 }
00211
00212 int rhfIsDataPending(ReqHandlerFile this)
00213 {
00214 return (this->data_pending);
00215 }
00216
00217 int rhfTerminate(ReqHandlerFile this)
00218 {
00219 if (this == NULL) return -1;
00220
00221 pd_free(this->buf.data);
00222 this->buf.data = NULL;
00223 pd_free(this->abs_path);
00224
00225 if (this->source > 0)
00226 close(this->source);
00227
00228
00229 pd_free(this);
00230 return 0;
00231 }
00232
00233 int rhfGetError(ReqHandlerFile this)
00234 {
00235 return this->error;
00236 }
00237
00238
00239
00240
00241 size_t rhfGetSourceSize(ReqHandlerFile this)
00242 {
00243 return this->src_size;
00244 }
00245
00246 time_t rhfGetModTime(ReqHandlerFile this)
00247 {
00248 return this->mod_time;
00249 }
00250
00251 const char *rhfGetAllow(ReqHandlerFile this)
00252 {
00253 return this->allow;
00254 }
00255
00256
00257 const char* rhfGetContentType(ReqHandlerFile this)
00258 {
00259
00260 return mimeLookup(this->extension);
00261 }
00262
00266
00267
00278 int getAbsPath(char** abs_path, const char* path)
00279 {
00280 char *dir;
00281 int ret_val = 0;
00282
00283 if (doc_root == NULL || path == NULL)
00284 {
00285 errno = EBADF;
00286 return -1;
00287 }
00288
00289
00290 dir = (char*) pd_malloc(doc_root_len + strlen(path)+1);
00291 strcpy(dir, doc_root);
00292 strcpy(dir + doc_root_len, path);
00293
00294
00296 *abs_path = (char*)pd_malloc(PATH_MAX+1);
00297 if (realpath(dir,*abs_path) != NULL)
00298 {
00299 struct stat buf;
00300 if (stat(*abs_path, &buf) == 0)
00301 {
00302 if (S_ISDIR(buf.st_mode))
00303 {
00304 char *tmp;
00305 struct stat tbuf;
00306 size_t abs_path_len = strlen(*abs_path);
00307
00309
00310 (*abs_path)[abs_path_len++] = '/';
00311 (*abs_path)[abs_path_len] = '\0';
00312
00313 tmp = (char*)pd_malloc(abs_path_len + index_file_len + 1);
00314
00315 strcpy(tmp, *abs_path);
00316
00317 strcpy(tmp + abs_path_len, index_file);
00318
00319 errno = 0;
00320
00321 if (stat(tmp, &tbuf) != 0)
00322 {
00323 pd_free(dir);
00324 pd_free(tmp);
00325 pd_free(*abs_path); *abs_path = NULL;
00326 return -1;
00327 }
00328 pd_free(*abs_path);
00329 *abs_path = tmp;
00330 }
00331 }
00332 else
00333
00334 return -1;
00335
00336
00337 if (strncmp(*abs_path, doc_root, doc_root_len) == 0)
00338 ret_val = 0;
00339 else
00340 {
00341 pd_free(dir);
00342 pd_free(*abs_path); *abs_path = NULL;
00343 errno = EACCES;
00344 return -1;
00345 }
00346 }
00347 else
00348 {
00350
00351 int errno_orig = errno;
00352 pd_free(dir);
00353 pd_free(*abs_path); *abs_path = NULL;
00354 errno = errno_orig;
00355 return -1;
00356 }
00357
00358 pd_free(dir);
00359 return ret_val;
00360 }
00361
00362
00372 int getSrcInfo(ReqHandlerFile this)
00373 {
00374 struct stat buf;
00375 int len;
00376 int cnt;
00377
00378
00379 this->extension = this->abs_path;
00380
00381 if (this->abs_path == NULL) return -1;
00382
00383 len = strlen(this->abs_path);
00384
00385 if (stat(this->abs_path, &buf) == 0)
00386 {
00387 this->src_size = buf.st_size;
00388 this->mod_time = buf.st_mtime;
00389 }
00390 else
00391 {
00392 this->src_size = 0;
00393 this->mod_time = 0;
00394 return -1;
00395 }
00396
00397
00398
00399 for (cnt = 0; cnt < len; ++cnt)
00400 if (this->abs_path[cnt] == '.' || this->abs_path[cnt] == '/')
00401 this->extension = this->abs_path+cnt;
00402
00403
00404 if (this->extension > this->abs_path + len - 2)
00405 this->extension = this->abs_path;
00406 else
00407
00408 ++this->extension;
00409
00410 return 0;
00411 }
00412
00413