Add some subscription (a.k.a. "follow") functionality
[blerg.git] / http / http_blerg.c
index 1a751ac..a6d3a5f 100644 (file)
@@ -28,6 +28,12 @@ struct put_state {
        int data_size;
 };
 
+struct subscribe_state {
+       struct MHD_PostProcessor *pp;
+       char username[33];
+       char to[33];
+};
+
 struct get_state {
        struct blerg *b;
        yajl_gen g;
@@ -75,7 +81,7 @@ ssize_t GET_generate_list(void *cls, uint64_t pos, char *buf, size_t max) {
        }
 
        /* Snarf one record */
-       json_generate_one_record(gs->g, NULL, gs->b, gs->entries[gs->i]);
+       json_generate_one_record(gs->g, NULL, gs->b, gs->entries[gs->i], 0);
 
        if (gs->i == 0) {
                yajl_gen_array_close(gs->g);
@@ -136,7 +142,7 @@ ssize_t GET_generate_taglist(void *cls, uint64_t pos, char *buf, size_t max) {
        /* Snarf one record */
        b = blerg_open(ts->results[ts->i].author);
        if (b != NULL) {
-               json_generate_one_record(ts->g, ts->results[ts->i].author, b, ts->results[ts->i].record);
+               json_generate_one_record(ts->g, ts->results[ts->i].author, b, ts->results[ts->i].record, 0);
                blerg_close(b);
        }
 
@@ -209,6 +215,22 @@ int POST_put_iterator(void *cls, enum MHD_ValueKind kind, const char *key, const
        return MHD_YES;
 }
 
+int POST_subscribe_iterator(void *cls, enum MHD_ValueKind kind, const char *key, const char *filename, const char *content_type, const char *transfer_encoding, const char *data, uint64_t off, size_t size) {
+       struct subscribe_state *ss = cls;
+
+       if (strncmp(key, "username", 9) == 0) {
+               if (size > 32) size = 32;
+               memcpy(ss->username, data, size);
+               ss->username[size] = 0;
+       } else if (strncmp(key, "to", 3) == 0) {
+               if (size > 32) size = 32;
+               memcpy(ss->to, data, size);
+               ss->to[size] = 0;
+       }
+
+       return MHD_YES;
+}
+
 struct MHD_Response *create_response_for_range(struct blerg *b, uint64_t from, uint64_t to) {
        struct MHD_Response *response;
        struct get_state *gs = malloc(sizeof(struct get_state));
@@ -264,15 +286,15 @@ ahc_derp (void *cls, struct MHD_Connection *connection, const char *url, const c
                        return respond_404(connection);
 
                ret = parse_url_info(url + 5, &info);
-               if ((ret & URL_INFO_AUTHOR) == 0)
+               if ((ret & URL_INFO_NAME) == 0)
                        return respond_404(connection);
 
-               if (!blerg_exists(info.author))
+               if (!blerg_exists(info.name))
                        return respond_404(connection);
 
                *ptr == NULL;
 
-               struct blerg *b = blerg_open(info.author);
+               struct blerg *b = blerg_open(info.name);
 
                if ((ret & URL_INFO_RECORD) && (ret & URL_INFO_RECORD_TO)) {
                        response = create_response_for_range(b, info.record, info.record_to);
@@ -317,14 +339,14 @@ ahc_derp (void *cls, struct MHD_Connection *connection, const char *url, const c
                        return respond_404(connection);
 
                ret = parse_url_info(url + 5, &info);
-               if ((ret & URL_INFO_AUTHOR) == 0)
+               if ((ret & URL_INFO_NAME) == 0)
                        return respond_404(connection);
 
-               if (!tag_exists(info.author))
+               if (!tag_exists(info.name))
                        return respond_404(connection);
 
                int recs = 50;
-               struct tag *taglist = tag_list(info.author, 0, &recs, -1);
+               struct tag *taglist = tag_list(info.name, 0, &recs, -1);
 
                if (recs == 0) {
                        response = MHD_create_response_from_data(2, "[]", MHD_NO, MHD_NO);
@@ -400,15 +422,15 @@ ahc_derp (void *cls, struct MHD_Connection *connection, const char *url, const c
                        return respond_404(connection);
 
                ret = parse_url_info(url + 6, &info);
-               if ((ret & URL_INFO_AUTHOR) == 0)
+               if ((ret & URL_INFO_NAME) == 0)
                        return respond_404(connection);
 
-               if (!blerg_exists(info.author))
+               if (!blerg_exists(info.name))
                        return respond_404(connection);
 
                *ptr == NULL;
 
-               struct blerg *b = blerg_open(info.author);
+               struct blerg *b = blerg_open(info.name);
                uint64_t record_count = blerg_get_record_count(b);
                blerg_close(b);
 
@@ -535,6 +557,33 @@ ahc_derp (void *cls, struct MHD_Connection *connection, const char *url, const c
                } else {
                        return respond_JSON_Failure(connection);
                }
+       } else if (strncmp(url, "/subscribe", 11) == 0) {
+               struct subscribe_state *ss = (struct subscribe_state *) *ptr;
+
+               if (ss == NULL) {
+                       if (strcmp(method, MHD_HTTP_METHOD_POST) != 0)
+                               return respond_405(connection);
+
+                       struct subscribe_state *ss = malloc(sizeof(struct subscribe_state));
+                       ss->username[0] = ss->to[0] = 0;
+                       ss->pp = MHD_create_post_processor(connection, 1024, &POST_subscribe_iterator, ss);
+                       *ptr = ss;
+                       return MHD_YES;
+               }
+
+               if (*upload_data_size) {
+                       MHD_post_process(ss->pp, upload_data, *upload_data_size);
+                       *upload_data_size = 0;
+                       return MHD_YES;
+               }
+
+               const char *given_token = MHD_lookup_connection_value(connection, MHD_COOKIE_KIND, "auth");
+               if (auth_check_token(ss->username, given_token)) {
+                       subscription_add(ss->username, ss->to);
+                       return respond_JSON_Success(connection);
+               } else {
+                       return respond_JSON_Failure(connection);
+               }
        } else {
                return respond_404(connection);
        }
@@ -548,7 +597,7 @@ int main(int argc, char *argv[]) {
 
        init_responses();
 
-       daemon = MHD_start_daemon(MHD_USE_DEBUG, 8080, NULL, NULL, &ahc_derp, NULL, MHD_OPTION_END);
+       daemon = MHD_start_daemon(MHD_USE_DEBUG, HTTP_BLERG_PORT, NULL, NULL, &ahc_derp, NULL, MHD_OPTION_END);
        if (daemon == NULL) {
                fprintf(stderr, "Could not start web server\n");
                return 1;