8543fb8195f6baa2809d31499cb278ec02ab1a46
[blerg.git] / http_blerg.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <microhttpd.h>
5 #include "database.h"
6 #include "tags.h"
7
8 #define URL_INFO_AUTHOR 0x1
9 #define URL_INFO_RECORD 0x2
10 #define DERP "DERP DERP DERP"
11 #define NOTFOUND "<html><head><title>404 Not Found</title></head><body><h1>404 Not Found</h1>I couldn't find that.</body></html>"
12
13 struct MHD_Response *response404;
14
15 void init_responses() {
16         response404 = MHD_create_response_from_data(strlen(NOTFOUND), NOTFOUND, MHD_NO, MHD_NO);
17 }
18
19 int respond_404(struct MHD_Connection *connection) {
20         return MHD_queue_response(connection, MHD_HTTP_NOT_FOUND, response404);
21 }
22
23 int parse_url_info(const char *url, char *author, uint64_t *record) {
24         const char *c;
25         int ret = 0;
26         int len;
27
28         c = strchr(url, '/');
29         if (c == NULL) {
30                 len = strlen(url);
31         } else {
32                 len = c - url;
33         }
34         if (len == 0)
35                 return 0;
36         memcpy(author, url, len);
37         author[len] = 0;
38         ret |= URL_INFO_AUTHOR;
39
40         if (c != NULL && c[1] != 0) {
41                 *record = strtoull(c + 1, NULL, 10);
42                 ret |= URL_INFO_RECORD;
43         }
44
45         return ret;
46 }
47
48 static int
49 ahc_derp (void *cls, struct MHD_Connection *connection, const char *url, const char *method,
50           const char *version, const char *upload_data, size_t *upload_data_size, void **ptr) {
51         struct MHD_Response *response;
52         int ret, len;
53         char author[33];
54         uint64_t record;
55         char *data;
56
57         if (strncmp(url, "/get", 4) == 0 && strlen(url) > 4) {
58                 if (strcmp(method, MHD_HTTP_METHOD_GET) != 0)
59                         return MHD_NO;
60                 if (url[4] != '/')
61                         return respond_404(connection);
62                 ret = parse_url_info(url + 5, author, &record);
63                 if (ret & URL_INFO_AUTHOR == 0)
64                         return respond_404(connection);
65
66                 if (ret & URL_INFO_RECORD) {
67                         if (*ptr == NULL) {
68                                 *ptr = (void *) 1;
69                                 return MHD_YES;
70                         } else {
71                                 *ptr == NULL;
72
73                                 struct blerg *b = blerg_open(author);
74                                 ret = blerg_fetch(b, record, &data, &len);
75                                 blerg_close(b);
76
77                                 if (ret == 0) {
78                                         return respond_404(connection);
79                                 } else {
80                                         response = MHD_create_response_from_data(len, data, MHD_YES, MHD_NO);
81                                         ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
82                                 }
83                                 MHD_destroy_response(response);
84                                 return ret;
85                         }
86                 } else {
87                         if (*ptr == NULL) {
88                                 *ptr = (void*) 1;
89                                 return MHD_YES;
90                         } else {
91                                 *ptr == NULL;
92                                 response = MHD_create_response_from_data(strlen(DERP), DERP, MHD_NO, MHD_NO);
93                                 ret = MHD_queue_response(connection, MHD_HTTP_OK, response);
94                                 MHD_destroy_response(response);
95                                 return ret;
96                         }
97                 }
98         } else if (strncmp(url, "/put", 4) == 0) {
99                 char *username;
100                 const char *password = "testpass";
101                 const char *realm = "Blerg Post";
102
103 #define OPAQUE "d29fb6db8f21a6e99903651a9f87470e"
104 #define DENIED "DENIED, MOTHERFUCKER"
105 #define PAGE "DERP DERP AUTHENTICATED DERP"
106
107                 if (*ptr == NULL) {
108                         *ptr = (void *) 1;
109
110                         username = MHD_digest_auth_get_username(connection);
111                         if (username == NULL) {
112                                 response = MHD_create_response_from_data(strlen (DENIED), DENIED, MHD_NO, MHD_NO);  
113                                 ret = MHD_queue_auth_fail_response(connection, realm, OPAQUE, response, MHD_NO);    
114                                 MHD_destroy_response(response);  
115                                 return ret;
116                         }
117
118                         printf("username: %s\n", username);
119
120                         ret = MHD_digest_auth_check(connection, realm, username, password, 300);
121                         free(username);
122
123                         if (ret == MHD_INVALID_NONCE || ret == MHD_NO) {
124                                 response = MHD_create_response_from_data(strlen (DENIED), DENIED, MHD_NO, MHD_NO);  
125                                 ret = MHD_queue_auth_fail_response(connection, realm, OPAQUE, response,
126                                                                    (ret == MHD_INVALID_NONCE) ? MHD_YES : MHD_NO);       
127                                 MHD_destroy_response(response);  
128                                 return ret;
129                         }
130                 }
131
132                 *ptr = NULL;
133
134                 if (url[4] != '/')
135                         return respond_404(connection);
136                 ret = parse_url_info(url + 5, author, &record);
137                 if ((ret & URL_INFO_AUTHOR) == 0)
138                         return respond_404(connection);
139
140                 response = MHD_create_response_from_data(strlen(PAGE), PAGE, MHD_NO, MHD_NO);
141                 ret = MHD_queue_response(connection, MHD_HTTP_OK, response);  
142                 MHD_destroy_response(response);
143                 return ret;
144         } else {
145                 return respond_404(connection);
146         }
147 }
148
149
150 int main(int argc, char *argv[]) {
151         struct MHD_Daemon *daemon;
152         fd_set rs, ws, es;
153         int max;
154
155         init_responses();
156
157         daemon = MHD_start_daemon(MHD_USE_DEBUG, 8080, NULL, NULL, &ahc_derp, NULL, MHD_OPTION_END);
158         if (daemon == NULL) {
159                 fprintf(stderr, "Could not start web server\n");
160                 return 1;
161         }
162
163         while (1) {
164                 FD_ZERO(&rs); FD_ZERO(&ws); FD_ZERO(&es);
165                 if (MHD_get_fdset(daemon, &rs, &ws, &es, &max) != MHD_YES) {
166                         fprintf(stderr, "Fatal error getting fd sets\n");
167                         break;
168                 }
169                 select(max + 1, &rs, &ws, &es, NULL);
170                 MHD_run(daemon);
171         }
172         MHD_stop_daemon(daemon);
173         return 0;
174 }