Return the status of token removal in auth_logout
[blerg.git] / http / http_blerg.c
index e205749..8a5b9a5 100644 (file)
@@ -29,12 +29,6 @@ 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;
@@ -174,22 +168,6 @@ void GET_generate_blergref_list_free(void *cls) {
        free(bs);
 }
 
-int POST_auth_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 auth_state *as = cls;
-
-       if (strncmp(key, "username", 9) == 0) {
-               if (size > 32) size = 32;
-               memcpy(as->username, data, size);
-               as->username[size] = 0;
-       } else if (strncmp(key, "password", 9) == 0) {
-               if (size > 32) size = 32;
-               memcpy(as->password, data, size);
-               as->password[size] = 0;
-       }
-
-       return MHD_YES;
-}
-
 int POST_put_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 put_state *ps = cls;
 
@@ -216,22 +194,98 @@ 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;
+int process_put(struct MHD_Connection *connection, const char *method, const char *upload_data, size_t *upload_data_size, void **ptr) {
+       struct put_state *ps = (struct put_state *) *ptr;
+
+       if (ps == NULL) {
+               if (strcmp(method, MHD_HTTP_METHOD_POST) != 0)
+                       return respond_405(connection);
+
+               *ptr = (void *) 1;
+
+               struct put_state *ps = malloc(sizeof(struct put_state));
+               ps->data = NULL;
+               ps->data_size = 0;
+               ps->pp = MHD_create_post_processor(connection, 16384, &POST_put_iterator, ps);
+               ps->username[0] = 0;
+               *ptr = ps;
+               return MHD_YES;
+       }
+
+       if (*upload_data_size) {
+               MHD_post_process(ps->pp, upload_data, *upload_data_size);
+               *upload_data_size = 0;
+               return MHD_YES;
+       }
+
+       return MHD_NO;
+}
+
+int process_and_check_put(struct MHD_Connection *connection, const char *method, const char *upload_data, size_t *upload_data_size, void **ptr) {
+       struct put_state *ps = (struct put_state *) *ptr;
+
+       if (process_put(connection, method, upload_data, upload_data_size, ptr) == MHD_YES)
+               return MHD_YES;
+
+       const char *given_token = MHD_lookup_connection_value(connection, MHD_COOKIE_KIND, "auth");
+       if (!auth_check_token(ps->username, given_token))
+               return respond_403(connection);
+
+       return MHD_NO;
+}
+
+int POST_auth_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 auth_state *as = 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) {
+               memcpy(as->username, data, size);
+               as->username[size] = 0;
+       } else if (strncmp(key, "password", 9) == 0) {
                if (size > 32) size = 32;
-               memcpy(ss->to, data, size);
-               ss->to[size] = 0;
+               memcpy(as->password, data, size);
+               as->password[size] = 0;
        }
 
        return MHD_YES;
 }
 
+int process_auth(struct MHD_Connection *connection, const char *method, const char *upload_data, size_t *upload_data_size, void **ptr) {
+       struct auth_state *as = (struct auth_state *) *ptr;
+
+       if (as == NULL) {
+               if (strcmp(method, MHD_HTTP_METHOD_POST) != 0)
+                       return respond_405(connection);
+
+               as = malloc(sizeof(struct auth_state));
+               as->username[0] = as->password[0] = 0;
+               as->pp = MHD_create_post_processor(connection, 1024, &POST_auth_iterator, as);
+               *ptr = as;
+               return MHD_YES;
+       }
+
+       if (*upload_data_size) {
+               MHD_post_process(as->pp, upload_data, *upload_data_size);
+               *upload_data_size = 0;
+               return MHD_YES;
+       }
+
+       return MHD_NO;
+}
+
+int process_and_check_auth(struct MHD_Connection *connection, const char *method, const char *upload_data, size_t *upload_data_size, void **ptr) {
+       struct auth_state *as = (struct auth_state *) *ptr;
+
+       if (process_auth(connection, method, upload_data, upload_data_size, ptr) == MHD_YES)
+               return MHD_YES;
+
+       const char *given_token = MHD_lookup_connection_value(connection, MHD_COOKIE_KIND, "auth");
+       if (!auth_check_token(as->username, given_token))
+               return respond_403(connection);
+
+       return MHD_NO;
+}
+
 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));
