static int uwsgi_wevdav_manage_delete(struct wsgi_request *wsgi_req) { char filename[PATH_MAX]; size_t filename_len = uwsgi_webdav_expand_path(wsgi_req, wsgi_req->path_info, wsgi_req->path_info_len, filename); // the collection does not exists if (!filename_len) { uwsgi_404(wsgi_req); return UWSGI_OK; } if (uwsgi_is_dir(filename)) { int ret = rmdir(filename); if (ret < 0) { if (errno == ENOTEMPTY) { if (uwsgi_webdav_massive_delete(filename)) { uwsgi_403(wsgi_req); return UWSGI_OK; } } else { uwsgi_403(wsgi_req); return UWSGI_OK; } } } else { if (unlink(filename)) { uwsgi_403(wsgi_req); return UWSGI_OK; } } uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6); return UWSGI_OK; }
static int uwsgi_wevdav_manage_put(struct wsgi_request *wsgi_req) { char filename[PATH_MAX]; size_t filename_len = uwsgi_webdav_expand_path(wsgi_req, wsgi_req->path_info, wsgi_req->path_info_len, filename); // the collection does not exist, search for the last / if (!filename_len) { filename_len = uwsgi_webdav_expand_fake_path(wsgi_req, wsgi_req->path_info, wsgi_req->path_info_len, filename); if (!filename_len) { uwsgi_response_prepare_headers(wsgi_req, "409 Conflict", 12); return UWSGI_OK; } } int fd = open(filename, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); if (fd < 0) { uwsgi_403(wsgi_req); return UWSGI_OK; } if (uwsgi_response_prepare_headers(wsgi_req, "201 Created", 11)) goto end; size_t remains = wsgi_req->post_cl; while(remains > 0) { ssize_t body_len = 0; char *body = uwsgi_request_body_read(wsgi_req, UMIN(remains, 32768) , &body_len); if (!body || body == uwsgi.empty) break; if (write(fd, body, body_len) != body_len) goto end; } end: close(fd); return UWSGI_OK; }
static int uwsgi_glusterfs_request(struct wsgi_request *wsgi_req) { char filename[PATH_MAX+1]; /* Standard GlusterFS request */ if (!wsgi_req->uh->pktsize) { uwsgi_log( "Empty GlusterFS request. skip.\n"); return -1; } if (uwsgi_parse_vars(wsgi_req)) { return -1; } // blocks empty paths if (wsgi_req->path_info_len == 0 || wsgi_req->path_info_len > PATH_MAX) { uwsgi_403(wsgi_req); return UWSGI_OK; } wsgi_req->app_id = uwsgi_get_app_id(wsgi_req, wsgi_req->appid, wsgi_req->appid_len, glusterfs_plugin.modifier1); if (wsgi_req->app_id == -1 && !uwsgi.no_default_app && uwsgi.default_app > -1) { if (uwsgi_apps[uwsgi.default_app].modifier1 == glusterfs_plugin.modifier1) { wsgi_req->app_id = uwsgi.default_app; } } if (wsgi_req->app_id == -1) { uwsgi_404(wsgi_req); return UWSGI_OK; } struct uwsgi_app *ua = &uwsgi_apps[wsgi_req->app_id]; memcpy(filename, wsgi_req->path_info, wsgi_req->path_info_len); filename[wsgi_req->path_info_len] = 0; glfs_fd_t *fd = glfs_open((glfs_t *) ua->interpreter, filename, O_RDONLY); if (!fd) { uwsgi_404(wsgi_req); return UWSGI_OK; } struct stat st; if (glfs_fstat(fd, &st)) { uwsgi_403(wsgi_req); return UWSGI_OK; } if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) goto end; size_t mime_type_len = 0; char *mime_type = uwsgi_get_mime_type(wsgi_req->path_info, wsgi_req->path_info_len, &mime_type_len); if (mime_type) { if (uwsgi_response_add_content_type(wsgi_req, mime_type, mime_type_len)) goto end; } if (uwsgi_response_add_last_modified(wsgi_req, (uint64_t) st.st_mtime)) goto end; if (uwsgi_response_add_content_length(wsgi_req, st.st_size)) goto end; // skip body on HEAD if (uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "HEAD", 4)) { size_t remains = st.st_size; while(remains > 0) { char buf[8192]; ssize_t rlen = glfs_read (fd, buf, UMIN(remains, 8192), 0); if (rlen <= 0) goto end; if (uwsgi_response_write_body_do(wsgi_req, buf, rlen)) goto end; remains -= rlen; } } end: glfs_close(fd); return UWSGI_OK; }
static int uwsgi_webdav_request(struct wsgi_request *wsgi_req) { if (!udav.mountpoints) { uwsgi_500(wsgi_req); return -1; } if (uwsgi_parse_vars(wsgi_req)) { return -1; } if (wsgi_req->path_info_len == 0) { uwsgi_403(wsgi_req); return UWSGI_OK; } wsgi_req->app_id = uwsgi_get_app_id(wsgi_req, wsgi_req->appid, wsgi_req->appid_len, webdav_plugin.modifier1); if (wsgi_req->app_id == -1) { uwsgi_403(wsgi_req); return UWSGI_OK; } // non lockables methods... if (!uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "OPTIONS", 7)) { return uwsgi_wevdav_manage_options(wsgi_req); } if (!uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "GET", 3)) { return uwsgi_wevdav_manage_get(wsgi_req, 1); } if (!uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "HEAD", 4)) { return uwsgi_wevdav_manage_get(wsgi_req, 0); } if (!uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "PROPFIND", 8)) { if (wsgi_req->post_cl > 0) { ssize_t body_len = 0; char *body = uwsgi_request_body_read(wsgi_req, wsgi_req->post_cl, &body_len); #ifdef UWSGI_DEBUG uwsgi_log("%.*s\n", body_len, body); #endif xmlDoc *doc = xmlReadMemory(body, body_len, NULL, NULL, 0); if (!doc) goto end; uwsgi_wevdav_manage_propfind(wsgi_req, doc); xmlFreeDoc(doc); } else { uwsgi_wevdav_manage_propfind(wsgi_req, NULL); } } if (!uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "REPORT", 6)) { if (wsgi_req->post_cl > 0) { ssize_t body_len = 0; char *body = uwsgi_request_body_read(wsgi_req, wsgi_req->post_cl, &body_len); #ifdef UWSGI_DEBUG uwsgi_log("%.*s\n", body_len, body); #endif xmlDoc *doc = xmlReadMemory(body, body_len, NULL, NULL, 0); if (!doc) goto end; xmlFreeDoc(doc); } } // lockable methods ... // check for locking if (!uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "PUT", 3)) { return uwsgi_wevdav_manage_put(wsgi_req); } if (!uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "DELETE", 6)) { return uwsgi_wevdav_manage_delete(wsgi_req); } if (!uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "MKCOL", 5)) { return uwsgi_wevdav_manage_mkcol(wsgi_req); } if (!uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "MKCALENDAR", 10)) { if (wsgi_req->post_cl == 0) goto end; ssize_t body_len = 0; char *body = uwsgi_request_body_read(wsgi_req, wsgi_req->post_cl, &body_len); #ifdef UWSGI_DEBUG uwsgi_log("%.*s\n", body_len, body); #endif xmlDoc *doc = xmlReadMemory(body, body_len, NULL, NULL, 0); if (!doc) goto end; uwsgi_wevdav_manage_mkcalendar(wsgi_req, doc); xmlFreeDoc(doc); } if (!uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "COPY", 4)) { return uwsgi_wevdav_manage_copy(wsgi_req); } if (!uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "MOVE", 4)) { return uwsgi_wevdav_manage_move(wsgi_req); } if (!uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "LOCK", 4)) { if (wsgi_req->post_cl > 0) { ssize_t body_len = 0; char *body = uwsgi_request_body_read(wsgi_req, wsgi_req->post_cl, &body_len); #ifdef UWSGI_DEBUG uwsgi_log("%.*s\n", body_len, body); #endif xmlDoc *doc = xmlReadMemory(body, body_len, NULL, NULL, 0); if (!doc) goto end; xmlFreeDoc(doc); } return uwsgi_wevdav_manage_lock(wsgi_req); } if (!uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "PROPPATCH", 9)) { if (wsgi_req->post_cl == 0) goto end; ssize_t body_len = 0; char *body = uwsgi_request_body_read(wsgi_req, wsgi_req->post_cl, &body_len); #ifdef UWSGI_DEBUG uwsgi_log("%.*s\n", body_len, body); #endif xmlDoc *doc = xmlReadMemory(body, body_len, NULL, NULL, 0); if (!doc) goto end; uwsgi_wevdav_manage_proppatch(wsgi_req, doc); xmlFreeDoc(doc); } end: return UWSGI_OK; }
static int uwsgi_wevdav_manage_get(struct wsgi_request *wsgi_req, int send_body) { char filename[PATH_MAX]; size_t filename_len = uwsgi_webdav_expand_path(wsgi_req, wsgi_req->path_info, wsgi_req->path_info_len, filename); if (!filename_len) { uwsgi_404(wsgi_req); return UWSGI_OK; } if (uwsgi_is_dir(filename)) { uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6); if (send_body) { uwsgi_webdav_dirlist(wsgi_req, filename); } return UWSGI_OK; } int fd = open(filename, O_RDONLY); if (fd < 0) { uwsgi_403(wsgi_req); return UWSGI_OK; } struct stat st; if (fstat(fd, &st)) { close(fd); uwsgi_403(wsgi_req); return UWSGI_OK; } if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) goto end; // add content_length if (uwsgi_response_add_content_length(wsgi_req, st.st_size)) goto end; // add last-modified if (uwsgi_response_add_last_modified(wsgi_req, st.st_mtime)) goto end; // add mime_type size_t mime_type_len = 0; char *mime_type = uwsgi_get_mime_type(filename, filename_len, &mime_type_len); if (mime_type) { if (uwsgi_response_add_content_type(wsgi_req, mime_type, mime_type_len)) goto end; } // add ETag (based on file mtime, not rock-solid, but good enough) char *etag = uwsgi_num2str(st.st_mtime); if (uwsgi_response_add_header(wsgi_req, "ETag", 4, etag, strlen(etag))) { free(etag); goto end; } free(etag); // start sending the file (note: we do not use sendfile() api, for being able to use caching and transformations) if (!send_body) goto end; // use a pretty big buffer (for performance reasons) char buf[32768]; size_t remains = st.st_size; while (remains > 0) { ssize_t rlen = read(fd, buf, UMIN(32768, remains)); if (rlen <= 0) { uwsgi_error("uwsgi_wevdav_manage_get/read()"); break; } remains -= rlen; if (uwsgi_response_write_body_do(wsgi_req, buf, rlen)) { break; } } end: close(fd); return UWSGI_OK; }
static int uwsgi_wevdav_manage_move(struct wsgi_request *wsgi_req) { char filename[PATH_MAX]; char d_filename[PATH_MAX]; size_t filename_len = uwsgi_webdav_expand_path(wsgi_req, wsgi_req->path_info, wsgi_req->path_info_len, filename); if (filename_len == 0) { uwsgi_404(wsgi_req); return UWSGI_OK; } uint16_t destination_len = 0; char *destination = uwsgi_get_var(wsgi_req, "HTTP_DESTINATION", 16, &destination_len); if (destination_len == 0) { uwsgi_403(wsgi_req); return UWSGI_OK; } uint16_t overwrite_len = 0; int can_overwrite = 1; char *overwrite = uwsgi_get_var(wsgi_req, "HTTP_OVERWRITE", 14, &overwrite_len); if (overwrite) { if (overwrite[0] == 'F') { can_overwrite = 0; } } uint16_t scheme_len = wsgi_req->scheme_len; if (wsgi_req->scheme_len == 0) { // http scheme_len = 4; } uint16_t skip = scheme_len + 3 + wsgi_req->host_len; int already_exists = 0; size_t d_filename_len = uwsgi_webdav_expand_path(wsgi_req, destination + skip, destination_len - skip, d_filename); if (d_filename_len > 0) { already_exists = 1; if (!can_overwrite) { uwsgi_response_prepare_headers(wsgi_req, "412 Precondition Failed", 23); return UWSGI_OK; } } else { d_filename_len = uwsgi_webdav_expand_fake_path(wsgi_req, destination + skip, destination_len - skip, d_filename); } if (d_filename_len == 0) { uwsgi_response_prepare_headers(wsgi_req, "409 Conflict", 12); return UWSGI_OK; } if (rename(filename, d_filename)) { uwsgi_403(wsgi_req); return UWSGI_OK; } if (already_exists) { uwsgi_response_prepare_headers(wsgi_req, "204 No Content", 14); } else { uwsgi_response_prepare_headers(wsgi_req, "201 Created", 11); } return UWSGI_OK; }
static int uwsgi_ssh_request(struct wsgi_request *wsgi_req) { #if !defined(UWSGI_PLUGIN_API) || UWSGI_PLUGIN_API == 1 if (!wsgi_req->uh->pktsize) #else if (!wsgi_req->len) #endif { uwsgi_log("[SSH] skipping empty request.\n"); return -1; } if (uwsgi_parse_vars(wsgi_req)) { uwsgi_error("uwsgi_ssh_request()/uwsgi_parse_vars()"); return -1; } if (wsgi_req->path_info_len == 0 || wsgi_req->path_info_len > PATH_MAX || wsgi_req->path_info[wsgi_req->path_info_len - 1] == '/') { uwsgi_403(wsgi_req); return UWSGI_OK; } wsgi_req->app_id = uwsgi_get_app_id(wsgi_req, wsgi_req->appid, wsgi_req->appid_len, libssh2_plugin.modifier1); if (wsgi_req->app_id == -1 && !uwsgi.no_default_app && uwsgi.default_app > -1) { if (uwsgi_apps[uwsgi.default_app].modifier1 == libssh2_plugin.modifier1) { wsgi_req->app_id = uwsgi.default_app; } } if (wsgi_req->app_id == -1) { uwsgi_404(wsgi_req); return UWSGI_OK; } struct uwsgi_app *ua = &uwsgi_apps[wsgi_req->app_id]; struct uwsgi_ssh_mountpoint *usm_list = (struct uwsgi_ssh_mountpoint *) ua->callable; char *complete_filepath = NULL; char *filepath = NULL; if (wsgi_req->path_info_len > ua->mountpoint_len && memcmp(wsgi_req->path_info, ua->mountpoint, ua->mountpoint_len) == 0) { filepath = uwsgi_strncopy( wsgi_req->path_info + ua->mountpoint_len, wsgi_req->path_info_len - ua->mountpoint_len ); } else { filepath = uwsgi_strncopy(wsgi_req->path_info, wsgi_req->path_info_len); } complete_filepath = uwsgi_concat2(usm_list->path, filepath); free(filepath); int return_status = 500; struct uwsgi_ssh_mountpoint *usm = usm_list; do { return_status = uwsgi_ssh_request_file( wsgi_req, complete_filepath, usm ); } while (return_status == 500 && ((usm = usm->next) != NULL)); free(complete_filepath); switch (return_status) { case 404: uwsgi_404(wsgi_req); break; case 500: default: uwsgi_500(wsgi_req); } return 0; }
static int uwsgi_rados_request(struct wsgi_request *wsgi_req) { char filename[PATH_MAX+1]; if (!wsgi_req->len) { uwsgi_log( "Empty request. skip.\n"); return -1; } if (uwsgi_parse_vars(wsgi_req)) { return -1; } // blocks empty paths if (wsgi_req->path_info_len == 0 || wsgi_req->path_info_len > PATH_MAX) { uwsgi_403(wsgi_req); return UWSGI_OK; } wsgi_req->app_id = uwsgi_get_app_id(wsgi_req, wsgi_req->appid, wsgi_req->appid_len, rados_plugin.modifier1); if (wsgi_req->app_id == -1 && !uwsgi.no_default_app && uwsgi.default_app > -1) { if (uwsgi_apps[uwsgi.default_app].modifier1 == rados_plugin.modifier1) { wsgi_req->app_id = uwsgi.default_app; } } if (wsgi_req->app_id == -1) { uwsgi_404(wsgi_req); return UWSGI_OK; } struct uwsgi_app *ua = &uwsgi_apps[wsgi_req->app_id]; if (wsgi_req->path_info_len > ua->mountpoint_len && memcmp(wsgi_req->path_info, ua->mountpoint, ua->mountpoint_len) == 0) { memcpy(filename, wsgi_req->path_info+ua->mountpoint_len, wsgi_req->path_info_len-ua->mountpoint_len); filename[wsgi_req->path_info_len-ua->mountpoint_len] = 0; } else { memcpy(filename, wsgi_req->path_info, wsgi_req->path_info_len); filename[wsgi_req->path_info_len] = 0; } // in multithread mode the memory is different (as we need a ctx for each thread) !!! rados_ioctx_t ctx; if (uwsgi.threads > 1) { rados_ioctx_t *ctxes = (rados_ioctx_t *) ua->responder0; ctx = ctxes[wsgi_req->async_id]; } else { ctx = (rados_ioctx_t) ua->responder0; } struct uwsgi_rados_mountpoint *urmp = (struct uwsgi_rados_mountpoint *) ua->responder1; uint64_t stat_size = 0; time_t stat_mtime = 0; struct uwsgi_rados_io *urio = &urados.urio[wsgi_req->async_id]; if (uwsgi.async > 0) { // no need to lock here (the rid protect us) if (pipe(urio->fds)) { uwsgi_error("uwsgi_rados_read_async()/pipe()"); uwsgi_500(wsgi_req); return UWSGI_OK; } } int ret = -1; int timeout = urmp->timeout ? urmp->timeout : urados.timeout; if (!uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "OPTIONS", 7)) { if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) goto end; if (uwsgi_response_add_header(wsgi_req, "Dav", 3, "1", 1)) goto end; struct uwsgi_buffer *ub_allow = uwsgi_buffer_new(64); if (uwsgi_buffer_append(ub_allow, "OPTIONS, GET, HEAD", 18)) { uwsgi_buffer_destroy(ub_allow); goto end; } if (urmp->allow_put) { if (uwsgi_buffer_append(ub_allow, ", PUT", 5)) { uwsgi_buffer_destroy(ub_allow); goto end; } } if (urmp->allow_delete) { if (uwsgi_buffer_append(ub_allow, ", DELETE", 8)) { uwsgi_buffer_destroy(ub_allow); goto end; } } if (urmp->allow_mkcol) { if (uwsgi_buffer_append(ub_allow, ", MKCOL", 7)) { uwsgi_buffer_destroy(ub_allow); goto end; } } if (urmp->allow_propfind) { if (uwsgi_buffer_append(ub_allow, ", PROPFIND", 10)) { uwsgi_buffer_destroy(ub_allow); goto end; } } uwsgi_response_add_header(wsgi_req, "Allow", 5, ub_allow->buf, ub_allow->pos); uwsgi_buffer_destroy(ub_allow); goto end; } // empty paths are mapped to propfind if (wsgi_req->path_info_len == 1 && wsgi_req->path_info[0] == '/') { if (urmp->allow_propfind && !uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "PROPFIND", 8)) { uwsgi_rados_propfind(wsgi_req, ctx, NULL, 0, 0, timeout); goto end; } uwsgi_405(wsgi_req); goto end; } // MKCOL does not require stat if (!uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "MKCOL", 5)) { if (!urmp->allow_mkcol) { uwsgi_405(wsgi_req); goto end; } ret = rados_pool_create(urmp->cluster, filename); if (ret < 0) { if (ret == -EEXIST) { uwsgi_405(wsgi_req); } else { uwsgi_500(wsgi_req); } goto end; } uwsgi_response_prepare_headers(wsgi_req, "201 Created", 11); goto end; } if (uwsgi.async > 0) { ret = uwsgi_rados_async_stat(urio, ctx, filename, &stat_size, &stat_mtime, timeout); } else { ret = rados_stat(ctx, filename, &stat_size, &stat_mtime); } // PUT AND MKCOL can be used for non-existent objects if (!uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "PUT", 3)) { if (!urmp->allow_put) { uwsgi_405(wsgi_req); goto end; } if (ret == 0) { if (uwsgi_rados_delete(wsgi_req, ctx, filename, timeout)) { uwsgi_500(wsgi_req); goto end; } } if (uwsgi_rados_put(wsgi_req, ctx, filename, urmp->put_buffer_size, timeout)) { uwsgi_500(wsgi_req); goto end; } uwsgi_response_prepare_headers(wsgi_req, "201 Created", 11); goto end; } else if (ret < 0) { if (ret == -ENOENT) uwsgi_404(wsgi_req); else uwsgi_403(wsgi_req); goto end; } if (!uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "DELETE", 6)) { if (!urmp->allow_delete) { uwsgi_405(wsgi_req); goto end; } if (uwsgi_rados_delete(wsgi_req, ctx, filename, timeout)) { uwsgi_403(wsgi_req); goto end; } uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6); goto end; } if (!uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "PROPFIND", 8)) { if (!urmp->allow_propfind) { uwsgi_405(wsgi_req); goto end; } uwsgi_rados_propfind(wsgi_req, ctx, filename, stat_size, stat_mtime, timeout); goto end; } if (uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "HEAD", 4) && uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "GET", 3)) { uwsgi_405(wsgi_req); goto end; } uint64_t offset = 0; uint64_t remains = stat_size; uwsgi_request_fix_range_for_size(wsgi_req, remains); switch (wsgi_req->range_parsed) { case UWSGI_RANGE_INVALID: if (uwsgi_response_prepare_headers(wsgi_req, "416 Requested Range Not Satisfiable", 35)) goto end; if (uwsgi_response_add_content_range(wsgi_req, -1, -1, stat_size)) goto end; return 0; case UWSGI_RANGE_VALID: offset = wsgi_req->range_from; remains = wsgi_req->range_to - wsgi_req->range_from + 1; if (uwsgi_response_prepare_headers(wsgi_req, "206 Partial Content", 19)) goto end; break; default: /* UWSGI_RANGE_NOT_PARSED */ if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) return -1; } size_t mime_type_len = 0; char *mime_type = uwsgi_get_mime_type(wsgi_req->path_info, wsgi_req->path_info_len, &mime_type_len); if (mime_type) { if (uwsgi_response_add_content_type(wsgi_req, mime_type, mime_type_len)) goto end; } if (uwsgi_response_add_last_modified(wsgi_req, (uint64_t) stat_mtime)) goto end; // set Content-Length to actual result size if (uwsgi_response_add_content_length(wsgi_req, remains)) goto end; if (wsgi_req->range_parsed == UWSGI_RANGE_VALID) { // here use the original size !!! if (uwsgi_response_add_content_range(wsgi_req, wsgi_req->range_from, wsgi_req->range_to, stat_size)) goto end; } // skip body on HEAD if (uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "HEAD", 4)) { if (uwsgi.async > 0) { if (uwsgi_rados_read_async(wsgi_req, ctx, filename, offset, remains, urmp->buffer_size, timeout)) goto end; } else { if (uwsgi_rados_read_sync(wsgi_req, ctx, filename, offset, remains, urmp->buffer_size)) goto end; } } end: if (uwsgi.async > 0) { close(urio->fds[0]); close(urio->fds[1]); } return UWSGI_OK; }
static int uwsgi_cgi_request(struct wsgi_request *wsgi_req) { char full_path[PATH_MAX]; char tmp_path[PATH_MAX]; struct stat cgi_stat; int need_free = 0; int is_a_file = 0; int discard_base = 0; size_t docroot_len = 0; size_t full_path_len = 0; char *helper = NULL; char *path_info = NULL; char *script_name = NULL; /* Standard CGI request */ if (!wsgi_req->uh->pktsize) { uwsgi_log("Empty CGI request. skip.\n"); return -1; } if (uwsgi_parse_vars(wsgi_req)) { return -1; } char *docroot = NULL; // check for file availability (and 'runnability') if (uc.from_docroot) { docroot = wsgi_req->document_root; docroot_len = wsgi_req->document_root_len; } else { docroot = uwsgi_cgi_get_docroot(wsgi_req->path_info, wsgi_req->path_info_len, &need_free, &is_a_file, &discard_base, &script_name); if (docroot) docroot_len = strlen(docroot); } if (docroot == NULL || docroot_len == 0) { uwsgi_404(wsgi_req); return UWSGI_OK; } memcpy(full_path, docroot, docroot_len); if (!is_a_file) { *(full_path+docroot_len) = '/'; *(full_path+docroot_len+1) = 0; if (uwsgi_cgi_walk(wsgi_req, full_path, docroot, docroot_len, discard_base, &path_info)) { if (need_free) free(docroot); return UWSGI_OK; } if (realpath(full_path, tmp_path) == NULL) { if (need_free) free(docroot); uwsgi_404(wsgi_req); return UWSGI_OK; } full_path_len = strlen(tmp_path); // add +1 to copy the null byte memcpy(full_path, tmp_path, full_path_len+1); if (uwsgi_starts_with(full_path, full_path_len, docroot, docroot_len)) { if (need_free) free(docroot); uwsgi_log("CGI security error: %s is not under %s\n", full_path, docroot); return -1; } } else { *(full_path+docroot_len) = 0; path_info = wsgi_req->path_info+discard_base; } if (stat(full_path, &cgi_stat)) { uwsgi_404(wsgi_req); if (need_free) free(docroot); return UWSGI_OK; } if (S_ISDIR(cgi_stat.st_mode)) { // add / to directories if (wsgi_req->path_info_len == 0 || (wsgi_req->path_info_len > 0 && wsgi_req->path_info[wsgi_req->path_info_len-1] != '/')) { uwsgi_redirect_to_slash(wsgi_req); if (need_free) free(docroot); return UWSGI_OK; } struct uwsgi_string_list *ci = uc.index; full_path[full_path_len] = '/'; full_path_len++; int found = 0; while(ci) { if (full_path_len + ci->len + 1 < PATH_MAX) { // add + 1 to ensure null byte memcpy(full_path+full_path_len, ci->value, ci->len + 1); if (!access(full_path, R_OK)) { found = 1; break; } } ci = ci->next; } if (!found) { uwsgi_404(wsgi_req); if (need_free) free(docroot); return UWSGI_OK; } } full_path_len = strlen(full_path); int cgi_allowed = 1; struct uwsgi_string_list *allowed = uc.allowed_ext; while(allowed) { cgi_allowed = 0; if (full_path_len >= allowed->len) { if (!uwsgi_strncmp(full_path+(full_path_len-allowed->len), allowed->len, allowed->value, allowed->len)) { cgi_allowed = 1; break; } } allowed = allowed->next; } if (!cgi_allowed) { uwsgi_403(wsgi_req); if (need_free) free(docroot); return UWSGI_OK; } // get the helper if (!is_a_file) { helper = uwsgi_cgi_get_helper(full_path); if (helper == NULL) { if (access(full_path, X_OK)) { uwsgi_error("access()"); uwsgi_403(wsgi_req); if (need_free) free(docroot); return UWSGI_OK; } } } int ret = uwsgi_cgi_run(wsgi_req, docroot, docroot_len, full_path, helper, path_info, script_name, is_a_file, discard_base); if (need_free) free(docroot); return ret; }
static int uwsgi_request_xslt(struct wsgi_request *wsgi_req) { char *xmlfile = NULL; char *output = NULL; int output_rlen = 0; char filename[PATH_MAX+1]; size_t filename_len = 0; char stylesheet[PATH_MAX+1]; size_t stylesheet_len = 0; char *params = NULL; if (uwsgi_parse_vars(wsgi_req)) { return -1; } // set default values if (!uxslt.content_type_len) { if (!uxslt.content_type) { uxslt.content_type = "text/html"; } uxslt.content_type_len = strlen(uxslt.content_type); } struct uwsgi_string_list *usl = uxslt.docroot; // first check for static docroots if (usl) { while(usl) { xmlfile = uwsgi_concat3n(usl->value, usl->len, "/", 1, wsgi_req->path_info, wsgi_req->path_info_len); if (uwsgi_is_file(xmlfile)) { break; } free(xmlfile); xmlfile = NULL; usl = usl->next; } } // fallback to DOCUMENT_ROOT else { if (wsgi_req->document_root_len == 0) { uwsgi_403(wsgi_req); return UWSGI_OK; } xmlfile = uwsgi_concat3n(wsgi_req->document_root, wsgi_req->document_root_len, "/", 1, wsgi_req->path_info, wsgi_req->path_info_len); } if (!xmlfile) { uwsgi_404(wsgi_req); return UWSGI_OK; } // we have the full path, check if it is valid if (!uwsgi_expand_path(xmlfile, strlen(xmlfile), filename)) { free(xmlfile); uwsgi_404(wsgi_req); return UWSGI_OK; } free(xmlfile); if (!uwsgi_is_file(filename)) { uwsgi_403(wsgi_req); return UWSGI_OK; } filename_len = strlen(filename); // now search for the xslt file int found = 0; // first check for specific vars usl = uxslt.var; while(usl) { uint16_t rlen; char *value = uwsgi_get_var(wsgi_req, usl->value, usl->len, &rlen); if (value) { memcpy(stylesheet, value, rlen); stylesheet[rlen] = 0; stylesheet_len = rlen; found = 1; break; } usl = usl->next; } if (found) goto apply; // then check for custom extensions if (uxslt.ext) { usl = uxslt.ext; while(usl) { char *tmp_path = uwsgi_concat2n(filename, filename_len, usl->value, usl->len); if (uwsgi_is_file(tmp_path)) { stylesheet_len = filename_len + usl->len; memcpy(stylesheet, tmp_path, stylesheet_len); stylesheet[stylesheet_len] = 0; free(tmp_path); found = 1; break; } free(tmp_path); usl = usl->next; } } // use default extensions .xsl/.xslt else { char *tmp_path = uwsgi_concat2n(filename, filename_len, ".xsl", 4); if (uwsgi_is_file(tmp_path)) { stylesheet_len = filename_len + 4; memcpy(stylesheet, tmp_path, stylesheet_len); stylesheet[stylesheet_len] = 0; free(tmp_path); goto apply; } free(tmp_path); tmp_path = uwsgi_concat2n(filename, filename_len, ".xslt", 5); if (uwsgi_is_file(tmp_path)) { stylesheet_len = filename_len + 5; memcpy(stylesheet, tmp_path, stylesheet_len); stylesheet[stylesheet_len] = 0; found = 1; } free(tmp_path); } if (found) goto apply; // finally check for static stylesheets usl = uxslt.stylesheet; while(usl) { if (uwsgi_is_file(usl->value)) { memcpy(stylesheet, usl->value, usl->len); stylesheet_len = usl->len; stylesheet[stylesheet_len] = 0; found = 1; break; } usl = usl->next; } if (found) goto apply; uwsgi_404(wsgi_req); return UWSGI_OK; apply: if (wsgi_req->query_string_len > 0) { params = uwsgi_concat2n(wsgi_req->query_string, wsgi_req->query_string_len, "", 0); } // we have both the file and the stylesheet, let's run the engine output = uwsgi_xslt_apply(filename, stylesheet, params, &output_rlen); if (params) free(params); if (!output) { uwsgi_500(wsgi_req); return UWSGI_OK; } // prepare headers if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) { uwsgi_500(wsgi_req); goto end; } // content_length if (uwsgi_response_add_content_length(wsgi_req, output_rlen)) { uwsgi_500(wsgi_req); goto end; } // content_type if (uwsgi_response_add_content_type(wsgi_req, uxslt.content_type, uxslt.content_type_len)) { uwsgi_500(wsgi_req); goto end; } uwsgi_response_write_body_do(wsgi_req, output, output_rlen); end: xmlFree(output); return UWSGI_OK; }
static int uwsgi_rados_request(struct wsgi_request *wsgi_req) { char filename[PATH_MAX+1]; if (!wsgi_req->uh->pktsize) { uwsgi_log( "Empty request. skip.\n"); return -1; } if (uwsgi_parse_vars(wsgi_req)) { return -1; } // blocks empty paths if (wsgi_req->path_info_len == 0 || wsgi_req->path_info_len > PATH_MAX) { uwsgi_403(wsgi_req); return UWSGI_OK; } wsgi_req->app_id = uwsgi_get_app_id(wsgi_req, wsgi_req->appid, wsgi_req->appid_len, rados_plugin.modifier1); if (wsgi_req->app_id == -1 && !uwsgi.no_default_app && uwsgi.default_app > -1) { if (uwsgi_apps[uwsgi.default_app].modifier1 == rados_plugin.modifier1) { wsgi_req->app_id = uwsgi.default_app; } } if (wsgi_req->app_id == -1) { uwsgi_404(wsgi_req); return UWSGI_OK; } struct uwsgi_app *ua = &uwsgi_apps[wsgi_req->app_id]; if (wsgi_req->path_info_len > ua->mountpoint_len && memcmp(wsgi_req->path_info, ua->mountpoint, ua->mountpoint_len) == 0) { memcpy(filename, wsgi_req->path_info+ua->mountpoint_len, wsgi_req->path_info_len-ua->mountpoint_len); } else { memcpy(filename, wsgi_req->path_info, wsgi_req->path_info_len); } filename[wsgi_req->path_info_len] = 0; struct { uint64_t size; time_t mtime; } st; rados_ioctx_t ctx = ua->responder1; int r = rados_stat(ctx, filename, &st.size, &st.mtime); if (r < 0) { if (r == -ENOENT) uwsgi_404(wsgi_req); else uwsgi_403(wsgi_req); return UWSGI_OK; } if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) goto end; size_t mime_type_len = 0; char *mime_type = uwsgi_get_mime_type(wsgi_req->path_info, wsgi_req->path_info_len, &mime_type_len); if (mime_type) { if (uwsgi_response_add_content_type(wsgi_req, mime_type, mime_type_len)) goto end; } if (uwsgi_response_add_last_modified(wsgi_req, (uint64_t) st.mtime)) goto end; if (uwsgi_response_add_content_length(wsgi_req, st.size)) goto end; // skip body on HEAD if (uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "HEAD", 4)) { size_t remains = st.size; if (uwsgi.async > 1) { if (uwsgi_rados_read_async(wsgi_req, ctx, filename, remains)) goto end; } else { if (uwsgi_rados_read_sync(wsgi_req, ctx, filename, remains)) goto end; } } end: return UWSGI_OK; }