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