Пример #1
0
static int uwsgi_routing_func_basicauth(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {

	// skip if already authenticated
	if (wsgi_req->remote_user_len > 0) {
		return UWSGI_ROUTE_NEXT;
	}


	if (wsgi_req->authorization_len > 7 && ur->data2_len > 0) {
		if (strncmp(wsgi_req->authorization, "Basic ", 6))
			goto forbidden;

		size_t auth_len = 0;
		char *auth = uwsgi_base64_decode(wsgi_req->authorization+6, wsgi_req->authorization_len-6, &auth_len);
		if (auth) {
			if (!ur->custom) {
				// check htpasswd-like file
				uint16_t ulen = htpasswd_check(ur->data2, auth);
				if (ulen > 0) {
					wsgi_req->remote_user = uwsgi_req_append(wsgi_req, "REMOTE_USER", 11, auth, ulen); 
					if (!wsgi_req->remote_user) {
						free(auth);
						goto forbidden;
					}
					wsgi_req->remote_user_len = ulen;
				}
				else if (ur->data3_len == 0) {
					free(auth);
					goto forbidden;
				}
			}
			else {
				if (!uwsgi_strncmp(auth, auth_len, ur->data2, ur->data2_len)) {
					wsgi_req->remote_user = uwsgi_req_append(wsgi_req, "REMOTE_USER", 11, auth, ur->custom); 
					if (!wsgi_req->remote_user) {
						free(auth);
						goto forbidden;
					}
					wsgi_req->remote_user_len = ur->custom;
				}
				else if (ur->data3_len == 0) {
					free(auth);
					goto forbidden;
				}
			}
			free(auth);
			return UWSGI_ROUTE_NEXT;
		}
	}

forbidden:
	if (uwsgi_response_prepare_headers(wsgi_req, "401 Authorization Required", 26)) goto end;
	char *realm = uwsgi_concat3n("Basic realm=\"", 13, ur->data, ur->data_len, "\"", 1);
	// no need to check for errors
	uwsgi_response_add_header(wsgi_req, "WWW-Authenticate", 16, realm, 13 + ur->data_len + 1);
	free(realm);
	uwsgi_response_write_body_do(wsgi_req, "Unauthorized", 12);
end:
	return UWSGI_ROUTE_BREAK;
}
Пример #2
0
Файл: ssi.c Проект: Algy/uwsgi
static int uwsgi_ssi_request(struct wsgi_request *wsgi_req) {
	struct uwsgi_buffer *ub = NULL;

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

	if (!wsgi_req->document_root_len || !wsgi_req->path_info_len) {
		uwsgi_log("[uwsgi-ssi] DOCUMENT_ROOT and PATH_INFO must be defined !!!\n");
		uwsgi_500(wsgi_req);
		return UWSGI_OK;
	}

	char *filename = uwsgi_concat3n(wsgi_req->document_root, wsgi_req->document_root_len, "/", 1, wsgi_req->path_info, wsgi_req->path_info_len);
	size_t filename_len = wsgi_req->document_root_len + 1 + wsgi_req->path_info_len;
	
	// we expand the path for future security implementations
	char *real_filename = uwsgi_expand_path(filename, filename_len, NULL);
	free(filename);
	if (!real_filename) {
		uwsgi_404(wsgi_req);
		return UWSGI_OK;
	}

	struct uwsgi_buffer *ub_ssi = uwsgi_buffer_from_file(real_filename);
	free(real_filename);
	if (!ub_ssi) {
		uwsgi_500(wsgi_req);
		return UWSGI_OK;
	}

	ub = uwsgi_ssi_parse(wsgi_req, ub_ssi->buf, ub_ssi->pos);
	uwsgi_buffer_destroy(ub_ssi);
	if (!ub) {
               	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, ub->pos)) {
               	uwsgi_500(wsgi_req);
               	goto end;
       	}
       	// content_type
       	if (uwsgi_response_add_content_type(wsgi_req, "text/html", 9)) {
               	uwsgi_500(wsgi_req);
               	goto end;
       	}

	uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos);
