remove 'deref_to_tree', not needed anymore
[webgit] / src / query.c
1 /*
2     cehtehs git web frontend
3
4   Copyright (C)
5     2007, 2008,         Christian Thaeter <ct@pipapo.org>
6
7   This program is free software: you can redistribute it and/or modify
8   it under the terms of the GNU Affero General Public License as published by
9   the Free Software Foundation, either version 3 of the License, or
10   (at your option) any later version.
11
12   This program is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   GNU Affero General Public License for more details.
16
17   You should have received a copy of the GNU Affero General Public License
18   along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21
22 #include "query.h"
23 #include "repo.h"
24
25 #include "cwa.h"
26
27 #include <stdint.h>
28 #include <time.h>
29
30 void
31 webgit_query_init (struct webgit_query* q)
32 {
33   q->request = NULL;
34   q->now = time (NULL);
35
36   q->content_type = cwa_strndup ("application/xhtml+xml", SIZE_MAX);
37
38   q->login_cookie = NULL;
39   q->prefs_cookie = NULL;
40   q->cookie_expire = 365UL * 86400UL; /*1 year*/
41
42   q->count_def = 100;
43   q->rxpd = NULL;
44   q->skindir = cwa_strndup (WEBGIT_SKINDIR_DEFAULT, SIZE_MAX);
45   q->webskindir = cwa_strndup (WEBGIT_WEBSKINDIR_DEFAULT, SIZE_MAX);
46   q->secret = NULL;
47   q->accountdir = NULL;
48   q->maxage = 1000000000;
49
50   q->repo = NULL;
51   q->action = NULL;
52   q->object = NULL;
53   q->head = NULL;
54   q->commit = NULL;
55   q->path = NULL;
56   q->blob = NULL;
57   q->blob_size = 0;
58   q->user = NULL;
59   q->name = NULL;
60   q->email = NULL;
61   q->ssign = NULL;
62   q->recover = 0;
63   q->skin = cwa_strndup (WEBGIT_DEFAULT_SKIN, SIZE_MAX);
64   q->count = -1;
65
66   llist_init (&q->repos);
67 }
68
69 struct webgit_query*
70 webgit_query_destroy (struct webgit_query* q)
71 {
72   cgi_free (q->request);
73
74   free (q->login_cookie);
75   free (q->prefs_cookie);
76
77   free (q->content_type);
78   free (q->rxpd);
79   free (q->skindir);
80   free (q->webskindir);
81   free (q->secret);
82   free (q->accountdir);
83
84   free (q->repo);
85   free (q->action);
86   free (q->object);
87   free (q->head);
88   free (q->commit);
89   free (q->path);
90   free (q->user);
91   free (q->name);
92   free (q->email);
93   free (q->ssign);
94   free (q->skin);
95   free (q->blob);
96
97   LLIST_WHILE_HEAD (&q->repos, head)
98     webgit_repoinfo_free ((struct webgit_repo_info*) head);
99
100   return q;
101 }
102
103
104 void
105 webgit_query_add_repo (struct webgit_query* q, const char* path)
106 {
107   struct webgit_repo_info* ri = webgit_repoinfo_new (q, path);
108   if (!ri)
109     return;
110
111   LList p = &q->repos;
112   LLIST_FOREACH (&q->repos, node)
113     {
114       struct webgit_repo_info* n = (struct webgit_repo_info*)node;
115       if (strcmp (n->name, ri->name) > 0)
116         break;
117       p = node;
118     }
119   llist_insert_next (p, &ri->node);
120 }
121
122 int
123 webgit_validate_string (const char *s, size_t v_sz)
124 {
125   for (const char* c = ";$&|<>!`#"; *c; ++c)
126     if (memchr (s, *c, v_sz))
127       return 0;
128
129   if (cwa_memmem (s, v_sz, "..", 2))
130     return 0;
131
132   return 1;
133 }
134
135 static void
136 webgit_repo_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
137 {
138   (void) self;
139   struct webgit_query* q = (struct webgit_query*) u_dat;
140
141   /* TODO validate that v is a probably legal repo name (alnum()) */
142   if (webgit_validate_string (v, v_sz))
143     {
144       free (q->repo);
145       q->repo = cwa_strndup (v, v_sz);
146     }
147 }
148
149
150 static void
151 webgit_action_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
152 {
153   (void) self;
154   struct webgit_query* q = (struct webgit_query*) u_dat;
155
156   /* TODO validate that v is a probably legal action name alpha() */
157   if (webgit_validate_string (v, v_sz))
158     {
159       free (q->action);
160       q->action = cwa_strndup (v, v_sz);
161     }
162 }
163
164
165 static void
166 webgit_object_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
167 {
168   (void) self;
169   struct webgit_query* q = (struct webgit_query*) u_dat;
170
171   if (!q->action)
172     q->action = cwa_strndup ("object", SIZE_MAX);
173
174   /* TODO validate that v is a probably sha1 (<=40 chars, hex) */
175   if (webgit_validate_string (v, v_sz))
176     {
177       free (q->object);
178       q->object = cwa_strndup (v, v_sz);
179     }
180 }
181
182
183 static void
184 webgit_ref_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
185 {
186   (void) self;
187   struct webgit_query* q = (struct webgit_query*) u_dat;
188
189   /* TODO validate that v is a probably legal reference (alnum() || one of '_/.') */
190   if (webgit_validate_string (v, v_sz))
191     {
192       free (q->head);
193       q->head = cwa_strndup (v, v_sz);
194     }
195 }
196
197
198 static void
199 webgit_commit_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
200 {
201   (void) self;
202   struct webgit_query* q = (struct webgit_query*) u_dat;
203
204   /* TODO validate that v is a probably legal reference (alnum() || one of '_/.') */
205   if (webgit_validate_string (v, v_sz))
206     {
207       free (q->commit);
208       q->commit = cwa_strndup (v, v_sz);
209     }
210 }
211
212
213 static void
214 webgit_path_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
215 {
216   (void) self;
217   struct webgit_query* q = (struct webgit_query*) u_dat;
218
219   /* TODO validate that v is a probably legal reference (alnum() || one of '_/.') */
220   if (webgit_validate_string (v, v_sz))
221     {
222       free (q->path);
223       q->path = cwa_strndup (v, v_sz);
224     }
225 }
226
227
228 static void
229 webgit_blob_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
230 {
231   (void) self;
232   struct webgit_query* q = (struct webgit_query*) u_dat;
233
234   free (q->blob);
235   q->blob = cwa_malloc (v_sz + 1);
236   q->blob_size = v_sz;
237   memcpy (q->blob, v, v_sz);
238   q->blob[v_sz] = '\0';
239 }
240
241
242 static void
243 webgit_skin_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
244 {
245   (void) self;
246   struct webgit_query* q = (struct webgit_query*) u_dat;
247
248   /* TODO validate that v is a probably legal reference (alnum() || one of '_/.') */
249   if (webgit_validate_string (v, v_sz))
250     {
251       free (q->skin);
252       q->skin = cwa_strndup (v, v_sz);
253     }
254 }
255
256
257 static void
258 webgit_maxage_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
259 {
260   (void) self;
261   struct webgit_query* q = (struct webgit_query*) u_dat;
262
263   if (v_sz)
264     {
265       unsigned long maxage = atol (v) * 86400UL;
266
267       LLIST_FOREACH (&q->repos, node)
268         ((struct webgit_repo_info*)node)->maxage = maxage;
269     }
270 }
271
272
273 static void
274 webgit_expire_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
275 {
276   (void) self;
277   struct webgit_query* q = (struct webgit_query*) u_dat;
278
279   if (v_sz)
280     {
281       q->cookie_expire = atol (v) * 86400UL;
282     }
283 }
284
285
286 static void
287 webgit_user_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
288 {
289   (void) self;
290   struct webgit_query* q = (struct webgit_query*) u_dat;
291
292   if (webgit_validate_string (v, v_sz))
293     {
294       free (q->user);
295       q->user = cwa_strndup (v, v_sz);
296     }
297 }
298
299
300 static void
301 webgit_name_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
302 {
303   (void) self;
304   struct webgit_query* q = (struct webgit_query*) u_dat;
305
306   if (webgit_validate_string (v, v_sz))
307     {
308       free (q->name);
309       q->name = cwa_strndup (v, v_sz);
310     }
311 }
312
313
314 static void
315 webgit_email_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
316 {
317   (void) self;
318   struct webgit_query* q = (struct webgit_query*) u_dat;
319
320   if (webgit_validate_string (v, v_sz))
321     {
322       free (q->email);
323       q->email = cwa_strndup (v, v_sz);
324     }
325 }
326
327
328 static void
329 webgit_ssign_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
330 {
331   (void) self;
332   struct webgit_query* q = (struct webgit_query*) u_dat;
333
334   if (webgit_validate_string (v, v_sz))
335     {
336       free (q->ssign);
337       q->ssign = cwa_strndup (v, v_sz);
338     }
339 }
340
341
342 static void
343 webgit_recover_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
344 {
345   (void) self;
346   struct webgit_query* q = (struct webgit_query*) u_dat;
347
348   q->recover = 1;
349 }
350
351
352 static void
353 webgit_login_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
354 {
355   if (v_sz)
356     {
357       char *name;
358       char *value;
359       char *data = cwa_urldecode (v);
360
361       while ((data = parse_namevalue (data, &name, &value)))
362         webgit_param_dispatch (self, name, value, value ? strlen (value) : 0, u_dat);
363     }
364 }
365
366
367 static void
368 webgit_prefs_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
369 {
370   webgit_login_param (self, v, v_sz, u_dat);
371 }
372
373
374 static void
375 webgit_count_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
376 {
377   (void) self;
378   struct webgit_query* q = (struct webgit_query*) u_dat;
379
380   if (v_sz)
381     q->count = atoi (v);
382 }
383
384
385 void
386 webgit_param_dispatch (const Cgi self,
387                       const char* name,
388                       const char* value,
389                       size_t value_len,
390                       void* user_data)
391 {
392 #define WEBGIT_PARAM(name, _) {#name, webgit_##name##_param},
393   struct param_table{
394     char* name;
395     void (*cb)(const Cgi, const char* v, size_t v_sz, void* u_dat);
396   } cmds[] = {WEBGIT_PARAMS {"", NULL}};
397 #undef WEBGIT_PARAMS
398
399   for (struct param_table* j = cmds; j->cb; ++j)
400     {
401       if (!strcmp (j->name, name))
402         {
403           j->cb (self, value, value_len, user_data);
404           break;
405         }
406     }
407 }
408
409 /*
410 //      Local Variables:
411 //      mode: C
412 //      c-file-style: "gnu"
413 //      indent-tabs-mode: nil
414 //      End:
415 */