Пример #1
0
static int uwsgi_ssh_request_file(
	struct wsgi_request *wsgi_req,
	char* filepath,
	struct uwsgi_ssh_mountpoint *usm
	) {

	int sock = -1;
	int return_status = 0;

	LIBSSH2_SESSION *session = NULL;
	if (uwsgi_init_ssh_session(usm, &sock, &session)) {
		uwsgi_log("[SSH] session initialization failed. Is the SSH server up?\n");
		return_status = 500;
		goto shutdown;
	}

	LIBSSH2_SFTP *sftp_session = NULL;
	do {
		sftp_session = libssh2_sftp_init(session);

		if (!sftp_session) {
			if ((libssh2_session_last_errno(session)) == LIBSSH2_ERROR_EAGAIN) {
				if (uwsgi_ssh_waitsocket(sock, session)) {
					return_status = 500;
					goto shutdown;
				}
			} else {
				uwsgi_error("uwsgi_ssh_request_file()/libssh2_sftp_init()");
				return_status = 500;
				goto shutdown;
			}
		}
	} while (!sftp_session);

	// Request file stats via SFTP
	LIBSSH2_SFTP_ATTRIBUTES file_attrs;
	int rc;
	while ((rc = libssh2_sftp_stat(sftp_session, filepath, &file_attrs)) == LIBSSH2_ERROR_EAGAIN) {
		if (uwsgi_ssh_waitsocket(sock, session)) {
			return_status = 500;
			goto shutdown;
		}
	}

	if (rc < 0) {
		// If it fails, requested file could not exist.
		if (rc == LIBSSH2_ERROR_SFTP_PROTOCOL && libssh2_sftp_last_error(sftp_session) == LIBSSH2_FX_NO_SUCH_FILE) {
				return_status = 404;
		} else {
			uwsgi_error("uwsgi_ssh_request_file()/libssh2_sftp_stat()");
			return_status = 500;
		}
		goto sftp_shutdown;
	}

	if (wsgi_req->if_modified_since_len) {
		time_t ims = uwsgi_parse_http_date(wsgi_req->if_modified_since, wsgi_req->if_modified_since_len);
		if (file_attrs.mtime <= (unsigned long)ims) {
			if (uwsgi_response_prepare_headers(wsgi_req, "304 Not Modified", 16) || uwsgi_response_write_headers_do(wsgi_req)) {
				uwsgi_error("uwsgi_parse_http_date()/uwsgi_response_prepare_headers(do)()");
			}
			return_status = 500;
			goto sftp_shutdown;
		}
	}

	if (uwsgi_response_prepare_headers(wsgi_req, "200", 3)) {
		uwsgi_error("uwsgi_ssh_request_file()/uwsgi_response_prepare_headers()");
		return_status = 500;
		goto sftp_shutdown;
	}

	if (uwsgi_response_add_content_length(wsgi_req, file_attrs.filesize)) {
		uwsgi_error("uwsgi_ssh_request_file()/uwsgi_response_add_content_length()");
		return_status = 500;
		goto sftp_shutdown;
	}

	if (uwsgi_response_add_last_modified(wsgi_req, file_attrs.mtime)) {
		uwsgi_error("uwsgi_ssh_request_file()/uwsgi_response_add_last_modified()");
		return_status = 500;
		goto sftp_shutdown;
	}

	size_t mime_type_len = 0;
	char *mime_type = uwsgi_get_mime_type(filepath, strlen(filepath), &mime_type_len);
	if (mime_type) {
		if (uwsgi_response_add_content_type(wsgi_req, mime_type, mime_type_len)) {
			uwsgi_error("uwsgi_ssh_request_file()/uwsgi_response_add_content_type()");
			// goto sftp_shutdown;
		}
	}

	// Request a file via SFTP
	LIBSSH2_SFTP_HANDLE *sftp_handle = NULL;
	do {
		sftp_handle = libssh2_sftp_open(sftp_session, filepath, LIBSSH2_FXF_READ, 0);

		if (!sftp_handle) {
			if (libssh2_session_last_errno(session) != LIBSSH2_ERROR_EAGAIN) {
				uwsgi_error("uwsgi_ssh_request_file()/libssh2_sftp_open()");
				return_status = 500;
				goto sftp_shutdown;
			} else {
				if (uwsgi_ssh_waitsocket(sock, session)) {
					return_status = 500;
					goto sftp_shutdown;
				}
			}
		}
	} while (!sftp_handle);

	size_t buffer_size = uwsgi.page_size;
	void *buffer = alloca(buffer_size);
	libssh2_uint64_t read_size = 0;

	while (read_size < file_attrs.filesize) {
		rc = libssh2_sftp_read(sftp_handle, buffer, buffer_size);

		if (rc == LIBSSH2_ERROR_EAGAIN) {
			if (uwsgi_ssh_waitsocket(sock, session)) {
				return_status = 500;
				goto sftp_shutdown;
			}
		} else if (rc < 0) {
			uwsgi_error("uwsgi_ssh_request_file()/libssh2_sftp_read()");
			break;
		} else {
			read_size += rc;
			if (uwsgi_response_write_body_do(wsgi_req, buffer, rc)) {
				uwsgi_error("uwsgi_ssh_request_file()/uwsgi_response_write_body_do()");
				break;
			}
		}
	}

	while ((rc = libssh2_sftp_close(sftp_handle)) == LIBSSH2_ERROR_EAGAIN) {
		if (uwsgi_ssh_waitsocket(sock, session)) {
			return_status = 500;
			goto sftp_shutdown;
		}
	};
	if (rc < 0) {
		uwsgi_error("uwsgi_ssh_request_file()/libssh2_sftp_close()");
	}

sftp_shutdown:

	while ((rc = libssh2_sftp_shutdown(sftp_session)) == LIBSSH2_ERROR_EAGAIN) {
		uwsgi_ssh_waitsocket(sock, session);
	}
	if (rc < 0) {
		uwsgi_error("uwsgi_ssh_request_file()/libssh2_sftp_shutdown()");
	}

shutdown:

	while (libssh2_session_disconnect(session, "Normal Shutdown, thank you!") == LIBSSH2_ERROR_EAGAIN) {
		uwsgi_ssh_waitsocket(sock, session);
	}
	libssh2_session_free(session);
	close(sock);
	libssh2_exit();
	return return_status;
}
Пример #2
0
int uwsgi_response_subhandler_web3(struct wsgi_request *wsgi_req) {

	PyObject *pychunk;

	// ok its a yield
	if (!wsgi_req->async_placeholder) {
		if (PyTuple_Check((PyObject *)wsgi_req->async_result)) {
			if (PyTuple_Size((PyObject *)wsgi_req->async_result) != 3) { 
				uwsgi_log("invalid Web3 response.\n"); 
				goto clear; 
			} 



			wsgi_req->async_placeholder = PyTuple_GetItem((PyObject *)wsgi_req->async_result, 0); 
			Py_INCREF((PyObject *)wsgi_req->async_placeholder);

			PyObject *spit_args = PyTuple_New(2);

			PyObject *status = PyTuple_GetItem((PyObject *)wsgi_req->async_result, 1);
			Py_INCREF(status);
			PyTuple_SetItem(spit_args, 0, status);

			PyObject *headers = PyTuple_GetItem((PyObject *)wsgi_req->async_result, 2);
			Py_INCREF(headers);
			PyTuple_SetItem(spit_args, 1, headers);

			if (py_uwsgi_spit(Py_None, spit_args) == NULL) { 
				PyErr_Print();
				Py_DECREF(spit_args);
				goto clear; 
			} 

			Py_DECREF(spit_args);

			if (PyString_Check((PyObject *)wsgi_req->async_placeholder)) {
				char *content = PyString_AsString(wsgi_req->async_placeholder);
				size_t content_len = PyString_Size(wsgi_req->async_placeholder);
				UWSGI_RELEASE_GIL
				uwsgi_response_write_body_do(wsgi_req, content, content_len);
				UWSGI_GET_GIL
				uwsgi_py_check_write_errors {
                        		uwsgi_py_write_exception(wsgi_req);
                		}
                		goto clear;
        		}

			PyObject *tmp = (PyObject *)wsgi_req->async_placeholder;

			wsgi_req->async_placeholder = PyObject_GetIter( (PyObject *)wsgi_req->async_placeholder );

			Py_DECREF(tmp);

			if (!wsgi_req->async_placeholder) {
				goto clear;
			}
			if (uwsgi.async > 0) {
				return UWSGI_AGAIN;
			}
		}
		else {
Пример #3
0
int uwsgi_routing_func_file(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {

	char buf[32768];
	struct stat st;
	int ret = UWSGI_ROUTE_BREAK;
	size_t remains = 0;

	struct uwsgi_router_file_conf *urfc = (struct uwsgi_router_file_conf *) ur->data2;

        char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
        uint16_t *subject_len = (uint16_t *)  (((char *)(wsgi_req))+ur->subject_len);

        struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urfc->filename, urfc->filename_len);
        if (!ub) return UWSGI_ROUTE_BREAK;

	int fd = open(ub->buf, O_RDONLY);
	if (fd < 0) {
		if (ur->custom)
			ret = UWSGI_ROUTE_NEXT;
		goto end; 
	}

	if (fstat(fd, &st)) {
		goto end2;
	}

	struct uwsgi_buffer *ub_s = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urfc->status, urfc->status_len);
        if (!ub_s) goto end2;

	if (urfc->no_headers) goto send;

	if (uwsgi_response_prepare_headers(wsgi_req, ub_s->buf, ub_s->pos)) {
		uwsgi_buffer_destroy(ub_s);
		goto end2;
	}
	uwsgi_buffer_destroy(ub_s);
	if (!urfc->no_cl) {
		if (uwsgi_response_add_content_length(wsgi_req, st.st_size)) goto end2;
	}
	if (urfc->mime) {
		size_t mime_type_len = 0;
		char *mime_type = uwsgi_get_mime_type(ub->buf, ub->pos, &mime_type_len);
		if (mime_type) {
			if (uwsgi_response_add_content_type(wsgi_req, mime_type, mime_type_len)) goto end2;
		}
		else {
			if (uwsgi_response_add_content_type(wsgi_req, urfc->content_type, urfc->content_type_len)) goto end2;
		}
	}
	else {
		if (uwsgi_response_add_content_type(wsgi_req, urfc->content_type, urfc->content_type_len)) goto end2;
	}

send:
	
	remains = st.st_size;
	while(remains) {
		ssize_t rlen = read(fd, buf, UMIN(32768, remains));
		if (rlen <= 0) goto end2;
		if (uwsgi_response_write_body_do(wsgi_req, buf, rlen)) goto end2;
		remains -= rlen;
	}
	
end2:
	close(fd);
end:
        uwsgi_buffer_destroy(ub);
        return ret;
}
Пример #4
0
Файл: cache.c Проект: Algy/uwsgi
// this function does not use the magic api internally to avoid too much copy
static void manage_magic_context(struct wsgi_request *wsgi_req, struct uwsgi_cache_magic_context *ucmc) {

	struct uwsgi_buffer *ub = NULL;
	struct uwsgi_cache *uc = uwsgi.caches;

	if (ucmc->cache_len > 0) {
		uc = uwsgi_cache_by_namelen(ucmc->cache, ucmc->cache_len);
		if (!uc) return;
	}

	if (!uc) return;

	// cache get
	if (!uwsgi_strncmp(ucmc->cmd, ucmc->cmd_len, "get", 3)) {
		uint64_t vallen = 0;
		uint64_t expires = 0;
		uwsgi_rlock(uc->lock);
		char *value = uwsgi_cache_get3(uc, ucmc->key, ucmc->key_len, &vallen, &expires);
		if (!value) {
			uwsgi_rwunlock(uc->lock);
			return;
		}
		// we are still locked !!!
		ub = uwsgi_buffer_new(uwsgi.page_size);
		ub->pos = 4;
		if (uwsgi_buffer_append_keyval(ub, "status", 6, "ok", 2)) goto error;
		if (uwsgi_buffer_append_keynum(ub, "size", 4, vallen)) goto error;
		if (expires) {
			if (uwsgi_buffer_append_keynum(ub, "expires", 7, expires)) goto error;
		}
		if (uwsgi_buffer_set_uh(ub, 111, 17)) goto error;
		if (uwsgi_buffer_append(ub, value, vallen)) goto error;
		// unlock !!!
		uwsgi_rwunlock(uc->lock);
		uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos);
		uwsgi_buffer_destroy(ub);
		return;	
	}

	// cache exists
	if (!uwsgi_strncmp(ucmc->cmd, ucmc->cmd_len, "exists", 6)) {
                uwsgi_rlock(uc->lock);
                if (!uwsgi_cache_exists2(uc, ucmc->key, ucmc->key_len)) {
                        uwsgi_rwunlock(uc->lock);
                        return;
                }
                // we are still locked !!!
                ub = uwsgi_buffer_new(uwsgi.page_size);
                ub->pos = 4;
                if (uwsgi_buffer_append_keyval(ub, "status", 6, "ok", 2)) goto error;
                if (uwsgi_buffer_set_uh(ub, 111, 17)) goto error;
                // unlock !!!
                uwsgi_rwunlock(uc->lock);
                uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos);
                uwsgi_buffer_destroy(ub);
                return;
        }

	// cache del
        if (!uwsgi_strncmp(ucmc->cmd, ucmc->cmd_len, "del", 3)) {
                uwsgi_wlock(uc->lock);
                if (uwsgi_cache_del2(uc, ucmc->key, ucmc->key_len, 0, 0)) {
                        uwsgi_rwunlock(uc->lock);
                        return;
                }
                // we are still locked !!!
                ub = uwsgi_buffer_new(uwsgi.page_size);
                ub->pos = 4;
                if (uwsgi_buffer_append_keyval(ub, "status", 6, "ok", 2)) goto error;
                if (uwsgi_buffer_set_uh(ub, 111, 17)) goto error;
                // unlock !!!
                uwsgi_rwunlock(uc->lock);
                uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos);
                uwsgi_buffer_destroy(ub);
                return;
        }

	// cache clear
        if (!uwsgi_strncmp(ucmc->cmd, ucmc->cmd_len, "clear", 5)) {
		uint64_t i;
		uwsgi_wlock(uc->lock);
		for (i = 1; i < uwsgi.caches->max_items; i++) {
			if (uwsgi_cache_del2(uc, NULL, 0, i, 0)) {
                                uwsgi_rwunlock(uc->lock);
                                return;
                        }	
		}
                // we are still locked !!!
                ub = uwsgi_buffer_new(uwsgi.page_size);
                ub->pos = 4;
                if (uwsgi_buffer_append_keyval(ub, "status", 6, "ok", 2)) goto error;
                if (uwsgi_buffer_set_uh(ub, 111, 17)) goto error;
                // unlock !!!
                uwsgi_rwunlock(uc->lock);
                uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos);
                uwsgi_buffer_destroy(ub);
                return;
        }

	// cache set
	if (!uwsgi_strncmp(ucmc->cmd, ucmc->cmd_len, "set", 3) || !uwsgi_strncmp(ucmc->cmd, ucmc->cmd_len, "update", 6)) {
		if (ucmc->size == 0 || ucmc->size > uc->max_item_size) return;
		wsgi_req->post_cl = ucmc->size;
		// read the value
		ssize_t rlen = 0;
		char *value = uwsgi_request_body_read(wsgi_req, ucmc->size, &rlen);
		if (rlen != (ssize_t) ucmc->size) return;
		// ok let's lock
		uwsgi_wlock(uc->lock);
		if (uwsgi_cache_set2(uc, ucmc->key, ucmc->key_len, value, ucmc->size, ucmc->expires, ucmc->cmd_len > 3 ? UWSGI_CACHE_FLAG_UPDATE : 0)) {
			uwsgi_rwunlock(uc->lock);
			return;
		}
		// we are still locked !!!
		ub = uwsgi_buffer_new(uwsgi.page_size);
		ub->pos = 4;
                if (uwsgi_buffer_append_keyval(ub, "status", 6, "ok", 2)) goto error;
		if (uwsgi_buffer_set_uh(ub, 111, 17)) goto error;
		// unlock !!!
		uwsgi_rwunlock(uc->lock);
		uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos);
                uwsgi_buffer_destroy(ub);
                return;
	}

	return;