end:
	if (ub) {
		uwsgi_buffer_destroy(ub);
	}
	return UWSGI_OK;
}
Пример #3
0
// status could be NNN or NNN message
int uwsgi_response_prepare_headers(struct wsgi_request *wsgi_req, char *status, uint16_t status_len) {

	if (wsgi_req->headers_sent || wsgi_req->headers_size || wsgi_req->response_size || status_len < 3 || wsgi_req->write_errors) return -1;

	if (!wsgi_req->headers) {
		wsgi_req->headers = uwsgi_buffer_new(uwsgi.page_size);
		wsgi_req->headers->limit = UMAX16;
	}

	// reset the buffer (could be useful for rollbacks...)
	wsgi_req->headers->pos = 0;
	// reset headers count
	wsgi_req->header_cnt = 0;
	struct uwsgi_buffer *hh = NULL;
	wsgi_req->status = uwsgi_str3_num(status);
#ifdef UWSGI_ROUTING
	// apply error routes
	if (uwsgi_apply_error_routes(wsgi_req) == UWSGI_ROUTE_BREAK) {
		// from now on ignore write body requests...
		wsgi_req->ignore_body = 1;
		return -1;
	}
	wsgi_req->is_error_routing = 0;
#endif
	if (status_len <= 4) {
		char *new_sc = NULL;
		size_t new_sc_len = 0;
		uint16_t sc_len = 0;
		const char *sc = uwsgi_http_status_msg(status, &sc_len);
		if (sc) {
			new_sc = uwsgi_concat3n(status, 3, " ", 1, (char *)sc, sc_len);
			new_sc_len = 4+sc_len;
		}
		else {	
			new_sc = uwsgi_concat2n(status, 3, " Unknown", 8);
			new_sc_len = 11;
		}
		hh = wsgi_req->socket->proto_prepare_headers(wsgi_req, new_sc, new_sc_len);
		free(new_sc);
	}
	else {
		hh = wsgi_req->socket->proto_prepare_headers(wsgi_req, status, status_len);
	}
	if (!hh) {wsgi_req->write_errors++; return -1;}
        if (uwsgi_buffer_append(wsgi_req->headers, hh->buf, hh->pos)) goto error;
        uwsgi_buffer_destroy(hh);
        return 0;
error:
        uwsgi_buffer_destroy(hh);
	wsgi_req->write_errors++;
	return -1;
}
Пример #4
0
static char *htpasswd_check_sha1(char *pwd) {
#ifdef UWSGI_SSL
	char sha1[20];
	uwsgi_sha1(pwd, strlen(pwd), sha1);

	size_t len = 0;
	char *b64 = uwsgi_base64_encode(sha1, 20, &len);
	if (!b64) return NULL;

	// we add a new line for being fgets-friendly
	char *crypted = uwsgi_concat3n("{SHA}", 5, b64, len, "\n", 1);
	free(b64);
	return crypted;

#else
	uwsgi_log("*** WARNING, rebuild uWSGI with SSL support for htpasswd sha1 feature ***\n");
	return NULL;
#endif
}
Пример #5
0
// status could be NNN or NNN message
int uwsgi_response_prepare_headers(struct wsgi_request *wsgi_req, char *status, uint16_t status_len) {

	if (wsgi_req->headers_sent || wsgi_req->headers_size || wsgi_req->response_size || status_len < 3 || wsgi_req->write_errors) return -1;

	if (!wsgi_req->headers) {
		wsgi_req->headers = uwsgi_buffer_new(uwsgi.page_size);
		wsgi_req->headers->limit = UMAX16;
	}

	// reset the buffer (could be useful for rollbacks...)
	wsgi_req->headers->pos = 0;
	struct uwsgi_buffer *hh = NULL;
	if (status_len <= 4) {
		char *new_sc = NULL;
		size_t new_sc_len = 0;
		uint16_t sc_len = 0;
		const char *sc = uwsgi_http_status_msg(status, &sc_len);
		if (sc) {
			new_sc = uwsgi_concat3n(status, 3, " ", 1, (char *)sc, sc_len);
			new_sc_len = 4+sc_len;
		}
		else {	
			new_sc = uwsgi_concat2n(status, 3, " Unknown", 8);
			new_sc_len = 11;
		}
		hh = wsgi_req->socket->proto_prepare_headers(wsgi_req, new_sc, new_sc_len);
		free(new_sc);
	}
	else {
		hh = wsgi_req->socket->proto_prepare_headers(wsgi_req, status, status_len);
	}
	if (!hh) {wsgi_req->write_errors++; return -1;}
        if (uwsgi_buffer_append(wsgi_req->headers, hh->buf, hh->pos)) goto error;
        uwsgi_buffer_destroy(hh);
	wsgi_req->status = uwsgi_str3_num(status);
        return 0;
error:
        uwsgi_buffer_destroy(hh);
	wsgi_req->write_errors++;
	return -1;
}
Пример #6
0
/* this is the dynamic loader, it loads app reading information from a wsgi_request */
PyObject *uwsgi_dyn_loader(void *arg1) {

	PyObject *callable = NULL;
	char *tmpstr;

	struct wsgi_request *wsgi_req = (struct wsgi_request *) arg1;

	// MANAGE UWSGI_SCRIPT
	if (wsgi_req->script_len > 0) {
		tmpstr = uwsgi_strncopy(wsgi_req->script, wsgi_req->script_len);
		callable = uwsgi_uwsgi_loader((void *)tmpstr);
		free(tmpstr);
	}
	// MANAGE UWSGI_MODULE
	else if (wsgi_req->module_len > 0) {
		if (wsgi_req->callable_len > 0) {
			tmpstr = uwsgi_concat3n(wsgi_req->module, wsgi_req->module_len, ":", 1, wsgi_req->callable, wsgi_req->callable_len);
		}
		else {
			tmpstr = uwsgi_strncopy(wsgi_req->module, wsgi_req->module_len);
		}
		callable = uwsgi_uwsgi_loader((void *)tmpstr);
		free(tmpstr);
	}
	// MANAGE UWSGI_FILE
	else if (wsgi_req->file_len > 0) {
		tmpstr = uwsgi_strncopy(wsgi_req->file, wsgi_req->file_len);
		callable = uwsgi_file_loader((void *)tmpstr);
		free(tmpstr);
	}
	// TODO MANAGE UWSGI_PASTE
/*
	else if (wsgi_req->wsgi_paste_len > 0) {
		tmpstr = uwsgi_strncopy(wsgi_req->paste, wsgi_req->paste_len);
		callable = uwsgi_paste_loader((void *)tmpstr);
		free(tmpstr);
	}
*/

	return callable;
}
Пример #7
0
static int uwsgi_mongrel2_json_parse(json_t * root, struct wsgi_request *wsgi_req) {

	char *json_val;
	char *query_string = NULL;
	size_t query_string_len = 0;
	size_t script_name_len = 0;
	void *json_iter;
	char *json_key;
	json_t *json_value;

	if ((json_val = uwsgi_mongrel2_json_get_string(root, "METHOD"))) {
		if (!strcmp(json_val, "JSON")) {
			return -1;
		}
		wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "REQUEST_METHOD", 14, json_val, strlen(json_val));
	}

	// pretty easy, we get the file and we map it to wsgi_req->post_file, uWSGI read api will automatically use this
	if ((json_val = uwsgi_mongrel2_json_get_string(root, "x-mongrel2-upload-done"))) {
		wsgi_req->post_file = fopen(json_val, "r");
		if (!wsgi_req->post_file) {
			uwsgi_error_open(json_val);
			return -1;
		}
	}
	else if (uwsgi_mongrel2_json_get_string(root, "x-mongrel2-upload-start")) {
		return -1;
	}


	wsgi_req->uh->pktsize += uwsgi_mongrel2_json_add(wsgi_req, root, "VERSION", "SERVER_PROTOCOL", 15, NULL, NULL);
	wsgi_req->uh->pktsize += uwsgi_mongrel2_json_add(wsgi_req, root, "QUERY", "QUERY_STRING", 12, &query_string, &query_string_len);
	if (query_string == NULL) {
		// always set QUERY_STRING
		wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "QUERY_STRING", 12, "", 0);
	}

	// set SCRIPT_NAME to an empty value
	wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "SCRIPT_NAME", 11, "", 0);

	if ((json_val = uwsgi_mongrel2_json_get_string(root, "PATH"))) {
		wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "PATH_INFO", 9, json_val + script_name_len, strlen(json_val + script_name_len));
		if (query_string_len) {
			char *request_uri = uwsgi_concat3n(json_val, strlen(json_val), "?", 1, query_string, query_string_len);
			wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "REQUEST_URI", 11, request_uri, strlen(json_val) + 1 + query_string_len);
			free(request_uri);
		}
		else {
			wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "REQUEST_URI", 11, json_val, strlen(json_val));
		}
	}

	if ((json_val = uwsgi_mongrel2_json_get_string(root, "URL_SCHEME"))) {
                wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "UWSGI_SCHEME", 12, json_val, strlen(json_val));
        }

	if ((json_val = uwsgi_mongrel2_json_get_string(root, "host"))) {
		char *colon = strchr(json_val, ':');
		if (colon) {
			wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "SERVER_PORT", 11, colon + 1, strlen(colon + 1));
		}
		else {
			wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "SERVER_PORT", 11, "80", 2);
		}
	}

	if ((json_val = uwsgi_mongrel2_json_get_string(root, "x-forwarded-for"))) {
		char *colon = strchr(json_val, ',');
		if (colon) {
			wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "REMOTE_ADDR", 11, colon + 1, (colon + 1) - json_val);
		}
		else {
			wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "REMOTE_ADDR", 11, json_val, strlen(json_val));
		}
	}


	if ((json_val = uwsgi_mongrel2_json_get_string(root, "content-length"))) {
		wsgi_req->post_cl = atoi(json_val);
	}

	wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "SERVER_NAME", 11, uwsgi.hostname, uwsgi.hostname_len);

	json_iter = json_object_iter(root);

	while (json_iter) {
		json_key = (char *) json_object_iter_key(json_iter);
		// is it a header ?
		if (json_key[0] >= 97) {
			json_value = json_object_iter_value(json_iter);
			if (json_is_string(json_value)) {
				json_val = (char *) json_string_value(json_value);
				wsgi_req->uh->pktsize += proto_base_add_uwsgi_header(wsgi_req, json_key, strlen(json_key), json_val, strlen(json_val));
			}
		}
		json_iter = json_object_iter_next(root, json_iter);
	}

	return 0;

}
Пример #8
0
// dumb/fake tnetstring implementation...all is a string
static int uwsgi_mongrel2_tnetstring_parse(struct wsgi_request *wsgi_req, char *buf, int len) {

	char *ptr = buf;
	char *watermark = buf + len;
	char *key = NULL;
	size_t keylen = 0;
	char *val = NULL;
	size_t vallen = 0;
	uint16_t script_name_len = 0;
	char *query_string = NULL;
	uint16_t query_string_len = 0;
	int async_upload = 0;

	// set an empty SCRIPT_NAME
	wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "SCRIPT_NAME", 11, "", 0);

	while (ptr < watermark) {

		ptr = uwsgi_netstring(ptr, len - (ptr - buf), &key, &keylen);
		if (ptr == NULL)
			break;
		// empty keys are not allowed
		if (keylen == 0)
			break;

		if (ptr >= watermark)
			break;

		ptr = uwsgi_netstring(ptr, len - (ptr - buf), &val, &vallen);
		if (ptr == NULL)
			break;


		if (key[0] < 97) {
			if (!uwsgi_strncmp("METHOD", 6, key, keylen)) {
				if (!uwsgi_strncmp("JSON", 4, val, vallen)) {
					return -1;
				}
				wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "REQUEST_METHOD", 14, val, vallen);
			}
			else if (!uwsgi_strncmp("VERSION", 7, key, keylen)) {
				wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "SERVER_PROTOCOL", 15, val, vallen);
			}
			else if (!uwsgi_strncmp("QUERY", 5, key, keylen)) {
				wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "QUERY_STRING", 12, val, vallen);
				query_string = val;
				query_string_len = vallen;
			}
			else if (!uwsgi_strncmp("PATH", 4, key, keylen)) {
				wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "PATH_INFO", 9, val + script_name_len, vallen - script_name_len);
				if (query_string_len) {
					char *request_uri = uwsgi_concat3n(val, vallen, "?", 1, query_string, query_string_len);
					wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "REQUEST_URI", 11, request_uri, vallen + 1 + query_string_len);
					free(request_uri);
				}
				else {
					wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "REQUEST_URI", 11, val, vallen);
				}
			}
		}
		else {
			// add header
			if (!uwsgi_strncmp("host", 4, key, keylen)) {
				char *colon = memchr(val, ':', vallen);
				if (colon) {
					wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "SERVER_PORT", 11, colon + 1, vallen - ((colon + 1) - val));
				}
				else {
					wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "SERVER_PORT", 11, "80", 2);
				}
			}
			else if (!uwsgi_strncmp("content-length", 14, key, keylen)) {
				wsgi_req->post_cl = uwsgi_str_num(val, vallen);
			}
			else if (!uwsgi_strncmp("x-mongrel2-upload-done", 22, key, keylen)) {
				char *post_filename = uwsgi_concat2n(val, vallen, "", 0);
				wsgi_req->post_file = fopen(post_filename, "r");
				if (!wsgi_req->post_file) {
					uwsgi_error_open(post_filename);
					wsgi_req->do_not_log = 1;
				}
				async_upload += 2;
				free(post_filename);
			}
			else if (!uwsgi_strncmp("x-forwarded-for", 15, key, keylen)) {
				char *colon = memchr(val, ',', vallen);
				if (colon) {
					wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "REMOTE_ADDR", 11, colon + 1, (colon + 1) - val);
				}
				else {
					wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "REMOTE_ADDR", 11, val, vallen);
				}
			}
			else if (!uwsgi_strncmp("x-mongrel2-upload-start", 23, key, keylen)) {
				async_upload += 1;
			}
			wsgi_req->uh->pktsize += proto_base_add_uwsgi_header(wsgi_req, key, keylen, val, vallen);
		}
	}

	wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "SERVER_NAME", 11, uwsgi.hostname, uwsgi.hostname_len);

	if (query_string == NULL) {
		// always set QUERY_STRING
		wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "QUERY_STRING", 12, "", 0);
	}

	// reject uncomplete upload
	if (async_upload == 1) {
		return -1;
	}
	return 0;
}
Пример #9
0
static int uwsgi_webdav_add_props(struct wsgi_request *wsgi_req, xmlNode *req_prop, xmlNode * multistatus, xmlNsPtr dav_ns, char *uri, char *filename, int with_values) {
	struct stat st;
	if (stat(filename, &st)) {
		uwsgi_error("uwsgi_webdav_add_props()/stat()");
		return -1;
	}

	int is_collection = 0;

	xmlNode *response = xmlNewChild(multistatus, dav_ns, BAD_CAST "response", NULL);
	uint16_t uri_len = strlen(uri) ;
	char *encoded_uri = uwsgi_malloc( (uri_len * 3) + 1);
	http_url_encode(uri, &uri_len, encoded_uri);
	encoded_uri[uri_len] = 0;
	xmlNewChild(response, dav_ns, BAD_CAST "href", BAD_CAST encoded_uri);
	free(encoded_uri);
	xmlNode *r_propstat = xmlNewChild(response, dav_ns, BAD_CAST "propstat", NULL);
	char *r_status = uwsgi_concat2n(wsgi_req->protocol, wsgi_req->protocol_len, " 200 OK", 7);
	xmlNewChild(r_propstat, dav_ns, BAD_CAST "status", BAD_CAST r_status);
	free(r_status);

	xmlNode *r_prop = xmlNewChild(r_propstat, dav_ns, BAD_CAST "prop", NULL);

	if (with_values) {
		if (uwsgi_webdav_prop_requested(req_prop, "DAV:", "displayname")) {
			char *base_uri = uwsgi_get_last_char(uri, '/');
			if (base_uri) {
				xmlNewChild(r_prop, dav_ns, BAD_CAST "displayname", BAD_CAST base_uri+1);
			}
			else {
				xmlNewChild(r_prop, dav_ns, BAD_CAST "displayname", BAD_CAST uri);
			}

		}

		if (S_ISDIR(st.st_mode)) is_collection = 1;

		xmlNode *r_type = NULL;

		if (uwsgi_webdav_prop_requested(req_prop, "DAV:", "resourcetype")) {
			r_type = xmlNewChild(r_prop, dav_ns, BAD_CAST "resourcetype", NULL);
			if (is_collection) {
				xmlNewChild(r_type, dav_ns, BAD_CAST "collection", NULL);
				is_collection = 1;
			}
		}


		if (!is_collection) {
			if (uwsgi_webdav_prop_requested(req_prop, "DAV:", "getcontentlength")) {
				char *r_contentlength = uwsgi_num2str(st.st_size);
				xmlNewChild(r_prop, dav_ns, BAD_CAST "getcontentlength", BAD_CAST r_contentlength);
				free(r_contentlength);
			}
			if (uwsgi_webdav_prop_requested(req_prop, "DAV:", "getcontenttype")) {
				size_t mime_type_len = 0;
				char *mime_type = uwsgi_get_mime_type(filename, strlen(filename), &mime_type_len);
				if (mime_type) {
					char *r_ctype = uwsgi_concat2n(mime_type, mime_type_len, "", 0);
					xmlNewTextChild(r_prop, dav_ns, BAD_CAST "getcontenttype", BAD_CAST r_ctype);
					free(r_ctype);
				}
			}
		}

		if (uwsgi_webdav_prop_requested(req_prop, "DAV:", "creationdate")) {
			// there is no creation date on UNIX/POSIX, ctime is the nearest thing...
			char *cdate = uwsgi_webdav_new_date(st.st_ctime);
			if (cdate) {
				xmlNewTextChild(r_prop, dav_ns, BAD_CAST "creationdate", BAD_CAST cdate);
				free(cdate);
			}
		}

		if (uwsgi_webdav_prop_requested(req_prop, "DAV:", "getlastmodified")) {
			char *mdate = uwsgi_webdav_new_date(st.st_mtime);
			if (mdate) {
				xmlNewTextChild(r_prop, dav_ns, BAD_CAST "getlastmodified", BAD_CAST mdate);
				free(mdate);
			}
		}

		if (uwsgi_webdav_prop_requested(req_prop, "DAV:", "getetag")) {
			char *etag = uwsgi_num2str(st.st_mtime);
			xmlNewTextChild(r_prop, dav_ns, BAD_CAST "getetag", BAD_CAST etag);
			free(etag);
		}

		if (uwsgi_webdav_prop_requested(req_prop, "DAV:", "executable")) {
			xmlNewChild(r_prop, dav_ns, BAD_CAST "executable", NULL);
		}

		if (uwsgi_webdav_prop_requested(req_prop, "DAV:", "owner")) {
			xmlNewTextChild(r_prop, dav_ns, BAD_CAST "owner", NULL);
		}

		if (wsgi_req->remote_user_len > 0) {

			if (udav.principal_base) {
				if (uwsgi_webdav_prop_requested(req_prop, "DAV:", "current-user-principal")) {
					char *current_user_principal = uwsgi_concat2n(udav.principal_base, strlen(udav.principal_base), wsgi_req->remote_user, wsgi_req->remote_user_len);
					xmlNode *cup = xmlNewChild(r_prop, dav_ns, BAD_CAST "current-user-principal", NULL);
					xmlNewTextChild(cup, dav_ns, BAD_CAST "href", BAD_CAST current_user_principal);
					if (uwsgi_webdav_prop_requested(req_prop, "DAV:", "resourcetype")) {
						if (!strcmp(current_user_principal, uri)) {
							xmlNewChild(r_type, dav_ns, BAD_CAST "principal", NULL);
						}
					}
					free(current_user_principal);
				}
			}

			if (uwsgi_webdav_prop_requested(req_prop, "DAV:", "current-user-privilege-set")) {
				xmlNode *cups = xmlNewChild(r_prop, dav_ns, BAD_CAST "current-user-privilege-set", NULL);
				xmlNode *privilege = xmlNewChild(cups, dav_ns, BAD_CAST "privilege", NULL);	
				xmlNewChild(privilege, dav_ns, BAD_CAST "all", NULL);
				xmlNewChild(privilege, dav_ns, BAD_CAST "read", NULL);
				xmlNewChild(privilege, dav_ns, BAD_CAST "write", NULL);
				xmlNewChild(privilege, dav_ns, BAD_CAST "write-content", NULL);
				xmlNewChild(privilege, dav_ns, BAD_CAST "write-properties", NULL);
			}
		}

		if (uwsgi_webdav_prop_requested(req_prop, "DAV:", "supported-report-set")) {
			xmlNode *report_set = xmlNewChild(r_prop, dav_ns, BAD_CAST "supported-report-set", NULL);
			xmlNode *supported_report = xmlNewChild(report_set, dav_ns, BAD_CAST "supported-report", NULL);
			xmlNewChild(supported_report, dav_ns, BAD_CAST "report", BAD_CAST "principal-property-search");
			supported_report = xmlNewChild(report_set, dav_ns, BAD_CAST "supported-report", NULL);
			xmlNewChild(supported_report, dav_ns, BAD_CAST "report", BAD_CAST "sync-collection");
			supported_report = xmlNewChild(report_set, dav_ns, BAD_CAST "supported-report", NULL);
			xmlNewChild(supported_report, dav_ns, BAD_CAST "report", BAD_CAST "expand-property");
			supported_report = xmlNewChild(report_set, dav_ns, BAD_CAST "supported-report", NULL);
			xmlNewChild(supported_report, dav_ns, BAD_CAST "report", BAD_CAST "principal-search-property-set");
		}

		uwsgi_webdav_foreach_prop(udav.add_prop, req_prop, r_prop, 0, NULL );
                uwsgi_webdav_foreach_prop(udav.add_prop_href, req_prop, r_prop, 1, NULL);
                uwsgi_webdav_foreach_prop(udav.add_prop_comp,req_prop, r_prop, 2 , NULL);

		uwsgi_webdav_foreach_prop(udav.add_rtype_prop,req_prop, r_type, 0, "resourcetype");

		if (is_collection) {
			uwsgi_webdav_foreach_prop(udav.add_rtype_collection_prop,req_prop, r_type, 0, "resourcetype");
			uwsgi_webdav_foreach_prop(udav.add_collection_prop,req_prop, r_prop, 0, NULL);
			uwsgi_webdav_foreach_prop(udav.add_collection_prop_href,req_prop, r_prop, 1, NULL);
			uwsgi_webdav_foreach_prop(udav.add_collection_prop_comp,req_prop, r_prop, 2, NULL);
		}
		else {
			uwsgi_webdav_foreach_prop(udav.add_rtype_object_prop,req_prop, r_type, 0, "resourcetype");
			uwsgi_webdav_foreach_prop(udav.add_object_prop,req_prop, r_prop, 0, NULL);
			uwsgi_webdav_foreach_prop(udav.add_object_prop_href,req_prop, r_prop, 1, NULL);
			uwsgi_webdav_foreach_prop(udav.add_object_prop_comp,req_prop, r_prop, 2, NULL);
		}
	}
	else {
		xmlNewChild(r_prop, dav_ns, BAD_CAST "displayname", NULL);
		xmlNewChild(r_prop, dav_ns, BAD_CAST "resourcetype", NULL);
		if (!S_ISDIR(st.st_mode)) {
			xmlNewChild(r_prop, dav_ns, BAD_CAST "getcontentlength", NULL);
			xmlNewChild(r_prop, dav_ns, BAD_CAST "getcontenttype", NULL);
		}
		xmlNewChild(r_prop, dav_ns, BAD_CAST "creationdate", NULL);
		xmlNewChild(r_prop, dav_ns, BAD_CAST "getlastmodified", NULL);
		xmlNewChild(r_prop, dav_ns, BAD_CAST "supported-report-set", NULL);
		if (wsgi_req->remote_user_len > 0) {
			xmlNewChild(r_prop, dav_ns, BAD_CAST "current-user-privilege-set", NULL);
			if (udav.principal_base) {
				xmlNewChild(r_prop, dav_ns, BAD_CAST "current-user-principal", NULL);
			}
		}
	}

#if defined(__linux__) || defined(__APPLE__)
	// get xattr for user.uwsgi.webdav.
#if defined(__linux__)
	ssize_t rlen = listxattr(filename, NULL, 0);
#elif defined(__APPLE__)
	ssize_t rlen = listxattr(filename, NULL, 0, 0);
#endif
	// do not return -1 as the previous xml is valid !!!
	if (rlen <= 0) return 0;
	// use calloc to avoid races
	char *xattrs = uwsgi_calloc(rlen);
#if defined(__linux__)
	if (listxattr(filename, xattrs, rlen) <= 0) {
#elif defined(__APPLE__)
	if (listxattr(filename, xattrs, rlen, 0) <= 0) {
#endif
		free(xattrs);
		return 0;
	}
	// parse the name list
	ssize_t i;
	char *key = NULL;
	for(i=0;i<rlen;i++) {
		// check for wrong condition
		if (xattrs[i] == 0 && key == NULL) break;
		if (key && xattrs[i] == 0) {
			if (!uwsgi_starts_with(key, strlen(key), "user.uwsgi.webdav.", 18)) {
				if (uwsgi_string_list_has_item(udav.skip_prop, key + 18, strlen(key + 18))) continue;
				xmlNsPtr xattr_ns = NULL;
				// does it has a namespace ?
				char *separator = strchr(key + 18, '|');
				char *xattr_key = key + 18;
				if (separator) {
					xattr_key = separator + 1;
					*separator = 0;
					if (!uwsgi_webdav_prop_requested(req_prop, key + 18, xattr_key)) continue;
				}
				else {
					if (!uwsgi_webdav_prop_requested(req_prop, NULL, xattr_key)) continue;
				}
				xmlNode *xattr_item = NULL;
				if (with_values) {
#if defined(__linux__)
					ssize_t rlen2 = getxattr(filename, key, NULL, 0);
#elif defined(__APPLE__)
					ssize_t rlen2 = getxattr(filename, key, NULL, 0, 0, 0);
#endif
					if (rlen > 0) {
						// leave space for final 0
						char *xvalue = uwsgi_calloc(rlen2 + 1);
#if defined(__linux__)
						if (getxattr(filename, key, xvalue, rlen2) > 0) {
#elif defined(__APPLE__)
						if (getxattr(filename, key, xvalue, rlen2, 0 ,0) > 0) {
#endif
							xattr_item = xmlNewTextChild(r_prop, NULL, BAD_CAST xattr_key, BAD_CAST xvalue);
						}
						free(xvalue);	
					}
					else if (rlen == 0) {
						xattr_item = xmlNewTextChild(r_prop, NULL, BAD_CAST xattr_key, NULL);
					}
				}
				else {
					xattr_item = xmlNewTextChild(r_prop, NULL, BAD_CAST xattr_key, NULL);
				}	
				if (separator && xattr_item) {
					xattr_ns = xmlNewNs(xattr_item, BAD_CAST (key + 18), NULL);
					*separator = '|';
					xmlSetNs(xattr_item, xattr_ns);	
				}
			}
			key = NULL;
		}
		else if (key == NULL) {
			key = &xattrs[i];
		}
	}
	free(xattrs);
	
#endif
	return 0;
}

static size_t uwsgi_webdav_expand_path(struct wsgi_request *wsgi_req, char *item, uint16_t item_len, char *filename) {
	struct uwsgi_app *ua = &uwsgi_apps[wsgi_req->app_id];
	char *docroot = ua->interpreter;
	size_t docroot_len = strlen(docroot);

	// merge docroot with path_info
	char *tmp_filename = uwsgi_concat3n(docroot, docroot_len, "/", 1, item, item_len);
	// try expanding the path 
	if (!realpath(tmp_filename, filename)) {
		free(tmp_filename);
		return 0;
	}
	free(tmp_filename);
	return strlen(filename);
}

static size_t uwsgi_webdav_expand_fake_path(struct wsgi_request *wsgi_req, char *item, uint16_t item_len, char *filename) {
	char *last_slash = uwsgi_get_last_charn(item, item_len, '/');
        if (!last_slash) return 0;
        size_t filename_len = uwsgi_webdav_expand_path(wsgi_req, item, last_slash - item, filename);
        if (!filename_len) return 0;
        // check for overflow
        if (filename_len + (item_len - (last_slash - item)) >= PATH_MAX) return 0;
        memcpy(filename + filename_len, last_slash, (item_len - (last_slash - item)));
        filename_len += (item_len - (last_slash - item));
        filename[(int)filename_len] = 0;
	return filename_len;
}

static xmlDoc *uwsgi_webdav_manage_prop(struct wsgi_request *wsgi_req, xmlNode *req_prop, char *filename, size_t filename_len, int with_values) {
	// default 1 depth
	int depth = 1;
        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);
        }

	xmlDoc *rdoc = xmlNewDoc(BAD_CAST "1.0");
        xmlNode *multistatus = xmlNewNode(NULL, BAD_CAST "multistatus");
        xmlDocSetRootElement(rdoc, multistatus);
        xmlNsPtr dav_ns = xmlNewNs(multistatus, BAD_CAST "DAV:", BAD_CAST "D");
        xmlSetNs(multistatus, dav_ns);

	if (depth == 0) {
                char *uri = uwsgi_concat2n(wsgi_req->path_info, wsgi_req->path_info_len, "", 0);
                uwsgi_webdav_add_props(wsgi_req, req_prop, multistatus, dav_ns, uri, filename, with_values);
                free(uri);
        }
        else {
                DIR *collection = opendir(filename);
                struct dirent de;
                for (;;) {
                        struct dirent *de_r = NULL;
                        if (readdir_r(collection, &de, &de_r)) {
                                uwsgi_error("uwsgi_wevdav_manage_propfind()/readdir_r()");
                                break;
                        }
                        if (de_r == NULL) {
                                break;
                        }
                        char *uri = NULL;
                        char *direntry = NULL;
                        if (!strcmp(de.d_name, "..")) {
                                // skip ..
                                continue;
                        }
                        else if (!strcmp(de.d_name, ".")) {
                                uri = uwsgi_concat2n(wsgi_req->path_info, wsgi_req->path_info_len, "", 0);
                                direntry = uwsgi_concat2n(filename, filename_len, "", 0);
                        }
                        else if (wsgi_req->path_info[wsgi_req->path_info_len - 1] == '/') {
                                uri = uwsgi_concat2n(wsgi_req->path_info, wsgi_req->path_info_len, de.d_name, strlen(de.d_name));
                                direntry = uwsgi_concat3n(filename, filename_len, "/", 1, de.d_name, strlen(de.d_name));
                        }
                        else {
                                uri = uwsgi_concat3n(wsgi_req->path_info, wsgi_req->path_info_len, "/", 1, de.d_name, strlen(de.d_name));
                                direntry = uwsgi_concat3n(filename, filename_len, "/", 1, de.d_name, strlen(de.d_name));
                        }
                        uwsgi_webdav_add_props(wsgi_req, req_prop, multistatus, dav_ns, uri, direntry, with_values);
                        free(uri);
                        free(direntry);
                }
                closedir(collection);
        }

	return rdoc;
	
}
Пример #10
0
int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_t document_root_len, char *path_info, uint16_t path_info_len, int is_a_file) {

	struct stat st;
	char real_filename[PATH_MAX + 1];
	size_t real_filename_len = 0;
	char *filename = NULL;
	size_t filename_len = 0;

	struct uwsgi_string_list *index = NULL;

	if (!is_a_file) {
		filename = uwsgi_concat3n(document_root, document_root_len, "/", 1, path_info, path_info_len);
		filename_len = document_root_len + 1 + path_info_len;
	}
	else {
		filename = uwsgi_concat2n(document_root, document_root_len, "", 0);
		filename_len = document_root_len;
	}

#ifdef UWSGI_DEBUG
	uwsgi_log("[uwsgi-fileserve] checking for %s\n", filename);
#endif

	if (uwsgi.static_cache_paths) {
		uwsgi_rlock(uwsgi.static_cache_paths->lock);
		uint64_t item_len;
		char *item = uwsgi_cache_get2(uwsgi.static_cache_paths, filename, filename_len, &item_len);
		if (item && item_len > 0 && item_len <= PATH_MAX) {
			memcpy(real_filename, item, item_len);
			real_filename_len = item_len;
			uwsgi_rwunlock(uwsgi.static_cache_paths->lock);
			goto found;
		}
		uwsgi_rwunlock(uwsgi.static_cache_paths->lock);
	}

	if (!realpath(filename, real_filename)) {
#ifdef UWSGI_DEBUG
		uwsgi_log("[uwsgi-fileserve] unable to get realpath() of the static file\n");
#endif
		free(filename);
		return -1;
	}
	real_filename_len = strlen(real_filename);

	if (uwsgi.static_cache_paths) {
		uwsgi_wlock(uwsgi.static_cache_paths->lock);
		uwsgi_cache_set2(uwsgi.static_cache_paths, filename, filename_len, real_filename, real_filename_len, uwsgi.use_static_cache_paths, UWSGI_CACHE_FLAG_UPDATE);
		uwsgi_rwunlock(uwsgi.static_cache_paths->lock);
	}

found:
	free(filename);

	if (uwsgi_starts_with(real_filename, real_filename_len, document_root, document_root_len)) {
		struct uwsgi_string_list *safe = uwsgi.static_safe;
		while(safe) {
			if (!uwsgi_starts_with(real_filename, real_filename_len, safe->value, safe->len)) {
				goto safe;
			}		
			safe = safe->next;
		}
		uwsgi_log("[uwsgi-fileserve] security error: %s is not under %.*s or a safe path\n", real_filename, document_root_len, document_root);
		return -1;
	}

safe:

	if (!uwsgi_static_stat(wsgi_req, real_filename, &real_filename_len, &st, &index)) {

		if (index) {
			// if we are here the PATH_INFO need to be changed
			if (uwsgi_req_append_path_info_with_index(wsgi_req, index->value, index->len)) {
                        	return -1;
                        }
		}

		// skip methods other than GET and HEAD
        	if (uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "GET", 3) && uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "HEAD", 4)) {
			return -1;
        	}

		// check for skippable ext
		struct uwsgi_string_list *sse = uwsgi.static_skip_ext;
		while (sse) {
			if (real_filename_len >= sse->len) {
				if (!uwsgi_strncmp(real_filename + (real_filename_len - sse->len), sse->len, sse->value, sse->len)) {
					return -1;
				}
			}
			sse = sse->next;
		}

