4662b8dc02ec0058fbc4093ca553165b9ee01109
[webgit] / src / query.c
1 /*
2     cehtehs git web frontend
3
4   Copyright (C)
5     2007,               Christian Thaeter <ct@pipapo.org>
6
7   This program is free software; you can redistribute it and/or
8   modify it under the terms of the GNU General Public License as
9   published by the Free Software Foundation; either version 2 of the
10   License, or (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 General Public License for more details.
16
17   You should have received a copy of the GNU General Public License
18   along with this program; if not, write to the Free Software
19   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22
23 #include "query.h"
24 #include "repo.h"
25
26 #include "cwa.h"
27
28 #include <stdint.h>
29 #include <time.h>
30
31 void
32 webgit_query_init (struct webgit_query* q)
33 {
34   q->request = NULL;
35   q->now = time (NULL);
36
37   q->deref_to_tree = 0;
38   q->content_type = cwa_strndup ("text/html", SIZE_MAX);
39
40   q->count_def = 100;
41   q->rxpd_name = NULL;
42   q->rxpd_port = 0;
43   q->skindir = cwa_strndup (WEBGIT_SKINDIR_DEFAULT, SIZE_MAX);
44   q->webskindir = cwa_strndup (WEBGIT_WEBSKINDIR_DEFAULT, SIZE_MAX);
45
46   q->repo = NULL;
47   q->action = NULL;
48   q->object = NULL;
49   q->head = NULL;
50   q->path = NULL;
51   q->blob = NULL;
52   q->blob_size = 0;
53   q->skin = cwa_strndup (WEBGIT_DEFAULT_SKIN, SIZE_MAX);
54   q->count = -1;
55
56   llist_init (&q->repos);
57 }
58
59 struct webgit_query*
60 webgit_query_destroy (struct webgit_query* q)
61 {
62   cgi_free (q->request);
63
64   free (q->content_type);
65   free (q->rxpd_name);
66   free (q->skindir);
67   free (q->webskindir);
68
69   free (q->repo);
70   free (q->action);
71   free (q->object);
72   free (q->head);
73   free (q->path);
74   free (q->skin);
75   free (q->blob);
76
77   LLIST_WHILE_HEAD (&q->repos, head)
78     webgit_repoinfo_free ((struct webgit_repo_info*) head);
79
80   return q;
81 }
82
83
84 void
85 webgit_query_add_repo (struct webgit_query* q, const char* path)
86 {
87   struct webgit_repo_info* ri = webgit_repoinfo_new (q, path);
88   if (!ri)
89     return;
90
91   LList p = &q->repos;
92   LLIST_FOREACH (&q->repos, node)
93     {
94       struct webgit_repo_info* n = (struct webgit_repo_info*)node;
95       if (strcmp (n->name, ri->name) > 0)
96         break;
97       p = node;
98     }
99   llist_insert_next (p, &ri->node);
100 }
101
102 int
103 webgit_validate_string (const char *s, size_t v_sz)
104 {
105   for (const char* c = ";$&|<>!`#"; *c; ++c)
106     if (memchr (s, *c, v_sz))
107       return 0;
108
109   if (cwa_memmem (s, v_sz, "..", 2))
110     return 0;
111
112   return 1;
113 }
114
115 static void
116 webgit_repo_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
117 {
118   (void) self;
119   struct webgit_query* q = (struct webgit_query*) u_dat;
120
121   /* TODO validate that v is a probably legal repo name (alnum()) */
122   if (webgit_validate_string (v, v_sz))
123     {
124       free (q->repo);
125       q->repo = cwa_strndup (v, v_sz);
126     }
127 }
128
129
130 static void
131 webgit_action_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
132 {
133   (void) self;
134   struct webgit_query* q = (struct webgit_query*) u_dat;
135
136   /* TODO validate that v is a probably legal action name alpha() */
137   if (webgit_validate_string (v, v_sz))
138     {
139       free (q->action);
140       q->action = cwa_strndup (v, v_sz);
141     }
142 }
143
144
145 static void
146 webgit_object_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
147 {
148   (void) self;
149   struct webgit_query* q = (struct webgit_query*) u_dat;
150
151   if (!q->action)
152     q->action = cwa_strndup ("object", SIZE_MAX);
153
154   /* TODO validate that v is a probably sha1 (<=40 chars, hex) */
155   if (webgit_validate_string (v, v_sz))
156     {
157       free (q->object);
158       q->object = cwa_strndup (v, v_sz);
159     }
160 }
161
162
163 static void
164 webgit_ref_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
165 {
166   (void) self;
167   struct webgit_query* q = (struct webgit_query*) u_dat;
168
169   /* TODO validate that v is a probably legal reference (alnum() || one of '_/.') */
170   if (webgit_validate_string (v, v_sz))
171     {
172       free (q->head);
173       q->head = cwa_strndup (v, v_sz);
174     }
175 }
176
177
178 static void
179 webgit_path_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
180 {
181   (void) self;
182   struct webgit_query* q = (struct webgit_query*) u_dat;
183
184   /* TODO validate that v is a probably legal reference (alnum() || one of '_/.') */
185   if (webgit_validate_string (v, v_sz))
186     {
187       free (q->path);
188       q->path = cwa_strndup (v, v_sz);
189     }
190 }
191
192
193 static void
194 webgit_blob_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
195 {
196   (void) self;
197   struct webgit_query* q = (struct webgit_query*) u_dat;
198
199   free (q->blob);
200   q->blob = cwa_malloc (v_sz + 1);
201   q->blob_size = v_sz;
202   memcpy (q->blob, v, v_sz);
203   q->blob[v_sz] = '\0';
204 }
205
206
207 static void
208 webgit_skin_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
209 {
210   (void) self;
211   struct webgit_query* q = (struct webgit_query*) u_dat;
212
213   /* TODO validate that v is a probably legal reference (alnum() || one of '_/.') */
214   if (webgit_validate_string (v, v_sz))
215     {
216       free (q->skin);
217       q->skin = cwa_strndup (v, v_sz);
218     }
219 }
220
221
222 static void
223 webgit_count_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
224 {
225   (void) self;
226   struct webgit_query* q = (struct webgit_query*) u_dat;
227
228   /* TODO validate that v is a probably legal reference (alnum() || one of '_/.') */
229   if (webgit_validate_string (v, v_sz))
230     {
231       q->count = atoi (v);
232     }
233 }
234
235
236 void
237 webgit_param_dispatch (const Cgi self,
238                       const char* name,
239                       const char* value,
240                       size_t value_len,
241                       void* user_data)
242 {
243 #define WEBGIT_PARAM(name, _) {#name, webgit_##name##_param},
244   struct param_table{
245     char* name;
246     void (*cb)(const Cgi, const char* v, size_t v_sz, void* u_dat);
247   } cmds[] = {WEBGIT_PARAMS {"", NULL}};
248 #undef WEBGIT_PARAMS
249
250   for (struct param_table* j = cmds; j->cb; ++j)
251     {
252       if (!strcmp (j->name, name))
253         {
254           j->cb (self, value, value_len, user_data);
255           break;
256         }
257     }
258 }
259
260 /*
261 //      Local Variables:
262 //      mode: C
263 //      c-file-style: "gnu"
264 //      indent-tabs-mode: nil
265 //      End:
266 */