error:
	uwsgi_rwunlock(uc->lock);
	uwsgi_buffer_destroy(ub);
}
Пример #5
0
int uwsgi_python_send_body(struct wsgi_request *wsgi_req, PyObject *chunk) {
	char *content = NULL;
	size_t content_len = 0;

#if defined(PYTHREE) || defined(Py_TPFLAGS_HAVE_NEWBUFFER)
	Py_buffer pbuf;
	int has_buffer = 0;
#endif

	if (!up.wsgi_accept_buffer && !wsgi_req->is_raw) goto strict;

#if defined(PYTHREE) || defined(Py_TPFLAGS_HAVE_NEWBUFFER)
	if (PyObject_CheckBuffer(chunk)) {
		if (!PyObject_GetBuffer(chunk, &pbuf, PyBUF_SIMPLE)) {
			content = (char *) pbuf.buf;
			content_len = (size_t) pbuf.len;
			has_buffer = 1;
			goto found;
		}
	}
#else
	if (PyObject_CheckReadBuffer(chunk)) {
#ifdef UWSGI_PYTHON_OLD
		int buffer_len = 0;
		if (!PyObject_AsCharBuffer(chunk, (const char **) &content, &buffer_len)) {
#else
		if (!PyObject_AsCharBuffer(chunk, (const char **) &content, (Py_ssize_t *) &content_len)) {
#endif
			PyErr_Clear();
			goto found;
		}
#ifdef UWSGI_PYTHON_OLD
		content_len = buffer_len;
#endif
	}
#endif

strict:
	// fallback
	if (PyString_Check(chunk)) {
               	content = PyString_AsString(chunk);
               	content_len = PyString_Size(chunk);
	}

found:
	if (content) {
                UWSGI_RELEASE_GIL
                uwsgi_response_write_body_do(wsgi_req, content, content_len);
                UWSGI_GET_GIL
#if defined(PYTHREE) || defined(Py_TPFLAGS_HAVE_NEWBUFFER)
		if (has_buffer) PyBuffer_Release(&pbuf);
#endif
                uwsgi_py_check_write_errors {
                       	uwsgi_py_write_exception(wsgi_req);
			return -1;
                }
		return 1;
	}
	return 0;
} 

/*
this is a hack for supporting non-file object passed to wsgi.file_wrapper
*/
static void uwsgi_python_consume_file_wrapper_read(struct wsgi_request *wsgi_req, PyObject *pychunk) {
	PyObject *read_method_args = NULL;
	PyObject *read_method = PyObject_GetAttrString(pychunk, "read");
	if (wsgi_req->sendfile_fd_chunk > 0) {
        	read_method_args = PyTuple_New(1);
		PyTuple_SetItem(read_method_args, 0, PyInt_FromLong(wsgi_req->sendfile_fd_chunk));
	}
	else {
        	read_method_args = PyTuple_New(0);
	}
	for(;;) {
        	PyObject *read_method_output = PyEval_CallObject(read_method, read_method_args);
                if (PyErr_Occurred()) {
                	uwsgi_manage_exception(wsgi_req, 0);
			break;
                }
		if (!read_method_output) break;
               	if (PyString_Check(read_method_output)) {
                     	char *content = PyString_AsString(read_method_output);
                        size_t content_len = PyString_Size(read_method_output);
			if (content_len == 0) {
                        	Py_DECREF(read_method_output);
				break;
			}
                        UWSGI_RELEASE_GIL
                        uwsgi_response_write_body_do(wsgi_req, content, content_len);
                        UWSGI_GET_GIL
                }
		Py_DECREF(read_method_output);
		if (wsgi_req->sendfile_fd_chunk == 0) break;
	}
        Py_DECREF(read_method_args);
        Py_DECREF(read_method);
}
Пример #6
0
static void uwsgi_rados_propfind(struct wsgi_request *wsgi_req, rados_ioctx_t ctx, char *key, uint64_t size, time_t mtime, int timeout) {
	// consume the body
	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;
		remains -= body_len;
	}

	if (uwsgi_response_prepare_headers(wsgi_req, "207 Multi-Status", 16)) return;
	if (uwsgi_response_add_content_type(wsgi_req, "text/xml; charset=\"utf-8\"", 25)) return;
	struct uwsgi_buffer *ub = uwsgi_webdav_multistatus_new();
	if (!ub) return;
	if (key) {
		size_t mime_type_len = 0;
        	char *mime_type = uwsgi_get_mime_type(key, strlen(key), &mime_type_len);
		char *slashed = uwsgi_concat2("/", key);
		if (uwsgi_webdav_propfind_item_add(ub, slashed, strlen(key)+1, size, mtime, mime_type, mime_type_len, NULL, 0, NULL, 0)) {
			free(slashed);
			goto end;
		}
		free(slashed);
		if (uwsgi_webdav_multistatus_close(ub)) goto end;
		uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos);
		goto end;
	}
	// request for /
	size_t depth = 0;
	uint16_t http_depth_len = 0;
        char *http_depth = uwsgi_get_var(wsgi_req, "HTTP_DEPTH", 10, &http_depth_len);
        if (http_depth) {
                depth = uwsgi_str_num(http_depth, http_depth_len);
        }

	if (depth == 0) {
		if (uwsgi_webdav_propfind_item_add(ub, "/", 1, 0, 0, NULL, 0, NULL, 0, NULL, 0)) {
                        goto end;
                }
                if (uwsgi_webdav_multistatus_close(ub)) goto end;
                uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos);
		goto end;
	}

	struct uwsgi_rados_io *urio = &urados.urio[wsgi_req->async_id];
	rados_list_ctx_t ctx_list;
	if (rados_objects_list_open(ctx, &ctx_list) < 0) {
		goto end;
	}

	char *entry = NULL;
	while(rados_objects_list_next(ctx_list, (const char **)&entry, NULL) == 0) {
		uint64_t stat_size = 0;
		time_t stat_mtime = 0;
		if (uwsgi.async > 0) {
        		if (uwsgi_rados_async_stat(urio, ctx, entry, &stat_size, &stat_mtime, timeout) < 0) goto end;
        	}
        	else {
                	if (rados_stat(ctx, entry, &stat_size, &stat_mtime) < 0) goto end;
        	}

		size_t mime_type_len = 0;
                char *mime_type = uwsgi_get_mime_type(entry, strlen(entry), &mime_type_len);
                char *slashed = uwsgi_concat2("/", entry);
                if (uwsgi_webdav_propfind_item_add(ub, slashed, strlen(entry)+1, stat_size, stat_mtime, mime_type, mime_type_len, NULL, 0, NULL, 0)) {
                        free(slashed);
                        goto end;
                }
                free(slashed);
                if (uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos)) goto end;
		// reset buffer;
		ub->pos = 0;
	}
	rados_objects_list_close(ctx_list);
        if (uwsgi_webdav_multistatus_close(ub)) goto end;
        uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos);