#ifdef UWSGI_ROUTING
		// before sending the file, we need to check if some rule applies
		if (!wsgi_req->is_routing && uwsgi_apply_routes_do(wsgi_req, NULL, 0) == UWSGI_ROUTE_BREAK) {
			return 0;
		}
		wsgi_req->routes_applied = 1;
#endif

		return uwsgi_real_file_serve(wsgi_req, real_filename, real_filename_len, &st);
	}

	return -1;

}
Пример #11
0
struct uwsgi_socket *uwsgi_new_socket(char *name) {

	struct uwsgi_socket *uwsgi_sock = uwsgi.sockets, *old_uwsgi_sock;
	struct sockaddr_in sin;
	socklen_t socket_type_len;

	if (!uwsgi_sock) {
		uwsgi.sockets = uwsgi_malloc(sizeof(struct uwsgi_socket));
		uwsgi_sock = uwsgi.sockets;
	}
	else {
		while (uwsgi_sock) {
			old_uwsgi_sock = uwsgi_sock;
			uwsgi_sock = uwsgi_sock->next;
		}

		uwsgi_sock = uwsgi_malloc(sizeof(struct uwsgi_socket));
		old_uwsgi_sock->next = uwsgi_sock;
	}

	memset(uwsgi_sock, 0, sizeof(struct uwsgi_socket));
	uwsgi_sock->name = name;
	uwsgi_sock->fd = -1;

