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