699b26d0ef747fb6e3a313d284ea864a3b4c2dc8
[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->skin = cwa_strndup (WEBGIT_DEFAULT_SKIN, SIZE_MAX);
55   q->count = -1;
56
57   llist_init (&q->repos);
58 }
59
60 struct webgit_query*
61 webgit_query_destroy (struct webgit_query* q)
62 {
63   cgi_free (q->request);
64
65   free (q->content_type);
66   free (q->rxpd);
67   free (q->skindir);
68   free (q->webskindir);
69   free (q->secret);
70   free (q->accountdir);
71
72   free (q->repo);
73   free (q->action);
74   free (q->object);
75   free (q->head);
76   free (q->path);
77   free (q->skin);
78   free (q->blob);
79
80   LLIST_WHILE_HEAD (&q->repos, head)
81     webgit_repoinfo_free ((struct webgit_repo_info*) head);
82
83   return q;
84 }
85
86
87 void
88 webgit_query_add_repo (struct webgit_query* q, const char* path)
89 {
90   struct webgit_repo_info* ri = webgit_repoinfo_new (q, path);
91   if (!ri)
92     return;
93
94   LList p = &q->repos;
95   LLIST_FOREACH (&q->repos, node)
96     {
97       struct webgit_repo_info* n = (struct webgit_repo_info*)node;
98       if (strcmp (n->name, ri->name) > 0)
99         break;
100       p = node;
101     }
102   llist_insert_next (p, &ri->node);
103 }
104
105 int
106 webgit_validate_string (const char *s, size_t v_sz)
107 {
108   for (const char* c = ";$&|<>!`#"; *c; ++c)
109     if (memchr (s, *c, v_sz))
110       return 0;
111
112   if (cwa_memmem (s, v_sz, "..", 2))
113     return 0;
114
115   return 1;
116 }
117
118 static void
119 webgit_repo_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
120 {
121   (void) self;
122   struct webgit_query* q = (struct webgit_query*) u_dat;
123
124   /* TODO validate that v is a probably legal repo name (alnum()) */
125   if (webgit_validate_string (v, v_sz))
126     {
127       free (q->repo);
128       q->repo = cwa_strndup (v, v_sz);
129     }
130 }
131
132
133 static void
134 webgit_action_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
135 {
136   (void) self;
137   struct webgit_query* q = (struct webgit_query*) u_dat;
138
139   /* TODO validate that v is a probably legal action name alpha() */
140   if (webgit_validate_string (v, v_sz))
141     {
142       free (q->action);
143       q->action = cwa_strndup (v, v_sz);
144     }
145 }
146
147
148 static void
149 webgit_object_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
150 {
151   (void) self;
152   struct webgit_query* q = (struct webgit_query*) u_dat;
153
154   if (!q->action)
155     q->action = cwa_strndup ("object", SIZE_MAX);
156
157   /* TODO validate that v is a probably sha1 (<=40 chars, hex) */
158   if (webgit_validate_string (v, v_sz))
159     {
160       free (q->object);
161       q->object = cwa_strndup (v, v_sz);
162     }
163 }
164
165
166 static void
167 webgit_ref_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   /* TODO validate that v is a probably legal reference (alnum() || one of '_/.') */
173   if (webgit_validate_string (v, v_sz))
174     {
175       free (q->head);
176       q->head = cwa_strndup (v, v_sz);
177     }
178 }
179
180
181 static void
182 webgit_path_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
183 {
184   (void) self;
185   struct webgit_query* q = (struct webgit_query*) u_dat;
186
187   /* TODO validate that v is a probably legal reference (alnum() || one of '_/.') */
188   if (webgit_validate_string (v, v_sz))
189     {
190       free (q->path);
191       q->path = cwa_strndup (v, v_sz);
192     }
193 }
194
195
196 static void
197 webgit_blob_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
198 {
199   (void) self;
200   struct webgit_query* q = (struct webgit_query*) u_dat;
201
202   free (q->blob);
203   q->blob = cwa_malloc (v_sz + 1);
204   q->blob_size = v_sz;
205   memcpy (q->blob, v, v_sz);
206   q->blob[v_sz] = '\0';
207 }
208
209
210 static void
211 webgit_skin_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
212 {
213   (void) self;
214   struct webgit_query* q = (struct webgit_query*) u_dat;
215
216   /* TODO validate that v is a probably legal reference (alnum() || one of '_/.') */
217   if (webgit_validate_string (v, v_sz))
218     {
219       free (q->skin);
220       q->skin = cwa_strndup (v, v_sz);
221     }
222 }
223
224
225 static void
226 webgit_maxage_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
227 {
228   (void) self;
229   struct webgit_query* q = (struct webgit_query*) u_dat;
230
231   if (v_sz)
232     {
233       unsigned long maxage = atol (v) * 86400UL;
234
235       LLIST_FOREACH (&q->repos, node)
236         ((struct webgit_repo_info*)node)->maxage = maxage;
237     }
238 }
239
240
241 static void
242 webgit_count_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
243 {
244   (void) self;
245   struct webgit_query* q = (struct webgit_query*) u_dat;
246
247   if (v_sz)
248     q->count = atoi (v);
249 }
250
251
252 void
253 webgit_param_dispatch (const Cgi self,
254                       const char* name,
255                       const char* value,
256                       size_t value_len,
257                       void* user_data)
258 {
259 #define WEBGIT_PARAM(name, _) {#name, webgit_##name##_param},
260   struct param_table{
261     char* name;
262     void (*cb)(const Cgi, const char* v, size_t v_sz, void* u_dat);
263   } cmds[] = {WEBGIT_PARAMS {"", NULL}};
264 #undef WEBGIT_PARAMS
265
266   for (struct param_table* j = cmds; j->cb; ++j)
267     {
268       if (!strcmp (j->name, name))
269         {
270           j->cb (self, value, value_len, user_data);
271           break;
272         }
273     }
274 }
275
276 /*
277 //      Local Variables:
278 //      mode: C
279 //      c-file-style: "gnu"
280 //      indent-tabs-mode: nil
281 //      End:
282 */