	if (!name)
		return uwsgi_sock;

	if (name[0] == '=') {
		int shared_socket = atoi(uwsgi_sock->name + 1);
		if (shared_socket >= 0) {
			struct uwsgi_socket *uss = uwsgi_get_shared_socket_by_num(shared_socket);
			if (!uss) {
				uwsgi_log("unable to use shared socket %d\n", shared_socket);
				exit(1);
			}
			uwsgi_sock->bound = 1;
			uwsgi_sock->shared = 1;
			uwsgi_sock->from_shared = shared_socket;
			return uwsgi_sock;
		}
	}

	if (!uwsgi_startswith(name, "fd://", 5)) {
		uwsgi_add_socket_from_fd(uwsgi_sock, atoi(name + 5));
		return uwsgi_sock;
	}

	char *tcp_port = strrchr(name, ':');
	if (tcp_port) {
		// INET socket, check for 0 port
		if (tcp_port[1] == 0 || tcp_port[1] == '0') {
			uwsgi_sock->fd = bind_to_tcp(name, uwsgi.listen_queue, tcp_port);
			uwsgi_sock->family = AF_INET;
			uwsgi_sock->bound = 1;

			uwsgi_sock->auto_port = 1;

			socket_type_len = sizeof(struct sockaddr_in);

			if (getsockname(uwsgi_sock->fd, (struct sockaddr *) &sin, &socket_type_len)) {
				uwsgi_error("getsockname()");
				exit(1);
			}


			char *auto_port = uwsgi_num2str(ntohs(sin.sin_port));
			uwsgi_sock->name = uwsgi_concat3n(name, tcp_port - name, ":", 1, auto_port, strlen(auto_port));
		}
		// is it fd 0 ?
		else if (tcp_port[1] == ':') {
			uwsgi_sock->fd = 0;
			uwsgi_sock->family = AF_INET;
			uwsgi_sock->bound = 1;

			socket_type_len = sizeof(struct sockaddr_in);

			if (getsockname(0, (struct sockaddr *) &sin, &socket_type_len)) {
				uwsgi_error("getsockname()");
				exit(1);
			}


			char *auto_port = uwsgi_num2str(ntohs(sin.sin_port));
			char *auto_ip = inet_ntoa(sin.sin_addr);
			uwsgi_sock->name = uwsgi_concat3n(auto_ip, strlen(auto_ip), ":", 1, auto_port, strlen(auto_port));
		}
	}

	return uwsgi_sock;
}
Пример #12
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;
}
Пример #13
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;
}