static int mod_http_request(calipso_request_t *request) { char date[64]; time_t tm; //calipso_pool_t *pool = calipso_request_get_pool(request); calipso_config_t * config = calipso_request_get_config(request); calipso_reply_t * reply = calipso_request_get_reply(request); int http_status = calipso_reply_get_status(reply); tm = calipso_request_get_time(request); cpo_http_time(date, &tm); calipso_reply_set_header_value(reply, "Date", "%s", date); calipso_reply_set_header_value(reply, "Server", "%s", calipso_get_server_string(config)); /* connection ? */ mod_http_set_keepalive(request); /* check pre errors from request/reply */ if ( calipso_http_status_is_error(http_status)) { TRACE("Pre http error %d\n", http_status); return (0); } /*XXX: HTTP 1.1 require host */ if (request->host == NULL) { calipso_reply_set_status(reply, HTTP_BAD_REQUEST); return (0); } calipso_reply_set_status(reply, HTTP_OK); return 1; }
static int mod_autoind_resource(calipso_request_t *request) { char *uri; calipso_reply_t *reply = calipso_request_get_reply(request); calipso_resource_t *resource = calipso_reply_get_resource(reply); int http_status = calipso_reply_get_status(reply); if (!calipso_resource_is_directory(resource) ||( calipso_http_status_is_error(http_status) && http_status != HTTP_FORBIDDEN )) { return NOK; } if(calipso_resource_is_directory(reply->resource)) { uri = calipso_request_get_uri(request); if( cpo_strlen( strrchr(uri,'/') ) == 1 ) { calipso_reply_set_status(reply, HTTP_OK); } else { calipso_reply_set_status(reply, HTTP_MOVED_PERMANENTLY); } mod_autoind_reply(request); } return OK; }
static int mod_http_set_if_modified_since(calipso_request_t *request, const char *http_date) { const char *modified_since = calipso_request_get_header_value(request, "if-modified-since"); if(modified_since && !strcmp(http_date , modified_since)) { calipso_reply_set_status(request->reply, HTTP_NOT_MODIFIED); return OK; } return NOK; }
static int calipso_request_read_body(calipso_request_t *request) { int reqlen = 0; calipso_client_t *client = request->client; calipso_socket_t *listener = client->listener; int max_size = request->in_filter->total_bytes + client->pending_bytes; if (max_size < REQUEST_BODY_SIZE_MAX) { char *buf = xmalloc(client->pending_bytes + 2); if (buf == NULL) { return calipso_reply_set_status(request->reply, HTTP_INTERNAL_SERVER_ERROR); } reqlen = listener->r(client, buf, client->pending_bytes); if (reqlen > 0) { assert(reqlen == (int)client->pending_bytes); chunks_add_tail(request->in_filter, buf, reqlen); } else if (reqlen < 0) { calipso_client_connection_error(client); reqlen = CPO_ERR; } free(buf); } else { return calipso_reply_set_status(request->reply, HTTP_REQUEST_ENTITY_TOO_LARGE); } return reqlen; }
static int mod_rewrite_request(calipso_request_t *request) { regex_t r; TRACE("Start\n"); compile_regex (&r, "^/dokuwiki/(data|conf|bin|inc)/"); if ( match(&r, request->uri) ) { //test just deny calipso_reply_set_status(request->reply, HTTP_FORBIDDEN); } regfree (& r); return CPO_OK; }
static int mod_http_partial_content(calipso_request_t *request, int fd) { /* HTTP_PARTIAL_CONTENT */ char *range; char *type; char *offset1; char *offset2; uintmax_t total_size; uintmax_t partial_size; range = calipso_request_get_header_value(request, "range"); if (range) { calipso_reply_set_status(request->reply, HTTP_PARTIAL_CONTENT); type = offset1 = offset2 = NULL; http_range_tokenize(range, &type, &offset1 , &offset2); TRACE("RANGE: %s\n", range); TRACE("type: %s offset1: %s offset2: %s \n", type, offset1, offset2); total_size = calipso_resource_get_size(request->reply->resource); partial_size = total_size - atol(offset1); TRACE("partial size: %llu ? total size %llu\n", partial_size, total_size); calipso_reply_set_header_value(request->reply, "content-range", "bytes=%s-%llu/%llu", offset1, total_size - 1, total_size); calipso_reply_set_header_value(request->reply, "Content-Length", "%llu", partial_size); /*set fd position */ (off_t)lseek(fd, (off_t)atoi(offset1), SEEK_SET); } /* !HTTP_PARTIAL_CONTENT*/ return OK; }
static int mod_autoind_make_index_table(calipso_reply_t * reply, const char *uri, int prop) { DIR *dir; struct stat sb; struct tm tm; char date[26]; struct dirent *ent; cpo_array_t arr; cpo_autoind_entry_t *entry; int i,dname_len; char *dname; const char * directory = calipso_resource_get_path(reply->resource); struct chunk_ctx * cb = chunk_ctx_alloc(reply->pool); arr.elem_size = sizeof(cpo_autoind_entry_t); arr.v = calloc(40 , sizeof(cpo_autoind_entry_t) ); arr.num = 0; arr.max = 32; if ((dir = opendir(directory)) == NULL) { calipso_reply_set_status(reply, HTTP_FORBIDDEN); return CPO_ERR; } while ((ent = readdir(dir)) != NULL) { if(!strncmp(ent->d_name, ".", 1)) { continue; } if( stat(ent->d_name , &sb) != -1) { entry = cpo_array_push(&arr); entry->name = cpo_pool_strdup(reply->pool, ent->d_name); entry->mtime = sb.st_mtime; entry->size = sb.st_size; entry->is_dir = S_ISDIR(sb.st_mode); } } closedir(dir); cpo_array_qsort(&arr, mod_autoindex_cmp_entries); chunk_ctx_printf(reply->pool, cb, indheadfoot[0], uri, uri); if(strcmp(uri,"/") ) { char dir[FILENAME_MAX]; strncpy(dir, uri, sizeof(dir)); chunk_ctx_printf(reply->pool, cb, "<a href=\"%s\">%s</a>%s %40s\n", dirname(dir), PARENT_DIR_NAME, add_space(PARENT_DIR_NAME, sizeof(PARENT_DIR_NAME), SPACE_CHAR), "-"); } for(i =0; i < arr.num; i++) { entry = cpo_array_get_at(&arr, i); dname_len = cpo_strlen(entry->name); if(ETALON_SPACE < dname_len) { int dots; dname = cpo_pool_strdup(reply->pool, entry->name); for(dots = 4; dots >= 1; dots--) { dname[ETALON_SPACE-dots] = ((dots == 1) ? '>' : '.'); } dname[ETALON_SPACE]='\0'; dname_len = ETALON_SPACE; } else { dname = entry->name; } if(dname) { cpo_gmtime(&tm, &entry->mtime); cpo_snprintf(date, sizeof(date), "%02d-%s-%d %02d:%02d ", tm.tm_mday, months[tm.tm_mon ], tm.tm_year, tm.tm_hour, tm.tm_min); if(entry->is_dir) { chunk_ctx_printf(reply->pool, cb, "<a href=\"%s%s/\">%s/</a>%s%10s %20s\n", uri, entry->name , dname, add_space(dname, dname_len, SPACE_CHAR), date, "-"); } else { chunk_ctx_printf(reply->pool, cb, "<a href=\"%s%s\">%s</a>%s %s %20.llu\n", uri, entry->name , dname, add_space(dname, dname_len ,SPACE_CHAR), date, (uintmax_t) entry->size); } //free dname } } chunk_ctx_printf(reply->pool, cb, indheadfoot[1], ""); CNUNKS_ADD_TAIL_CTX(reply->out_filter, cb); free(arr.v); return CPO_OK; }
static int mod_http_resource(calipso_request_t *request) { int fd; struct stat sb; char date[32]; calipso_reply_t *reply = calipso_request_get_reply(request); calipso_resource_t *resource = calipso_reply_get_resource(reply); const char *filename = calipso_resource_get_path(resource); int http_status = calipso_reply_get_status(reply); /* Set the default handler */ calipso_request_set_handler(request, mod_http_reply); if (calipso_http_status_is_error(http_status)) { TRACE(" http error %d\n", http_status); return (0); } //XXX: IsHandler AddHandelr ... if ( is_file_of(filename, ".php") ) { return (0); } /* check method */ if (strcasecmp(request->method, "GET") != 0 && strcasecmp(request->method, "HEAD") != 0) { calipso_reply_set_status(reply, HTTP_NOT_IMPLEMENTED); return (NOK); } /* stat the resource for other modules to know what type it is */ #ifdef _WIN32 remove_trailing_slash(filename); #endif if (stat(filename, &sb) < 0) { //TRACE("ERROR: %s %s\n", strerror(errno), filename); switch (errno) { case ENOTDIR: case ENOENT: calipso_reply_set_status(reply, HTTP_NOT_FOUND); break; case EACCES: calipso_reply_set_status(reply, HTTP_FORBIDDEN); break; case ENAMETOOLONG: calipso_reply_set_status(reply, HTTP_REQUEST_URI_TOO_LARGE); break; default: calipso_reply_set_status(reply, HTTP_INTERNAL_SERVER_ERROR); } return CPO_OK; } calipso_resource_set_stat(resource, &sb); cpo_http_time(date, &sb.st_mtime); /* modified_since */ if(USE_HEADER_MODFIED_SINCE && CPO_OK == mod_http_set_if_modified_since(request, date)) return OK; if (! calipso_resource_is_file(resource)) { /* default state mod_directory override */ if(!calipso_http_status_is_error(http_status)) { calipso_reply_set_status(reply, HTTP_FORBIDDEN); } return CPO_OK; } /*XXX: fcache needed */ fd = cpo_file_open(filename, 0); if(fd < 0 ){ calipso_reply_set_status(reply, HTTP_INTERNAL_SERVER_ERROR); return CPO_ERR; } calipso_reply_set_header_value(reply, "Accept-Ranges", "bytes"); if (!calipso_reply_get_header_value(reply, "content-range")) reply->content_length = calipso_resource_get_size(resource); //calipso_reply_set_header_value(reply, "Content-Length", "%llu", // calipso_resource_get_size(resource)); calipso_reply_set_header_value(reply, "Last-Modified", date); calipso_resource_set_file_descriptor(resource, fd); mod_http_partial_content(request, fd); return CPO_OK; }
static int mod_http_translate(calipso_request_t *request) { char *pathname = NULL; char *uri = NULL; char *documentroot = NULL; calipso_client_t *client = calipso_request_get_client(request); calipso_server_t *server = calipso_client_get_server(client); calipso_reply_t *reply = calipso_request_get_reply(request); calipso_resource_t *resource = calipso_reply_get_resource(reply); calipso_pool_t *pool = calipso_request_get_pool(request); int http_status = calipso_reply_get_status(reply); if ( calipso_http_status_is_error(http_status)) { TRACE(" http error %d\n", http_status); return (0); } if( remove_dots_from_uri_path(request->uri) == -1 ) { calipso_reply_set_status(reply, HTTP_BAD_REQUEST); return 0; } if (!cpo_uri_sanity_check( request->uri )) { calipso_reply_set_status(reply, HTTP_BAD_REQUEST); return 0; } uri = calipso_request_get_uri(request); //if (*uri != '/') { // calipso_reply_set_status(reply, HTTP_BAD_REQUEST); // return (0); //} documentroot = calipso_server_get_documentroot(server); if (!documentroot) { calipso_reply_set_status(reply, HTTP_BAD_REQUEST); return (0); } pathname = cpo_pool_malloc(pool, MAXPATHLEN); strlcpy(pathname, documentroot, MAXPATHLEN); cpo_uri_strdecode(uri, uri); if (strlcat(pathname, uri, MAXPATHLEN) >= MAXPATHLEN) { calipso_reply_set_status(reply, HTTP_REQUEST_URI_TOO_LARGE); return (0); } /* security chek */ //if (!cpo_uri_sanity_check( pathname )) { // calipso_reply_set_status(reply, HTTP_BAD_REQUEST); // return 0; //} /* decode string */ //cpo_uri_strdecode(pathname, pathname); calipso_resource_set_path(resource, pathname); return 1; }
static int request_parse_status_line(calipso_request_t *request, char *line) { char *method = NULL; char *uri = NULL; char *lastword = NULL; char *querystring = NULL; /*TODO: fix me */ /* Method */ method = line; calipso_request_set_method(request, method); while (*line && !isspace((int )*line) && ++line) ; if (*line == 0) return (1); *line++ = 0; uri = line; if (*uri == 0) return (1); lastword = NULL; while (*line) { if (isspace((int)*line) && *(line + 1) && !isspace((int )*(line + 1))) lastword = line + 1; ++line; } if (lastword) { *(lastword - 1) = 0; calipso_request_set_version(request, lastword); /* remove tailing spaces */ while (*lastword && ++lastword) ; --lastword; while (isspace((int)*lastword) && (*lastword-- = 0) == 0) ; } while (*uri && isspace((int )*uri) && ++uri) ; uri = cpo_strtok(uri, "?"); querystring = cpo_strtok( NULL, "?"); if (querystring) { char *new_querystring = cpo_pool_strdup(request->pool, querystring); calipso_request_set_querystring(request, new_querystring); } if (uri && *uri == '/') { char *new_uri = cpo_pool_strdup(request->pool, uri); calipso_request_set_uri(request, new_uri); /* remove tailing spaces */ /* while (*uri && ++uri) ; --uri; while (isspace((int)*uri) && (*uri-- = 0) == 0) ; */ } else { calipso_reply_set_status(request->reply, HTTP_BAD_REQUEST); } return (1); }
static int calipso_request_read_header(calipso_request_t *request) { int n; char p; char *end; calipso_client_t *client = request->client; chunk_buf_t * c = request->header_buf; calipso_socket_t *listener = calipso_client_get_listener(client); for (;;) { if ((INPUTBUFSZ - 1) <= c->size) { *(c->b + c->size) = '\0'; client->done = CPO_OK; return calipso_reply_set_status(request->reply, HTTP_REQUEST_URI_TOO_LARGE); } n = listener->r(client, &p, 1); if (n <= 0) { if (errno == EAGAIN) { TRACE("EAGAIN\n"); break; } else { *(c->b + c->size) = '\0'; cpo_log_error(calipso->log, "connection error %s", strerror(errno)); calipso_client_connection_error(client); return CPO_ERR; } } else { //printf("read_char 0x%X - %c\n", p, p); if (p < 0x9 || p > 0x7e) { *(c->b + c->size) = '\0'; client->done = CPO_OK; cpo_log_error(calipso->log, "Non printable char -> 0x%X", p); return calipso_reply_set_status(request->reply, HTTP_BAD_REQUEST); } *(c->b + c->size) = p; c->size++; *(c->b + c->size) = '\0'; } if (c->size > 4) { end = (c->b + (c->size - 4)); if (!strcmp(end, EOLCR EOLCR)) { return CPO_OK; } end = (c->b + (c->size - 2)); if (!strcmp(end, EOL EOL)) { return CPO_OK; } } } return NOK; }