From 0e2527f43d6b43ddba8139073703f986a8fa43d8 Mon Sep 17 00:00:00 2001 From: Jan-Piet Mens Date: Wed, 9 Sep 2015 18:31:41 +0200 Subject: [PATCH] feature: http: allow override user,device for last_users() via X-Limit- headers --- http.c | 95 ++++++++++++++++++++++++++++++------------------------- ocat.c | 3 +- storage.c | 22 +++++++++++-- storage.h | 2 +- 4 files changed, 74 insertions(+), 48 deletions(-) diff --git a/http.c b/http.c index 83c47f5..c5461a2 100644 --- a/http.c +++ b/http.c @@ -71,6 +71,35 @@ static int send_reply(struct mg_connection *conn) } } +/* + * Return a copy of a GET/POST parameter or NULL. The parameter + * may be overriden by an HTTP header called X-Limit-. + * Caller must free if return is non-NULL. + */ + +static char *field(struct mg_connection *conn, char *fieldname) +{ + char buf[BUFSIZ]; + int ret, n; + + snprintf(buf, sizeof(buf), "X-Limit-%s", fieldname); + + for (n = 0; n < conn->num_headers; n++) { + struct mg_header *hh; + + hh = &conn->http_headers[n]; + // fprintf(stderr, " %s=%s\n", hh->name, hh->value); + if (*hh->name == 'X' && strcasecmp(hh->name, buf) == 0) { + return (strdup(hh->value)); + } + } + + if ((ret = mg_get_var(conn, fieldname, buf, sizeof(buf))) > 0) { + return (strdup(buf)); + } + return (NULL); +} + /* * Push a list of LAST users down the Websocket. We send individual * JSON objects (not an array of them) because these are what the @@ -81,10 +110,17 @@ static void send_last(struct mg_connection *conn) { struct udata *ud = (struct udata *)conn->server_param; JsonNode *user_array, *o, *one; + char *u = NULL, *d = NULL; - if ((user_array = last_users()) != NULL) { + u = field(conn, "user"); + d = field(conn, "device"); + + if ((user_array = last_users(u, d)) != NULL) { char *js; + if (u) free(u); + if (d) free(d); + json_foreach(one, user_array) { JsonNode *f; @@ -131,34 +167,6 @@ static int json_response(struct mg_connection *conn, JsonNode *json) return (MG_TRUE); } -/* - * Return a copy of a GET/POST parameter or NULL. The parameter - * may be overriden by an HTTP header called X-Limit-. - * Caller must free if return is non-NULL. - */ - -static char *field(struct mg_connection *conn, char *fieldname) -{ - char buf[BUFSIZ]; - int ret, n; - - snprintf(buf, sizeof(buf), "X-Limit-%s", fieldname); - - for (n = 0; n < conn->num_headers; n++) { - struct mg_header *hh; - - hh = &conn->http_headers[n]; - // fprintf(stderr, " %s=%s\n", hh->name, hh->value); - if (*hh->name == 'X' && strcasecmp(hh->name, buf) == 0) { - return (strdup(hh->value)); - } - } - - if ((ret = mg_get_var(conn, fieldname, buf, sizeof(buf))) > 0) { - return (strdup(buf)); - } - return (NULL); -} /* * We are being called with the portion behind /api/0/ as in @@ -196,19 +204,20 @@ static int dispatch(struct mg_connection *conn, const char *uri) fprintf(stderr, "%d = %s\n", ret, uparts[ret]); } - if (nparts == 1 && !strcmp(uparts[0], "last")) { - JsonNode *user_array; - - if ((user_array = last_users()) != NULL) { - return (json_response(conn, user_array)); - } - } - u = field(conn, "user"); d = field(conn, "device"); time_from = field(conn, "from"); time_to = field(conn, "to"); + if (nparts == 1 && !strcmp(uparts[0], "last")) { + JsonNode *user_array; + + if ((user_array = last_users(u, d)) != NULL) { + CLEANUP; + return (json_response(conn, user_array)); + } + } + if ((ret = mg_get_var(conn, "limit", buf, sizeof(buf))) > 0) { limit = atoi(buf); } @@ -308,7 +317,12 @@ int ev_handler(struct mg_connection *conn, enum mg_event ev) case MG_REQUEST: -#if 0 +#if 1 + fprintf(stderr, "------------------------------ %s (%ld) %.*s\n", + conn->uri, + conn->content_len, + (int)conn->content_len, + conn->content); for (int n = 0; n < conn->num_headers; n++) { struct mg_header *hh; @@ -316,11 +330,6 @@ int ev_handler(struct mg_connection *conn, enum mg_event ev) fprintf(stderr, " %s=%s\n", hh->name, hh->value); } - fprintf(stderr, "%s (%ld) %.*s\n", - conn->uri, - conn->content_len, - (int)conn->content_len, - conn->content); #endif /* Websockets URI ?*/ if (strcmp(conn->uri, "/ws/last") == 0) { diff --git a/ocat.c b/ocat.c index cbd1b1d..8a5784b 100644 --- a/ocat.c +++ b/ocat.c @@ -315,7 +315,8 @@ int main(int argc, char **argv) if (last) { JsonNode *user_array; - if ((user_array = last_users()) != NULL) { + // FIXME: allow last_users with username, device + if ((user_array = last_users(NULL, NULL)) != NULL) { char *js; if ((js = json_stringify(user_array, JSON_INDENT)) != NULL) { diff --git a/storage.c b/storage.c index fed8832..4b714cd 100644 --- a/storage.c +++ b/storage.c @@ -146,10 +146,12 @@ void append_device_details(JsonNode *userlist, char *user, char *device) } /* - * Return an array of users gleaned from LAST with merged details + * Return an array of users gleaned from LAST with merged details. + * If user and device are specified, limit to those; either may be + * NULL. */ -JsonNode *last_users() +JsonNode *last_users(char *in_user, char *in_device) { JsonNode *obj = json_mkobject(); JsonNode *un, *dn, *userlist = json_mkarray(); @@ -157,6 +159,9 @@ JsonNode *last_users() snprintf(path, BUFSIZ, "%s/last", STORAGEDIR); + fprintf(stderr, "last_users(%s, %s)\n", (in_user) ? in_user : "", + (in_device) ? in_device : ""); + if (user_device_list(path, 0, obj) == 1) return (obj); @@ -171,7 +176,18 @@ JsonNode *last_users() } else if (dn->tag == JSON_NUMBER) { /* all digits? */ sprintf(device, "%.lf", dn->number_); } - append_device_details(userlist, user, device); + + if (!in_user && !in_device) { + append_device_details(userlist, user, device); + } else if (in_user && !in_device) { + if (strcmp(user, in_user) == 0) { + append_device_details(userlist, user, device); + } + } else if (in_user && in_device) { + if (strcmp(user, in_user) == 0 && strcmp(device, in_device) == 0) { + append_device_details(userlist, user, device); + } + } } } json_delete(obj); diff --git a/storage.h b/storage.h index 093952e..22a0815 100644 --- a/storage.h +++ b/storage.h @@ -21,7 +21,7 @@ int make_times(char *time_from, time_t *s_lo, char *time_to, time_t *s_to); JsonNode *geo_json(JsonNode *json); JsonNode *geo_linestring(JsonNode *location_array); JsonNode *kill_datastore(char *username, char *device); -JsonNode *last_users(); +JsonNode *last_users(char *user, char *device); char *gpx_string(JsonNode *json); void storage_init(int revgeo);