@@ -240,7 +294,6 @@ struct MHD_Response *create_response_for_range(struct blerg *b, uint64_t from, u
        uint64_t record_count = blerg_get_record_count(b);
 
        if (from > to || from >= record_count || to >= record_count || to - from > 99) {
-               blerg_close(b);
                free(gs);
                return NULL;
        }
@@ -365,36 +418,16 @@ ahc_derp (void *cls, struct MHD_Connection *connection, const char *url, const c
 
                return ret;
        } else if (strncmp(url, "/put", 4) == 0) {
-               struct put_state *ps = (struct put_state *) *ptr;
-               if (*ptr == NULL) {
-                       if (strcmp(method, MHD_HTTP_METHOD_POST) != 0)
-                               return respond_405(connection);
-
-                       if (url[4] == '/')
-                               return respond_404(connection);
-
-                       *ptr = (void *) 1;
-
-                       struct put_state *ps = malloc(sizeof(struct put_state));
-                       ps->data = NULL;
-                       ps->data_size = 0;
-                       ps->pp = MHD_create_post_processor(connection, 16384, &POST_put_iterator, ps);
-                       ps->username[0] = 0;
-                       *ptr = ps;
-                       return MHD_YES;
-               }
+               if (url[4] == '/')
+                       return respond_404(connection);
 
-               if (*upload_data_size) {
-                       MHD_post_process(ps->pp, upload_data, *upload_data_size);
-                       *upload_data_size = 0;
+               ret = process_and_check_put(connection, method, upload_data, upload_data_size, ptr);
+               if (ret == MHD_YES)
                        return MHD_YES;
-               }
 
-               if (ps->data == NULL || ps->data_size == 0 || ps->username[0] == 0)
-                       return respond_JSON_Failure(connection);
+               struct put_state *ps = (struct put_state *) *ptr;
 
-               const char *given_token = MHD_lookup_connection_value(connection, MHD_COOKIE_KIND, "auth");
-               if (!auth_check_token(ps->username, given_token))
+               if (ps->data == NULL || ps->data_size == 0)
                        return respond_JSON_Failure(connection);
 
                struct blerg *b = blerg_open(ps->username);
@@ -456,24 +489,11 @@ ahc_derp (void *cls, struct MHD_Connection *connection, const char *url, const c
 
                return ret;
        } else if (strncmp(url, "/create", 8) == 0) {
-               struct auth_state *as = (struct auth_state *) *ptr;
-
-               if (as == NULL) {
-                       if (strcmp(method, MHD_HTTP_METHOD_POST) != 0)
-                               return respond_405(connection);
-
-                       struct auth_state *as = malloc(sizeof(struct auth_state));
-                       as->username[0] = as->password[0] = 0;
-                       as->pp = MHD_create_post_processor(connection, 1024, &POST_auth_iterator, as);
-                       *ptr = as;
+               ret = process_auth(connection, method, upload_data, upload_data_size, ptr);
+               if (ret == MHD_YES)
                        return MHD_YES;
-               }
 
-               if (*upload_data_size) {
-                       MHD_post_process(as->pp, upload_data, *upload_data_size);
-                       *upload_data_size = 0;
-                       return MHD_YES;
-               }
+               struct auth_state *as = (struct auth_state *) *ptr;
 
                if (as->username[0] == 0 || as->password[0] == 0)
                        return respond_JSON_Failure(connection);
@@ -491,34 +511,21 @@ ahc_derp (void *cls, struct MHD_Connection *connection, const char *url, const c
 
                return respond_JSON_Success(connection);
        } else if (strncmp(url, "/login", 7) == 0) {
-               struct auth_state *as = (struct auth_state *) *ptr;
-
-               if (as == NULL) {
-                       if (strcmp(method, MHD_HTTP_METHOD_POST) != 0)
-                               return respond_405(connection);
-
-                       struct auth_state *as = malloc(sizeof(struct auth_state));
-                       as->username[0] = as->password[0] = 0;
-                       as->pp = MHD_create_post_processor(connection, 1024, &POST_auth_iterator, as);
-                       *ptr = as;
+               ret = process_auth(connection, method, upload_data, upload_data_size, ptr);
+               if (ret == MHD_YES)
                        return MHD_YES;
-               }
 
-               if (*upload_data_size) {
-                       MHD_post_process(as->pp, upload_data, *upload_data_size);
-                       *upload_data_size = 0;
-                       return MHD_YES;
-               }
+               struct auth_state *as = (struct auth_state *) *ptr;
 
                if (as->username[0] == 0 || as->password[0] == 0)
                        return respond_JSON_Failure(connection);
 
-               if (!auth_login(as->username, as->password))
+               char *token = auth_login(as->username, as->password);
+               if (token == NULL)
                        return respond_JSON_Failure(connection);
 
                response = MHD_create_response_from_data(strlen(JSON_SUCCESS), JSON_SUCCESS, MHD_NO, MHD_NO);
 
-               char *token = auth_get_token(as->username);
                data = malloc(512);
                snprintf(data, 512, "auth=%s", token);
                MHD_add_response_header(response, "Set-Cookie", data);
@@ -534,104 +541,96 @@ ahc_derp (void *cls, struct MHD_Connection *connection, const char *url, const c
 
                return ret;
        } else if (strncmp(url, "/logout", 8) == 0) {
-               struct auth_state *as = (struct auth_state *) *ptr;
-
-               if (as == NULL) {
-                       if (strcmp(method, MHD_HTTP_METHOD_POST) != 0)
-                               return respond_405(connection);
-
-                       struct auth_state *as = malloc(sizeof(struct auth_state));
-                       as->username[0] = as->password[0] = 0;
-                       as->pp = MHD_create_post_processor(connection, 1024, &POST_auth_iterator, as);
-                       *ptr = as;
+               ret = process_and_check_auth(connection, method, upload_data, upload_data_size, ptr);
+               if (ret == MHD_YES)
                        return MHD_YES;
-               }
 
-               if (*upload_data_size) {
-                       MHD_post_process(as->pp, upload_data, *upload_data_size);
-                       *upload_data_size = 0;
-                       return MHD_YES;
-               }
+               struct auth_state *as = (struct auth_state *) *ptr;
 
                const char *given_token = MHD_lookup_connection_value(connection, MHD_COOKIE_KIND, "auth");
-               if (auth_check_token(as->username, given_token)) {
-                       auth_logout(as->username);
-                       return respond_JSON_Success(connection);
-               } else {
-                       return respond_JSON_Failure(connection);
-               }
-       } else if (strncmp(url, "/subscribe", 11) == 0 || strncmp(url, "/unsubscribe", 13) == 0) {
-               struct subscribe_state *ss = (struct subscribe_state *) *ptr;
+               auth_logout(as->username, given_token);
+               return respond_JSON_Success(connection);
+       } else if (strncmp(url, "/subscribe", 10) == 0 || strncmp(url, "/unsubscribe", 12) == 0) {
+               ret = process_and_check_auth(connection, method, upload_data, upload_data_size, ptr);
+               if (ret == MHD_YES)
+                       return MHD_YES;
 
-               if (ss == NULL) {
-                       if (strcmp(method, MHD_HTTP_METHOD_POST) != 0)
-                               return respond_405(connection);
+               struct auth_state *as = (struct auth_state *) *ptr;
 
-                       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 (url[1] == 'u') {
+                       if (url[12] != '/')
+                               return respond_404(connection);
 
-               if (*upload_data_size) {
-                       MHD_post_process(ss->pp, upload_data, *upload_data_size);
-                       *upload_data_size = 0;
-                       return MHD_YES;
-               }
+                       ret = parse_url_info(url + 13, &info);
+                       if ((ret & URL_INFO_NAME) == 0)
+                               return respond_404(connection);
 
-               const char *given_token = MHD_lookup_connection_value(connection, MHD_COOKIE_KIND, "auth");
-               if (auth_check_token(ss->username, given_token)) {
-                       if (url[1] == 'u') {
-                               subscription_remove(ss->username, ss->to);
-                       } else {
-                               subscription_add(ss->username, ss->to);
-                       }
-                       return respond_JSON_Success(connection);
+                       subscription_remove(as->username, info.name);
                } else {
-                       return respond_JSON_Failure(connection);
+                       if (url[10] != '/')
+                               return respond_404(connection);
+
+                       ret = parse_url_info(url + 11, &info);
+                       if ((ret & URL_INFO_NAME) == 0)
+                               return respond_404(connection);
+
+                       subscription_add(as->username, info.name);
                }
+               return respond_JSON_Success(connection);
        } else if (strncmp(url, "/feed", 6) == 0) {
+               ret = process_and_check_auth(connection, method, upload_data, upload_data_size, ptr);
+               if (ret == MHD_YES)
+                       return MHD_YES;
+
                struct auth_state *as = (struct auth_state *) *ptr;
 
-               if (as == NULL) {
-                       if (strcmp(method, MHD_HTTP_METHOD_POST) != 0)
-                               return respond_405(connection);
+               int recs = 50;
+               struct blergref *feedlist = subscription_list(as->username, 0, &recs, -1);
 
-                       struct auth_state *as = malloc(sizeof(struct auth_state));
-                       as->username[0] = as->password[0] = 0;
-                       as->pp = MHD_create_post_processor(connection, 1024, &POST_auth_iterator, as);
-                       *ptr = as;
-                       return MHD_YES;
+               if (recs == 0) {
+                       response = MHD_create_response_from_data(2, "[]", MHD_NO, MHD_NO);
+               } else {
+                       response = create_blergref_response(feedlist, recs);
                }
 
-               if (*upload_data_size) {
-                       MHD_post_process(as->pp, upload_data, *upload_data_size);
-                       *upload_data_size = 0;
+               if (response == NULL)
+                       return respond_JSON_Failure(connection);
+
+               ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
+               MHD_destroy_response(response);
+
+               return ret;
+       } else if (strncmp(url, "/feedinfo", 9) == 0) {
+               ret = process_and_check_auth(connection, method, upload_data, upload_data_size, ptr);
+               if (ret == MHD_YES)
                        return MHD_YES;
-               }
 
-               const char *given_token = MHD_lookup_connection_value(connection, MHD_COOKIE_KIND, "auth");
-               if (auth_check_token(as->username, given_token)) {
-                       int recs = 50;
-                       struct blergref *feedlist = subscription_list(as->username, 0, &recs, -1);
+               struct auth_state *as = (struct auth_state *) *ptr;
 
-                       if (recs == 0) {
-                               response = MHD_create_response_from_data(2, "[]", MHD_NO, MHD_NO);
-                       } else {
-                               response = create_blergref_response(feedlist, recs);
-                       }
+               if (url[9] != '/')
+                       return respond_404(connection);
 
-                       if (response == NULL)
-                               return respond_JSON_Failure(connection);
+               ret = parse_url_info(url + 10, &info);
+               if ((ret & URL_INFO_NAME) == 0)
+                       return respond_404(connection);
 
-                       ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
-                       MHD_destroy_response(response);
+               yajl_gen g = yajl_gen_alloc(&yajl_c, NULL);
+               yajl_gen_map_open(g);
+               yajl_gen_string(g, "subscribed", 10);
+               yajl_gen_bool(g, is_subscribed(as->username, info.name));
+               yajl_gen_map_close(g);
 
-                       return ret;
-               } else {
-                       return respond_JSON_Failure(connection);
-               }
+               const unsigned char *ybuf;
+               yajl_gen_get_buf(g, &ybuf, &len);
+
+               response = MHD_create_response_from_data(len, (void *)ybuf, MHD_NO, MHD_YES);
+               ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
+               MHD_destroy_response(response);
+
+               yajl_gen_free(g);
+               free(as);
+
+               return ret;
        } else {
                return respond_404(connection);
        }