/* ==================================================================== * Copyright (c) 1997 Fons Rademakers. * Author: Fons Rademakers 15/1/97 */ #include "httpd.h" #include "http_config.h" #include "http_protocol.h" #include "http_log.h" #include "util_script.h" #include "http_main.h" #include "http_request.h" int root_handler (request_rec *r) { FILE *f; if (r->method_number != M_GET) return DECLINED; if (r->finfo.st_mode == 0) { log_reason("File does not exist", r->filename, r); return NOT_FOUND; } f = fopen (r->filename, "r"); if (f == NULL) { log_reason("file permissions deny server access", r->filename, r); return FORBIDDEN; } soft_timeout ("send", r); send_http_header (r); if (!r->header_only) { int offset, length, n, o = 0; char *buf; conn_rec *c = r->connection; /* rprintf(r, "args: %s\n", r->args); */ /* if no range is given return (could also send whole file) */ /* send_fd (f, r); */ if (!r->args || strlen(r->args) == 0 || strchr(r->args,':') == 0) { log_reason("no (valid) byte range specified", r->filename, r); return FORBIDDEN; } n = sscanf(r->args, "%d:%d", &offset, &length); /* some sanity checks */ if (n != 2 || offset < 0 || length <= 0) { log_reason("invalid offset or length specified", r->filename, r); /* rprintf(r, "args: %s, offset: %d, length: %d\n", r->args, offset, length); */ return FORBIDDEN; } if (fseek(f, offset, SEEK_SET) == -1) { log_reason("fseek failed", r->filename, r); return FORBIDDEN; } /* palloc'ed buffer will be cleaned up in case of time out */ buf = palloc(r->pool, length); while ((n = fread(buf, sizeof(char), length, f)) < 1 && ferror(f) && errno == EINTR) continue; while (n && !r->connection->aborted) { int w; w = bwrite(c->client, &buf[o], n); if (w <= 0) break; reset_timeout(r); /* reset timeout after successful write */ n -= w; o += w; } /* like SET_BYTES_SENT macro in http_protocol.c */ if (r->sent_bodyct) bgetopt (r->connection->client, BO_BYTECT, &r->bytes_sent); bflush(c->client); } fclose (f); return OK; } handler_rec root_handlers[] = { { "root-action", root_handler }, { NULL } }; module root_module = { STANDARD_MODULE_STUFF, NULL, /* initializer */ NULL, /* create per-directory config structure */ NULL, /* merge per-directory config structures */ NULL, /* create per-server config structure */ NULL, /* merge per-server config structures */ NULL, /* command table */ root_handlers, /* handlers */ NULL, /* translate_handler */ NULL, /* check_user_id */ NULL, /* check auth */ NULL, /* check access */ NULL, /* type_checker */ NULL, /* pre-run fixups */ NULL /* logger */ };