Add a whole lore of new query parameters for handling edits
[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   q->current_repo = NULL;
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   q->account_validated = 0;
51
52   q->repo = NULL;
53   q->action = NULL;
54   q->object = NULL;
55   q->head = NULL;
56   q->commit = NULL;
57   q->path = NULL;
58   q->blob = NULL;
59   q->blob_size = 0;
60   q->file = NULL;
61   q->file_size = 0;
62   q->oldpath = NULL;
63   q->comment = NULL;
64   q->mode = NULL;
65   q->user = NULL;
66   q->name = NULL;
67   q->email = NULL;
68   q->ssign = NULL;
69   q->recover = 0;
70   q->skin = cwa_strndup (WEBGIT_DEFAULT_SKIN, SIZE_MAX);
71   q->count = -1;
72
73   llist_init (&q->repos);
74 }
75
76 struct webgit_query*
77 webgit_query_destroy (struct webgit_query* q)
78 {
79   cgi_free (q->request);
80
81   free (q->login_cookie);
82   free (q->prefs_cookie);
83
84   free (q->content_type);
85   free (q->rxpd);
86   free (q->skindir);
87   free (q->webskindir);
88   free (q->secret);
89   free (q->accountdir);
90
91   free (q->repo);
92   free (q->action);
93   free (q->object);
94   free (q->head);
95   free (q->commit);
96   free (q->path);
97   free (q->comment);
98   free (q->oldpath);
99   free (q->mode);
100   free (q->user);
101   free (q->name);
102   free (q->email);
103   free (q->ssign);
104   free (q->skin);
105   free (q->blob);
106   free (q->file);
107
108   LLIST_WHILE_HEAD (&q->repos, head)
109     webgit_repoinfo_free ((struct webgit_repo_info*) head);
110
111   return q;
112 }
113
114
115 void
116 webgit_query_add_repo (struct webgit_query* q, const char* path)
117 {
118   struct webgit_repo_info* ri = webgit_repoinfo_new (q, path);
119   if (!ri)
120     return;
121
122   LList p = &q->repos;
123   LLIST_FOREACH (&q->repos, node)
124     {
125       struct webgit_repo_info* n = (struct webgit_repo_info*)node;
126       if (strcmp (n->name, ri->name) > 0)
127         break;
128       p = node;
129     }
130   llist_insert_next (p, &ri->node);
131 }
132
133 int
134 webgit_validate_string (const char *s, size_t v_sz)
135 {
136   for (const char* c = ";$&|<>!`#"; *c; ++c)
137     if (memchr (s, *c, v_sz))
138       return 0;
139
140   if (cwa_memmem (s, v_sz, "..", 2))
141     return 0;
142
143   return 1;
144 }
145
146 static void
147 webgit_repo_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
148 {
149   (void) self;
150   struct webgit_query* q = (struct webgit_query*) u_dat;
151
152   /* TODO validate that v is a probably legal repo name (alnum()) */
153   if (webgit_validate_string (v, v_sz))
154     {
155       free (q->repo);
156       q->repo = cwa_strndup (v, v_sz);
157     }
158 }
159
160
161 static void
162 webgit_action_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
163 {
164   (void) self;
165   struct webgit_query* q = (struct webgit_query*) u_dat;
166
167   /* TODO validate that v is a probably legal action name alpha() */
168   if (webgit_validate_string (v, v_sz))
169     {
170       free (q->action);
171       q->action = cwa_strndup (v, v_sz);
172     }
173 }
174
175
176 static void
177 webgit_object_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
178 {
179   (void) self;
180   struct webgit_query* q = (struct webgit_query*) u_dat;
181
182   if (!q->action)
183     q->action = cwa_strndup ("object", SIZE_MAX);
184
185   /* TODO validate that v is a probably sha1 (<=40 chars, hex) */
186   if (webgit_validate_string (v, v_sz))
187     {
188       free (q->object);
189       q->object = cwa_strndup (v, v_sz);
190     }
191 }
192
193
194 static void
195 webgit_ref_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
196 {
197   (void) self;
198   struct webgit_query* q = (struct webgit_query*) u_dat;
199
200   /* TODO validate that v is a probably legal reference (alnum() || one of '_/.') */
201   if (webgit_validate_string (v, v_sz))
202     {
203       free (q->head);
204       q->head = cwa_strndup (v, v_sz);
205     }
206 }
207
208
209 static void
210 webgit_commit_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
211 {
212   (void) self;
213   struct webgit_query* q = (struct webgit_query*) u_dat;
214
215   /* TODO validate that v is a probably legal reference (alnum() || one of '_/.') */
216   if (webgit_validate_string (v, v_sz))
217     {
218       free (q->commit);
219       q->commit = cwa_strndup (v, v_sz);
220     }
221 }
222
223
224 static void
225 webgit_path_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
226 {
227   (void) self;
228   struct webgit_query* q = (struct webgit_query*) u_dat;
229
230   /* TODO validate that v is a probably legal reference (alnum() || one of '_/.') */
231   if (webgit_validate_string (v, v_sz))
232     {
233       free (q->path);
234       q->path = cwa_strndup (v, v_sz);
235     }
236 }
237
238
239 static void
240 webgit_oldpath_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
241 {
242   (void) self;
243   struct webgit_query* q = (struct webgit_query*) u_dat;
244
245   /* TODO validate that v is a probably legal reference (alnum() || one of '_/.') */
246   if (webgit_validate_string (v, v_sz))
247     {
248       free (q->oldpath);
249       q->oldpath = cwa_strndup (v, v_sz);
250     }
251 }
252
253
254 static void
255 webgit_mode_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
256 {
257   (void) self;
258   struct webgit_query* q = (struct webgit_query*) u_dat;
259
260   /* TODO validate that v is a probably legal reference (alnum() || one of '_/.') */
261   if (webgit_validate_string (v, v_sz))
262     {
263       free (q->mode);
264       q->mode = cwa_strndup (v, v_sz);
265     }
266 }
267
268
269 static void
270 webgit_blob_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
271 {
272   (void) self;
273   struct webgit_query* q = (struct webgit_query*) u_dat;
274
275   free (q->blob);
276   q->blob = cwa_malloc (v_sz + 1);
277   q->blob_size = v_sz;
278   memcpy (q->blob, v, v_sz);
279   q->blob[v_sz] = '\0';
280 }
281
282
283 static void
284 webgit_file_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
285 {
286   (void) self;
287   struct webgit_query* q = (struct webgit_query*) u_dat;
288
289   free (q->file);
290   q->file = cwa_malloc (v_sz + 1);
291   q->file_size = v_sz;
292   memcpy (q->file, v, v_sz);
293   q->file[v_sz] = '\0';
294 }
295
296
297 static void
298 webgit_comment_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
299 {
300   (void) self;
301   struct webgit_query* q = (struct webgit_query*) u_dat;
302
303   free (q->comment);
304   q->comment = cwa_strndup (v, v_sz);
305 }
306
307
308 static void
309 webgit_skin_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
310 {
311   (void) self;
312   struct webgit_query* q = (struct webgit_query*) u_dat;
313
314   /* TODO validate that v is a probably legal reference (alnum() || one of '_/.') */
315   if (webgit_validate_string (v, v_sz))
316     {
317       free (q->skin);
318       q->skin = cwa_strndup (v, v_sz);
319     }
320 }
321
322
323 static void
324 webgit_maxage_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
325 {
326   (void) self;
327   struct webgit_query* q = (struct webgit_query*) u_dat;
328
329   if (v_sz)
330     {
331       unsigned long maxage = atol (v) * 86400UL;
332
333       LLIST_FOREACH (&q->repos, node)
334         ((struct webgit_repo_info*)node)->maxage = maxage;
335     }
336 }
337
338
339 static void
340 webgit_expire_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
341 {
342   (void) self;
343   struct webgit_query* q = (struct webgit_query*) u_dat;
344
345   if (v_sz)
346     {
347       q->cookie_expire = atol (v) * 86400UL;
348     }
349 }
350
351
352 static void
353 webgit_user_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
354 {
355   (void) self;
356   struct webgit_query* q = (struct webgit_query*) u_dat;
357
358   if (webgit_validate_string (v, v_sz))
359     {
360       free (q->user);
361       q->user = cwa_strndup (v, v_sz);
362     }
363 }
364
365
366 static void
367 webgit_name_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
368 {
369   (void) self;
370   struct webgit_query* q = (struct webgit_query*) u_dat;
371
372   if (webgit_validate_string (v, v_sz))
373     {
374       free (q->name);
375       q->name = cwa_strndup (v, v_sz);
376     }
377 }
378
379
380 static void
381 webgit_email_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
382 {
383   (void) self;
384   struct webgit_query* q = (struct webgit_query*) u_dat;
385
386   if (webgit_validate_string (v, v_sz))
387     {
388       free (q->email);
389       q->email = cwa_strndup (v, v_sz);
390     }
391 }
392
393
394 static void
395 webgit_ssign_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
396 {
397   (void) self;
398   struct webgit_query* q = (struct webgit_query*) u_dat;
399
400   if (webgit_validate_string (v, v_sz))
401     {
402       free (q->ssign);
403       q->ssign = cwa_strndup (v, v_sz);
404     }
405 }
406
407
408 static void
409 webgit_cancel_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
410 {
411   (void) self;
412   (void) v;
413   (void) v_sz;
414   struct webgit_query* q = (struct webgit_query*) u_dat;
415
416   free (q->action);
417   q->action = cwa_strndup ("cancel", SIZE_MAX);
418 }
419
420
421 static void
422 webgit_stage_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
423 {
424   (void) self;
425   (void) v;
426   (void) v_sz;
427   struct webgit_query* q = (struct webgit_query*) u_dat;
428
429   free (q->action);
430   q->action = cwa_strndup ("stage", SIZE_MAX);
431 }
432
433
434 static void
435 webgit_docommit_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
436 {
437   (void) self;
438   (void) v;
439   (void) v_sz;
440   struct webgit_query* q = (struct webgit_query*) u_dat;
441
442   free (q->action);
443   q->action = cwa_strndup ("commit", SIZE_MAX);
444 }
445
446
447 static void
448 webgit_recover_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
449 {
450   (void) self;
451   struct webgit_query* q = (struct webgit_query*) u_dat;
452
453   q->recover = 1;
454 }
455
456
457 static void
458 webgit_login_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
459 {
460   if (v_sz)
461     {
462       char *name;
463       char *value;
464       char *data = cwa_urldecode (v);
465
466       while ((data = parse_namevalue (data, &name, &value)))
467         webgit_param_dispatch (self, name, value, value ? strlen (value) : 0, u_dat);
468     }
469 }
470
471
472 static void
473 webgit_prefs_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
474 {
475   webgit_login_param (self, v, v_sz, u_dat);
476 }
477
478
479 static void
480 webgit_count_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
481 {
482   (void) self;
483   struct webgit_query* q = (struct webgit_query*) u_dat;
484
485   if (v_sz)
486     q->count = atoi (v);
487 }
488
489
490 void
491 webgit_param_dispatch (const Cgi self,
492                       const char* name,
493                       const char* value,
494                       size_t value_len,
495                       void* user_data)
496 {
497 #define WEBGIT_PARAM(name, _) {#name, webgit_##name##_param},
498   struct param_table{
499     char* name;
500     void (*cb)(const Cgi, const char* v, size_t v_sz, void* u_dat);
501   } cmds[] = {WEBGIT_PARAMS {"", NULL}};
502 #undef WEBGIT_PARAMS
503
504   for (struct param_table* j = cmds; j->cb; ++j)
505     {
506       if (!strcmp (j->name, name))
507         {
508           j->cb (self, value, value_len, user_data);
509           break;
510         }
511     }
512 }
513
514 /*
515 //      Local Variables:
516 //      mode: C
517 //      c-file-style: "gnu"
518 //      indent-tabs-mode: nil
519 //      End:
520 */