end:
	uwsgi_buffer_destroy(ub);
}
Пример #7
0
Файл: cache.c Проект: Algy/uwsgi
static int uwsgi_cache_request(struct wsgi_request *wsgi_req) {

        uint64_t vallen = 0;
        char *value;
        char *argv[3];
        uint16_t argvs[3];
        uint8_t argc = 0;

	// used for modifier2 17
	struct uwsgi_cache_magic_context ucmc;
	struct uwsgi_cache *uc = NULL;

        switch(wsgi_req->uh->modifier2) {
                case 0:
                        // get
                        if (wsgi_req->uh->_pktsize > 0) {
                                value = uwsgi_cache_magic_get(wsgi_req->buffer, wsgi_req->uh->_pktsize, &vallen, NULL, NULL);
                                if (value) {
                                        wsgi_req->uh->_pktsize = vallen;
					if (uwsgi_response_write_body_do(wsgi_req, (char *)&wsgi_req->uh, 4)) { free(value) ; return -1;}
					uwsgi_response_write_body_do(wsgi_req, value, vallen);
					free(value);
                                }
                        }
                        break;
                case 1:
                        // set
                        if (wsgi_req->uh->_pktsize > 0) {
				// max 3 items
                                argc = 3;
                                if (!uwsgi_parse_array(wsgi_req->buffer, wsgi_req->uh->_pktsize, argv, argvs, &argc)) {
                                        if (argc > 1) {
						uwsgi_cache_magic_set(argv[0], argvs[0], argv[1], argvs[1], 0, 0, NULL);
                                        }
                                }
                        }
                        break;
                case 2:
                        // del
                        if (wsgi_req->uh->_pktsize > 0) {
                                uwsgi_cache_magic_del(wsgi_req->buffer, wsgi_req->uh->_pktsize, NULL);
                        }
                        break;
                case 3:
                case 4:
                        // dict
                        if (wsgi_req->uh->_pktsize > 0) {
                                uwsgi_hooked_parse(wsgi_req->buffer, wsgi_req->uh->_pktsize, cache_simple_command, (void *) wsgi_req);
                        }
                        break;
                case 5:
                        // get (uwsgi + stream)
                        if (wsgi_req->uh->_pktsize > 0) {
                                value = uwsgi_cache_magic_get(wsgi_req->buffer, wsgi_req->uh->_pktsize, &vallen, NULL, NULL);
                                if (value) {
                                        wsgi_req->uh->_pktsize = 0;
                                        wsgi_req->uh->modifier2 = 1;
					if (uwsgi_response_write_body_do(wsgi_req, (char *)&wsgi_req->uh, 4)) { free(value) ;return -1;}
					uwsgi_response_write_body_do(wsgi_req, value, vallen);
					free(value);
                                }
                                else {
                                        wsgi_req->uh->_pktsize = 0;
                                        wsgi_req->uh->modifier2 = 0;
					uwsgi_response_write_body_do(wsgi_req, (char *)&wsgi_req->uh, 4);
					free(value);
                                }
                        }
                        break;
		case 6:
			// dump
			uc = uwsgi.caches;
			if (wsgi_req->uh->_pktsize > 0) {
				uc = uwsgi_cache_by_namelen(wsgi_req->buffer, wsgi_req->uh->_pktsize);
			}

			if (!uc) break;

			uwsgi_wlock(uc->lock);
			struct uwsgi_buffer *cache_dump = uwsgi_buffer_new(uwsgi.page_size + uc->filesize);
			cache_dump->pos = 4;
			if (uwsgi_buffer_append_keynum(cache_dump, "items", 5, uc->max_items)) {
				uwsgi_buffer_destroy(cache_dump);
				break;
			}
			if (uwsgi_buffer_append_keynum(cache_dump, "blocksize", 9, uc->blocksize)) {
				uwsgi_buffer_destroy(cache_dump);
				break;
			}

			if (uwsgi_buffer_set_uh(cache_dump, 111, 7)) {
				uwsgi_buffer_destroy(cache_dump);
				break;
			}

			if (uwsgi_buffer_append(cache_dump, (char *)uc->items, uc->filesize)) {
				uwsgi_buffer_destroy(cache_dump);
				break;
			}

			uwsgi_rwunlock(uc->lock);

			uwsgi_response_write_body_do(wsgi_req, cache_dump->buf, cache_dump->pos);
			uwsgi_buffer_destroy(cache_dump);
			break;
		case 17:
			if (wsgi_req->uh->_pktsize == 0) break;
			memset(&ucmc, 0, sizeof(struct uwsgi_cache_magic_context));
			if (uwsgi_hooked_parse(wsgi_req->buffer, wsgi_req->uh->_pktsize, uwsgi_cache_magic_context_hook, &ucmc)) {
				break;
			}
			manage_magic_context(wsgi_req, &ucmc);
			break;
		default:
			break;
        }

        return UWSGI_OK;
}
Пример #8
0
static int uwsgi_websockets_pong(struct wsgi_request *wsgi_req) {
        return uwsgi_response_write_body_do(wsgi_req, uwsgi.websockets_pong->buf, uwsgi.websockets_pong->pos);
}
Пример #9
0
static int uwsgi_websocket_send_do(struct wsgi_request *wsgi_req, char *msg, size_t len, uint8_t opcode) {
	struct uwsgi_buffer *ub = uwsgi_websocket_message(wsgi_req, msg, len, opcode);
	if (!ub) return -1;

	return uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos);
}
Пример #10
0
int uwsgi_response_subhandler_pump(struct wsgi_request *wsgi_req) {

	PyObject *pychunk;
	int i;

	char sc[4];

	// ok its a yield
	if (!wsgi_req->async_placeholder) {
		if (PyDict_Check((PyObject *)wsgi_req->async_result)) {


			PyObject *status = PyDict_GetItemString((PyObject *)wsgi_req->async_result, "status");
			if (!status) {
				uwsgi_log("invalid Pump response (status code).\n"); 
				goto clear; 
			}

			PyObject *headers = PyDict_GetItemString((PyObject *)wsgi_req->async_result, "headers");
			if (!headers) {
				uwsgi_log("invalid Pump response (headers).\n"); 
				goto clear; 
			}


			wsgi_req->async_placeholder =  PyDict_GetItemString((PyObject *)wsgi_req->async_result, "body");
			if (!wsgi_req->async_placeholder) {
				uwsgi_log("invalid Pump response (body).\n"); 
				goto clear; 
			}

			// get the status code
			if (!PyInt_Check(status)) {
				uwsgi_log("invalid Pump response (status code).\n"); 
				goto clear; 
			}

			if (uwsgi_num2str2n(PyInt_AsLong(status), sc, 4) != 3) {
				uwsgi_log("invalid Pump response (status code).\n"); 
				goto clear; 
			}

			if (uwsgi_response_prepare_headers(wsgi_req, sc, 3)) {
				uwsgi_log("unable to prepare response headers\n");
			}

			PyObject *hhkey, *hhvalue;
#ifdef UWSGI_PYTHON_OLD
			int hhpos = 0;
#else
			Py_ssize_t hhpos = 0;
#endif
			while (PyDict_Next(headers, &hhpos, &hhkey, &hhvalue)) {
				if (!PyString_Check(hhkey)) continue;

				char *k = PyString_AsString(hhkey);
				size_t kl = PyString_Size(hhkey);	
				k[0] = toupper((int) k[0]);

				if (PyList_Check(hhvalue)) {
					for(i=0;i<PyList_Size(hhvalue);i++) {
						PyObject *item = PyList_GetItem(hhvalue, i);
						if (PyString_Check(item)) {
							if (uwsgi_response_add_header(wsgi_req, k, kl, PyString_AsString(item), PyString_Size(item))) goto clear;
						}
					}	
				}
				else if (PyString_Check(hhvalue)) {
					if (uwsgi_response_add_header(wsgi_req, k, kl, PyString_AsString(hhvalue), PyString_Size(hhvalue))) goto clear;
				}
			}

			Py_INCREF((PyObject *)wsgi_req->async_placeholder);

			if (PyString_Check((PyObject *)wsgi_req->async_placeholder)) {
				UWSGI_RELEASE_GIL
				uwsgi_response_write_body_do(wsgi_req, PyString_AsString(wsgi_req->async_placeholder), PyString_Size(wsgi_req->async_placeholder));
				UWSGI_GET_GIL
				uwsgi_py_check_write_errors {
                                        uwsgi_py_write_exception(wsgi_req);
                                }
                		goto clear;
        		}
#ifdef PYTHREE
			else if ((wsgi_req->sendfile_fd = PyObject_AsFileDescriptor((PyObject *)wsgi_req->async_placeholder)) > -1) {
Пример #11
0
static int uwsgi_lua_request(struct wsgi_request *wsgi_req) {

	int i;
	const char *http, *http2;
	size_t slen, slen2;
	char *ptrbuf;
	lua_State *L = ulua.L[wsgi_req->async_id];

	if (wsgi_req->async_status == UWSGI_AGAIN) {
		if ((i = lua_pcall(L, 0, 1, 0)) == 0) {
			if (lua_type(L, -1) == LUA_TSTRING) {
				http = lua_tolstring(L, -1, &slen);
				uwsgi_response_write_body_do(wsgi_req, (char *)http, slen);
			}
			lua_pop(L, 1);
			lua_pushvalue(L, -1);
			return UWSGI_AGAIN;
		}
		goto clear;
	}

	/* Standard WSAPI request */
	if (!wsgi_req->uh->pktsize) {
		uwsgi_log( "Empty lua request. skip.\n");
		return -1;
	}

	if (uwsgi_parse_vars(wsgi_req)) {
		return -1;
	}

	// put function in the stack
	//lua_getfield(L, LUA_GLOBALSINDEX, "run");
	lua_pushvalue(L, -1);

	// put cgi vars in the stack

	lua_newtable(L);
	lua_pushstring(L, "");
	lua_setfield(L, -2, "CONTENT_TYPE");
	for(i=0;i<wsgi_req->var_cnt;i++) {
		lua_pushlstring(L, (char *)wsgi_req->hvec[i+1].iov_base, wsgi_req->hvec[i+1].iov_len);
		// transform it in a valid c string TODO this is ugly
		ptrbuf = wsgi_req->hvec[i].iov_base+wsgi_req->hvec[i].iov_len;
		*ptrbuf = 0;
		lua_setfield(L, -2, (char *)wsgi_req->hvec[i].iov_base);
		i++;
	}


	// put "input" table
	lua_newtable(L);
	lua_pushcfunction(L, uwsgi_lua_input);
	lua_setfield(L, -2, "read");
	lua_setfield(L, -2, "input");

#ifdef UWSGI_DEBUG
	uwsgi_log("stack pos %d\n", lua_gettop(L));
#endif

	// call function
	i = lua_pcall(L, 1, 3, 0);
	if (i != 0) {
		uwsgi_log("%s\n", lua_tostring(L, -1));
		lua_pop(L, 1);
                lua_pushvalue(L, -1);
		goto clear;
	}

	//uwsgi_log("%d %s %s %s\n",i,lua_typename(L, lua_type(L, -3)), lua_typename(L, lua_type(L, -2)) ,  lua_typename(L, lua_type(L, -1)));

	// send status
	if (lua_type(L, -3) == LUA_TSTRING || lua_type(L, -3) == LUA_TNUMBER) {
		http = lua_tolstring(L, -3, &slen);
		uwsgi_response_prepare_headers(wsgi_req, (char *) http, slen);
	}
	else {
		uwsgi_log("[uwsgi-lua] invalid response status !!!\n");
		// let's continue 
	}

	// send headers

	lua_pushnil(L);
	while(lua_next(L, -3) != 0) {
		http = lua_tolstring(L, -2, &slen);
		http2 = lua_tolstring(L, -1, &slen2);
		uwsgi_response_add_header(wsgi_req, (char *) http, slen, (char *) http2, slen2);
		lua_pop(L, 1);
	}

	// send body with coroutine
	lua_pushvalue(L, -1);

	while ( (i = lua_pcall(L, 0, 1, 0)) == 0) {
		if (lua_type(L, -1) == LUA_TSTRING) {
			http = lua_tolstring(L, -1, &slen);
			uwsgi_response_write_body_do(wsgi_req, (char *)http, slen);
		}
		lua_pop(L, 1);
		lua_pushvalue(L, -1);
		if (uwsgi.async > 1) {
			return UWSGI_AGAIN;
		}
	}

clear:
	lua_pop(L, 4);
	// set frequency
	lua_gc(L, LUA_GCCOLLECT, 0);

	return UWSGI_OK;

}
Пример #12
0
static int uwsgi_cgi_parse(struct wsgi_request *wsgi_req, int fd, char *buf, size_t blen) {

	size_t i;
	size_t header_size = 0;
	int status_sent = 0;
	size_t remains = blen;
	char *ptr = buf;
	size_t len = 0;

	while(remains > 0) {
		ssize_t rlen = uwsgi_read_true_nb(fd, ptr, remains, uc.timeout);
		if (rlen < 0) {
			if (!errno) return 1;
			return -1;
		}
		// timed out
		if (rlen == 0) return -1;
		remains -= rlen;
		len += rlen;
		ptr += rlen;

		// Search for Status/Location headers
		if (!status_sent) {
			status_sent = uwsgi_cgi_check_status(wsgi_req, buf, len); 
			if (status_sent < 0) return -1;
			// need more data ?
			if (status_sent == 0) continue;
		}

		// send headers
		char *key = buf;
		char *value = NULL;

		for(i=0;i<len;i++) {
			// end of a line
			if (buf[i] == '\n') {
				// end of headers
				if (key == NULL) {
					i++;
					goto send_body;
				}
				// invalid header
				else if (value == NULL) {
					return -1;
				}
				header_size = (buf+i) - key;
				// security check
				if (buf+i > buf) {
					if ((buf[i-1]) == '\r') {
						header_size--;
					}
				}

#ifdef UWSGI_DEBUG
				uwsgi_log("found CGI header: %.*s\n", header_size, key);
#endif

				// Ignore "Status: NNN" header
				if (header_size >= 11) {
					if (!strncasecmp("Status: ", key, 8)) {
						key = NULL;
						value = NULL;
						continue;
					}
				}

				uwsgi_response_add_header(wsgi_req, NULL, 0, key, header_size);
				key = NULL;
				value = NULL;
			}
			else if (buf[i] == ':') {
				value = buf+i;
			}
			else if (buf[i] != '\r') {
				if (key == NULL) {
					key = buf + i;
				}
			}
		}
	}

	return -1;

send_body:

	if (len-i > 0) {
		uwsgi_response_write_body_do(wsgi_req, buf+i, len-i);
	}

	return 0;	
}
Пример #13
0
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;
}
Пример #14
0
int uwsgi_exceptions_catch(struct wsgi_request *wsgi_req) {

	if (uwsgi_response_prepare_headers(wsgi_req, "500 Internal Server Error", 25)) {
		return -1;
	}

	if (uwsgi_response_add_content_type(wsgi_req, "text/plain", 10)) {
		return -1;
	}

	struct uwsgi_buffer *ub = uwsgi_buffer_new(4096);
	if (uwsgi_buffer_append(ub, "uWSGI exceptions catcher for \"", 30)) goto error;
	if (uwsgi_buffer_append(ub, wsgi_req->method, wsgi_req->method_len)) goto error;
	if (uwsgi_buffer_append(ub, " ", 1)) goto error;
	if (uwsgi_buffer_append(ub, wsgi_req->uri, wsgi_req->uri_len)) goto error;
	if (uwsgi_buffer_append(ub, "\" (request plugin: \"", 20)) goto error;
	if (uwsgi_buffer_append(ub, (char *) uwsgi.p[wsgi_req->uh->modifier1]->name, strlen(uwsgi.p[wsgi_req->uh->modifier1]->name))) goto error;
	if (uwsgi_buffer_append(ub, "\", modifier1: ", 14 )) goto error;
	if (uwsgi_buffer_num64(ub, wsgi_req->uh->modifier1)) goto error;
	if (uwsgi_buffer_append(ub, ")\n\n", 3)) goto error;

	if (uwsgi_buffer_append(ub, "Exception: ", 11)) goto error;
                
        if (uwsgi.p[wsgi_req->uh->modifier1]->exception_repr) {
                struct uwsgi_buffer *ub_exc_repr = uwsgi.p[wsgi_req->uh->modifier1]->exception_repr(wsgi_req);
                if (ub_exc_repr) {
                        if (uwsgi_buffer_append(ub, ub_exc_repr->buf, ub_exc_repr->pos)) {
                                uwsgi_buffer_destroy(ub_exc_repr);
                                goto error;
                        }
                        uwsgi_buffer_destroy(ub_exc_repr);
                }
                else {
                        goto notavail3;
                }
        }
        else {
notavail3:
                if (uwsgi_buffer_append(ub, "-Not available-", 15)) goto error;
        }

        if (uwsgi_buffer_append(ub, "\n\n", 2)) goto error;

	if (uwsgi_buffer_append(ub, "Exception class: ", 17)) goto error;

	if (uwsgi.p[wsgi_req->uh->modifier1]->exception_class) {
		struct uwsgi_buffer *ub_exc_class = uwsgi.p[wsgi_req->uh->modifier1]->exception_class(wsgi_req);
		if (ub_exc_class) {
			if (uwsgi_buffer_append(ub, ub_exc_class->buf, ub_exc_class->pos)) {
				uwsgi_buffer_destroy(ub_exc_class);
				goto error;
			}
			uwsgi_buffer_destroy(ub_exc_class);
		}
		else {
			goto notavail;
		}
	}
	else {
notavail:
		if (uwsgi_buffer_append(ub, "-Not available-", 15)) goto error;
	}

	if (uwsgi_buffer_append(ub, "\n\n", 2)) goto error;

	if (uwsgi_buffer_append(ub, "Exception message: ", 19)) goto error;

        if (uwsgi.p[wsgi_req->uh->modifier1]->exception_msg) {
                struct uwsgi_buffer *ub_exc_msg = uwsgi.p[wsgi_req->uh->modifier1]->exception_msg(wsgi_req);
                if (ub_exc_msg) {
                        if (uwsgi_buffer_append(ub, ub_exc_msg->buf, ub_exc_msg->pos)) {
                                uwsgi_buffer_destroy(ub_exc_msg);
                                goto error;
                        }
                        uwsgi_buffer_destroy(ub_exc_msg);
                }
                else {
                        goto notavail2;
                }
        }
        else {
notavail2:
                if (uwsgi_buffer_append(ub, "-Not available-", 15)) goto error;
        }

	if (uwsgi_buffer_append(ub, "\n\n", 2)) goto error;

	if (uwsgi_buffer_append(ub, "Backtrace:\n", 11)) goto error;

        if (uwsgi.p[wsgi_req->uh->modifier1]->backtrace) {
                struct uwsgi_buffer *ub_exc_bt = uwsgi.p[wsgi_req->uh->modifier1]->backtrace(wsgi_req);
                if (ub_exc_bt) {
			struct uwsgi_buffer *parsed_bt = uwsgi_buffer_new(4096);
			if (uwsgi_hooked_parse_array(ub_exc_bt->buf, ub_exc_bt->pos, append_backtrace_to_ubuf, parsed_bt)) {
				uwsgi_buffer_destroy(ub_exc_bt);
				uwsgi_buffer_destroy(parsed_bt);
                                goto error;
			}
			uwsgi_buffer_destroy(ub_exc_bt);
                        if (uwsgi_buffer_append(ub, parsed_bt->buf, parsed_bt->pos)) {
                                uwsgi_buffer_destroy(parsed_bt);
                                goto error;
                        }
                        uwsgi_buffer_destroy(parsed_bt);
                }
                else {
                        goto notavail4;
                }
        }
        else {
notavail4:
                if (uwsgi_buffer_append(ub, "-Not available-", 15)) goto error;
        }

        if (uwsgi_buffer_append(ub, "\n\n", 2)) goto error;

	if (uwsgi_hooked_parse(wsgi_req->buffer, wsgi_req->uh->pktsize, append_vars_to_ubuf, ub)) {
		goto error;
	}

	if (uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos)) {
		goto error;
	}

	uwsgi_buffer_destroy(ub);
	return 0;

error:
	uwsgi_buffer_destroy(ub);
	return -1;

}
Пример #15
0
static int uwsgi_routing_func_xmldir(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){
	char **subject;
	uint16_t *subject_len;
	char *dirname;
	struct uwsgi_buffer *ub;
	char *name = NULL;
	char *path = NULL;
	int i;
	int n;
	struct dirent **tasklist;
	xmlDoc *rdoc;
	xmlNode *rtree;
	xmlNodePtr entrynode;
	char *path_info = NULL;
	struct stat sb;
	size_t sizebuf_len;
	char *sizebuf;
	char timebuf[20];
	int xlen = 0;

	subject = (char **) (((char *)(wsgi_req))+ur->subject);
	subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
	ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len,
	    ur->data, ur->data_len);
	if (!ub) {
		uwsgi_500(wsgi_req);
		return UWSGI_ROUTE_BREAK;
	}
	dirname = ub->buf;

	path_info = uwsgi_concat2n(wsgi_req->path_info, wsgi_req->path_info_len,
	    "", 1);

	n = scandir(dirname, &tasklist, 0, alphasort);
	if (n < 0) {
		uwsgi_404(wsgi_req);
		goto out;
	}

	rdoc = xmlNewDoc(BAD_CAST "1.0");
	rtree = xmlNewNode(NULL, BAD_CAST "index");
	xmlNewProp(rtree, BAD_CAST "path", BAD_CAST path_info);
	xmlDocSetRootElement(rdoc, rtree);

	for(i = 0; i < n; i++) {
		if ((strcmp(tasklist[i]->d_name, ".") == 0) ||
		    (strcmp(tasklist[i]->d_name, "..") == 0)) {
			goto next_entry;
		}

		path = uwsgi_concat3(dirname, "/", tasklist[i]->d_name);
		if (lstat(path, &sb) == -1) {
			goto next_entry;
		}

		name = to_utf8(conf.codeset, tasklist[i]->d_name);
		if (name == NULL) {
			goto next_entry;
		}

		if (S_ISDIR(sb.st_mode)) {
			entrynode = xmlNewTextChild(rtree, NULL,
			    BAD_CAST "directory", BAD_CAST name);
		} else if (S_ISREG(sb.st_mode)) {
			entrynode = xmlNewTextChild(rtree, NULL,
			    BAD_CAST "file", BAD_CAST name);
		} else {
			/* skip everything but directories and regular files */
			goto next_entry;
		}

		sizebuf_len = snprintf(NULL, 0, "%jd", (intmax_t) sb.st_size);
		sizebuf = uwsgi_malloc(sizebuf_len + 1);
		snprintf(sizebuf, sizebuf_len + 1, "%jd", (intmax_t) sb.st_size);
		xmlNewProp(entrynode, BAD_CAST "size", BAD_CAST sizebuf);
		free(sizebuf);

		strftime(timebuf, sizeof (timebuf), "%Y-%m-%dT%H:%M:%S",
		    localtime(&sb.st_mtime));
		xmlNewProp(entrynode, BAD_CAST "mtime", BAD_CAST timebuf);

next_entry:
		free(path);
		path = NULL;
		free(tasklist[i]);
		free(name);
		name = NULL;
	}

	free(tasklist);

	xmlChar *xmlbuf;
	xmlDocDumpFormatMemory(rdoc, &xmlbuf, &xlen, 1);

	uwsgi_response_prepare_headers(wsgi_req,"200 OK", 6);
	uwsgi_response_write_body_do(wsgi_req, (char *) xmlbuf, xlen);

	xmlFreeDoc(rdoc);
	xmlFree(xmlbuf);

out:
	uwsgi_buffer_destroy(ub);
	free(path_info);

	return UWSGI_ROUTE_BREAK;
}
Пример #16
0
static int uwsgi_routing_func_memcached(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){
	// this is the buffer for the memcached response
	char buf[MEMCACHED_BUFSIZE];
	size_t i;
	char last_char = 0;

	struct uwsgi_router_memcached_conf *urmc = (struct uwsgi_router_memcached_conf *) ur->data2;

	char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
        uint16_t *subject_len = (uint16_t *)  (((char *)(wsgi_req))+ur->subject_len);

	struct uwsgi_buffer *ub_key = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urmc->key, urmc->key_len);
        if (!ub_key) return UWSGI_ROUTE_BREAK;

	int fd = uwsgi_connect(urmc->addr, 0, 1);
	if (fd < 0) { uwsgi_buffer_destroy(ub_key) ; goto end; }

        // wait for connection;
        int ret = uwsgi.wait_write_hook(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
        if (ret <= 0) {
		uwsgi_buffer_destroy(ub_key) ;
		close(fd);
		goto end;
        }

	// build the request and send it
	char *cmd = uwsgi_concat3n("get ", 4, ub_key->buf, ub_key->pos, "\r\n", 2);
	if (uwsgi_write_true_nb(fd, cmd, 6+ub_key->pos, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
		uwsgi_buffer_destroy(ub_key);
		free(cmd);
		close(fd);
		goto end;
	}
	uwsgi_buffer_destroy(ub_key);
	free(cmd);

	// ok, start reading the response...
	// first we need to get a full line;
	size_t found = 0;
	size_t pos = 0;
	for(;;) {
		ssize_t len = read(fd, buf + pos, MEMCACHED_BUFSIZE - pos);
		if (len > 0) {
			pos += len;
			goto read;
		}
		if (len < 0) {
			if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) goto wait;
		}
		close(fd);
		goto end;
wait:
		ret = uwsgi.wait_read_hook(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
		// when we have a chunk try to read the first line
		if (ret > 0) {
			len = read(fd, buf + pos, MEMCACHED_BUFSIZE - pos);
			if (len > 0) {
				pos += len;
				goto read;
			}
		}
		close(fd);
		goto end;
read:
		for(i=0;i<pos;i++) {
			if (last_char == '\r' && buf[i] == '\n') {
				found = i-1;
				break;
			}
			last_char = buf[i];
		}
		if (found) break;
	}

	// ok parse the first line
	size_t response_size = memcached_firstline_parse(buf, found);

	if (response_size == 0) {
		close(fd);
		goto end;
	}

	if (urmc->type_num == 1) {
		if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) { close(fd); goto end; }
		if (uwsgi_response_add_content_type(wsgi_req, urmc->content_type, urmc->content_type_len)) { close(fd); goto end; }
		if (uwsgi_response_add_content_length(wsgi_req, response_size)) { close(fd); goto end; }
	}
	size_t remains = pos-(found+2);
	if (remains >= response_size) {
		uwsgi_response_write_body_do(wsgi_req, buf+found+2, response_size);
		close(fd);
		goto end;
	}

	// send what we have
	if (uwsgi_response_write_body_do(wsgi_req, buf+found+2, remains)) {
		close(fd);
		goto end;
	}

	// and now start reading til the output is consumed
	response_size -= remains;
	while(response_size > 0) {
		ssize_t len = read(fd, buf, UMIN(MEMCACHED_BUFSIZE, response_size));
		if (len > 0) goto write;
		if (len < 0) {
                        if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) goto wait2;
                }
		goto error;
wait2:
		ret = uwsgi.wait_read_hook(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
		if (ret > 0) {
                        len = read(fd, buf, UMIN(MEMCACHED_BUFSIZE, response_size));
			if (len > 0) goto write;
		}
		goto error;
write:
		if (uwsgi_response_write_body_do(wsgi_req, buf, len)) {
			goto error;
        	}
		response_size -= len;
	}

	close(fd);
	return UWSGI_ROUTE_BREAK;

error:
	close(fd);
	
end:
	if (ur->custom)
        	return UWSGI_ROUTE_NEXT;

	return UWSGI_ROUTE_BREAK;
}