X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fuhttpd.git;a=blobdiff_plain;f=ubus.c;h=269f7cdf85ed7195964399e9449cd97a65a9c595;hp=0d41c2dd6b7f3b712f9dd3e725e7b6f2f0a6f2cc;hb=fd8e5e379c23c5fbcec3e76894b839233df09067;hpb=3864c083a42e713e291bd954b2fa6fe2b85e930a diff --git a/ubus.c b/ubus.c index 0d41c2d..269f7cd 100644 --- a/ubus.c +++ b/ubus.c @@ -104,6 +104,13 @@ static const struct { [ERROR_TIMEOUT] = { -32003, "ubus request timed out" }, }; +enum cors_hdr { + HDR_ORIGIN, + HDR_ACCESS_CONTROL_REQUEST_METHOD, + HDR_ACCESS_CONTROL_REQUEST_HEADERS, + __HDR_MAX +}; + static void __uh_ubus_next_batched_request(struct uloop_timeout *timeout); static void uh_ubus_next_batched_request(struct client *cl) @@ -114,10 +121,52 @@ static void uh_ubus_next_batched_request(struct client *cl) uloop_timeout_set(&du->timeout, 1); } +static void uh_ubus_add_cors_headers(struct client *cl) +{ + struct blob_attr *tb[__HDR_MAX]; + static const struct blobmsg_policy hdr_policy[__HDR_MAX] = { + [HDR_ORIGIN] = { "origin", BLOBMSG_TYPE_STRING }, + [HDR_ACCESS_CONTROL_REQUEST_METHOD] = { "access-control-request-method", BLOBMSG_TYPE_STRING }, + [HDR_ACCESS_CONTROL_REQUEST_HEADERS] = { "access-control-request-headers", BLOBMSG_TYPE_STRING }, + }; + + blobmsg_parse(hdr_policy, __HDR_MAX, tb, blob_data(cl->hdr.head), blob_len(cl->hdr.head)); + + if (!tb[HDR_ORIGIN]) + return; + + if (tb[HDR_ACCESS_CONTROL_REQUEST_METHOD]) + { + char *hdr = (char *) blobmsg_data(tb[HDR_ACCESS_CONTROL_REQUEST_METHOD]); + + if (strcmp(hdr, "POST") && strcmp(hdr, "OPTIONS")) + return; + } + + ustream_printf(cl->us, "Access-Control-Allow-Origin: %s\r\n", + blobmsg_data(tb[HDR_ORIGIN])); + + if (tb[HDR_ACCESS_CONTROL_REQUEST_HEADERS]) + ustream_printf(cl->us, "Access-Control-Allow-Headers: %s\r\n", + blobmsg_data(tb[HDR_ACCESS_CONTROL_REQUEST_HEADERS])); + + ustream_printf(cl->us, "Access-Control-Allow-Methods: POST, OPTIONS\r\n"); + ustream_printf(cl->us, "Access-Control-Allow-Credentials: true\r\n"); +} + static void uh_ubus_send_header(struct client *cl) { ops->http_header(cl, 200, "OK"); - ustream_printf(cl->us, "Content-Type: application/json\r\n\r\n"); + + if (conf.ubus_cors) + uh_ubus_add_cors_headers(cl); + + ustream_printf(cl->us, "Content-Type: application/json\r\n"); + + if (cl->request.method == UH_HTTP_MSG_OPTIONS) + ustream_printf(cl->us, "Content-Length: 0\r\n"); + + ustream_printf(cl->us, "\r\n"); } static void uh_ubus_send_response(struct client *cl) @@ -127,19 +176,17 @@ static void uh_ubus_send_response(struct client *cl) char *str; if (du->array && du->array_idx > 1) - sep = ", "; + sep = ","; - str = blobmsg_format_json_indent(buf.head, true, du->array); + str = blobmsg_format_json(buf.head, true); ops->chunk_printf(cl, "%s%s", sep, str); free(str); du->jsobj_cur = NULL; if (du->array) uh_ubus_next_batched_request(cl); - else { - ops->chunk_printf(cl, "\n"); + else return ops->request_done(cl); - } } static void uh_ubus_init_response(struct client *cl) @@ -332,6 +379,8 @@ static void uh_ubus_send_list(struct client *cl, json_object *obj, struct blob_a blob_buf_init(data.buf, 0); + uh_client_ref(cl); + if (!params || blob_id(params) != BLOBMSG_TYPE_ARRAY) { r = blobmsg_open_array(data.buf, "result"); ubus_lookup(ctx, NULL, uh_ubus_list_cb, &data); @@ -351,6 +400,8 @@ static void uh_ubus_send_list(struct client *cl, json_object *obj, struct blob_a blobmsg_close_table(data.buf, r); } + uh_client_unref(cl); + uh_ubus_init_response(cl); blobmsg_add_blob(&buf, blob_data(data.buf->head)); uh_ubus_send_response(cl); @@ -415,12 +466,12 @@ static void uh_ubus_init_batch(struct client *cl) du->array = true; uh_ubus_send_header(cl); - ops->chunk_printf(cl, "[\n\t"); + ops->chunk_printf(cl, "["); } static void uh_ubus_complete_batch(struct client *cl) { - ops->chunk_printf(cl, "\n]\n"); + ops->chunk_printf(cl, "]"); ops->request_done(cl); } @@ -448,7 +499,7 @@ static bool uh_ubus_allowed(const char *sid, const char *obj, const char *fun) return false; blob_buf_init(&req, 0); - blobmsg_add_string(&req, "sid", sid); + blobmsg_add_string(&req, "ubus_rpc_session", sid); blobmsg_add_string(&req, "object", obj); blobmsg_add_string(&req, "function", fun); @@ -463,6 +514,8 @@ static void uh_ubus_handle_request_object(struct client *cl, struct json_object struct rpc_data data = {}; enum rpc_error err = ERROR_PARSE; + uh_client_ref(cl); + if (json_object_get_type(obj) != json_type_object) goto error; @@ -506,6 +559,8 @@ error: out: if (data.params) free(data.params); + + uh_client_unref(cl); } static void __uh_ubus_next_batched_request(struct uloop_timeout *timeout) @@ -565,14 +620,24 @@ static void uh_ubus_handle_request(struct client *cl, char *url, struct path_inf blob_buf_init(&buf, 0); - if (cl->request.method != UH_HTTP_MSG_POST) - return ops->client_error(cl, 400, "Bad Request", "Invalid Request"); + switch (cl->request.method) + { + case UH_HTTP_MSG_POST: + d->data_send = uh_ubus_data_send; + d->data_done = uh_ubus_data_done; + d->close_fds = uh_ubus_close_fds; + d->free = uh_ubus_request_free; + d->ubus.jstok = json_tokener_new(); + break; + + case UH_HTTP_MSG_OPTIONS: + uh_ubus_send_header(cl); + ops->request_done(cl); + break; - d->close_fds = uh_ubus_close_fds; - d->free = uh_ubus_request_free; - d->data_send = uh_ubus_data_send; - d->data_done = uh_ubus_data_done; - d->ubus.jstok = json_tokener_new(); + default: + ops->client_error(cl, 400, "Bad Request", "Invalid Request"); + } } static bool