Add /info method to cgi_blerg
[blerg.git] / cgi / cgi_blerg.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <cgi-util.h>
5 #include <yajl/yajl_gen.h>
6 #include "database.h"
7 #include "tags.h"
8 #include "auth.h"
9 #include "app.h"
10 #include "config.h"
11
12 yajl_gen_config yajl_c = { 0, 0 };
13
14 void respond_simple_data(unsigned const char *data, int len) {
15         printf("Content-length: %d\r\n\r\n", len);
16         write(0, data, len);
17 }
18
19 void respond_404() {
20         printf("Status: 404 Not Found\r\n");
21         printf("Content-type: text/html\r\n");
22         printf("Content-length: %d\r\n\r\n", strlen(CONTENT_404));
23
24         printf(CONTENT_404);
25 }
26
27 void respond_405() {
28         printf("Status: 405 Method Not Allowed\r\n");
29         printf("Content-type: text/html\r\n");
30         printf("Content-length: %d\r\n\r\n", strlen(CONTENT_405));
31
32         printf(CONTENT_405);
33 }
34
35 void respond_JSON_Failure() {
36         respond_simple_data(JSON_FAILURE, strlen(JSON_FAILURE));
37 }
38
39 void respond_JSON_Success() {
40         respond_simple_data(JSON_SUCCESS, strlen(JSON_SUCCESS));
41 }
42
43 void respond_for_range(struct blerg *b, uint64_t from, uint64_t to) {
44         const unsigned char *ybuf;
45         char number[21];
46         unsigned int len;
47         uint64_t i;
48         yajl_gen g;
49         uint64_t record_count = blerg_get_record_count(b);
50
51         printf("Content-type: application/json\r\n\r\n");
52
53         if (from > to || from >= record_count || to >= record_count || to - from > 99) {
54                 respond_JSON_Failure();
55                 return;
56         }
57
58         g = yajl_gen_alloc(&yajl_c, NULL);
59         yajl_gen_array_open(g);
60
61         for (i = to; i != from - 1; i--) {
62                 json_generate_one_record(g, NULL, b, i);
63                 yajl_gen_get_buf(g, &ybuf, &len);
64                 write(0, ybuf, len);
65                 yajl_gen_clear(g);
66         }
67
68         yajl_gen_array_close(g);
69         yajl_gen_get_buf(g, &ybuf, &len);
70         write(0, ybuf, len);
71         yajl_gen_free(g);
72 }
73
74 int main(int argc, char *argv[]) {
75         char *path;
76         char *request_method;
77         int ret, len;
78         struct url_info info;
79         char *data;
80
81         if (cgi_init() != CGIERR_NONE)
82                 exit(0);
83
84         path = getenv("PATH_INFO");
85         if (path == NULL) {
86                 respond_404();
87                 exit(0);
88         }
89         request_method = getenv("REQUEST_METHOD");
90
91         if (strncmp(path, "/get", 4) == 0 && strlen(path) > 4) {
92                 if (strncmp(request_method, "GET", 4) != 0) {
93                         respond_405();
94                         exit(0);
95                 }
96
97                 if (path[4] != '/') {
98                         respond_404();
99                         exit(0);
100                 }
101
102                 ret = parse_url_info(path + 5, &info);
103                 if ((ret & URL_INFO_AUTHOR) == 0) {
104                         respond_404();
105                         exit(0);
106                 }
107
108                 if (!blerg_exists(info.author)) {
109                         respond_404();
110                         exit(0);
111                 }
112
113                 struct blerg *b = blerg_open(info.author);
114
115                 if ((ret & URL_INFO_RECORD) && (ret & URL_INFO_RECORD_TO)) {
116                         respond_for_range(b, info.record, info.record_to);
117                 } else if (ret & URL_INFO_RECORD) {
118                         ret = blerg_fetch(b, info.record, &data, &len);
119
120                         if (ret == 0) {
121                                 respond_404();
122                                 exit(0);
123                         }
124                         respond_simple_data(data, len);
125                 } else {
126                         uint64_t record_count, from, to;
127                         record_count = blerg_get_record_count(b);
128                         if (record_count == 0) {
129                                 respond_simple_data("[]", 2);
130                         } else {
131                                 to = record_count - 1;
132                                 from = (record_count > 50 ? to - 49 : 0);
133                                 respond_for_range(b, from, to);
134                         }
135                 }
136
137                 blerg_close(b);
138         } else if (strncmp(path, "/info", 5) == 0) {
139                 if (strcmp(request_method, "GET") != 0) {
140                         respond_405();
141                         exit(0);
142                 }
143
144                 if (path[5] != '/') {
145                         respond_404();
146                         exit(0);
147                 }
148
149                 ret = parse_url_info(path + 6, &info);
150                 if ((ret & URL_INFO_AUTHOR) == 0) {
151                         respond_404();
152                         exit(0);
153                 }
154
155                 if (!blerg_exists(info.author)) {
156                         respond_404();
157                         exit(0);
158                 }
159
160                 struct blerg *b = blerg_open(info.author);
161                 uint64_t record_count = blerg_get_record_count(b);
162                 blerg_close(b);
163
164                 char number[21];
165                 yajl_gen g = yajl_gen_alloc(&yajl_c, NULL);
166                 yajl_gen_map_open(g);
167                 yajl_gen_string(g, "record_count", 12);
168                 snprintf(number, 21, "%llu", record_count);
169                 yajl_gen_string(g, number, strlen(number));
170                 yajl_gen_map_close(g);
171
172                 const unsigned char *ybuf;
173                 yajl_gen_get_buf(g, &ybuf, &len);
174
175                 printf("Content-type: application/json\r\n");
176                 printf("Content-length: %d\r\n\r\n", len);
177                 write(0, ybuf, len);
178
179                 yajl_gen_free(g);
180         } else {
181                 respond_404();
182                 exit(0);
183         }
184
185         cgi_quit();
186 }