add a 'blob' query parameter which is used for content when editing
[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->stylesheet = NULL;
41   q->count_def = 100;
42   q->rxpd_name = NULL;
43   q->rxpd_port = 0;
44
45   q->repo = NULL;
46   q->action = NULL;
47   q->object = NULL;
48   q->head = NULL;
49   q->path = NULL;
50   q->blob = NULL;
51   q->blob_size = 0;
52   q->count = -1;
53
54   llist_init (&q->repos);
55 }
56
57 struct webgit_query*
58 webgit_query_destroy (struct webgit_query* q)
59 {
60   cgi_free (q->request);
61
62   free (q->content_type);
63   free (q->stylesheet);
64   free (q->rxpd_name);
65
66   free (q->repo);
67   free (q->action);
68   free (q->object);
69   free (q->head);
70   free (q->path);
71   free (q->blob);
72
73   LLIST_WHILE_HEAD (&q->repos, head)
74     webgit_repoinfo_free ((struct webgit_repo_info*) head);
75
76   return q;
77 }
78
79
80 void
81 webgit_query_add_repo (struct webgit_query* q, const char* path)
82 {
83   struct webgit_repo_info* ri = webgit_repoinfo_new (q, path);
84   if (!ri)
85     return;
86
87   LList p = &q->repos;
88   LLIST_FOREACH (&q->repos, node)
89     {
90       struct webgit_repo_info* n = (struct webgit_repo_info*)node;
91       if (strcmp (n->name, ri->name) > 0)
92         break;
93       p = node;
94     }
95   llist_insert_next (p, &ri->node);
96 }
97
98 int
99 webgit_validate_string (const char *s, size_t v_sz)
100 {
101   for (const char* c = ";$&|<>!`#"; *c; ++c)
102     if (memchr (s, *c, v_sz))
103       return 0;
104
105   return 1;
106 }
107
108 static void
109 webgit_repo_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
110 {
111   (void) self;
112   struct webgit_query* q = (struct webgit_query*) u_dat;
113
114   /* TODO validate that v is a probably legal repo name (alnum()) */
115   if (webgit_validate_string (v, v_sz))
116     {
117       free (q->repo);
118       q->repo = cwa_strndup (v, v_sz);
119     }
120 }
121
122
123 static void
124 webgit_action_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
125 {
126   (void) self;
127   struct webgit_query* q = (struct webgit_query*) u_dat;
128
129   /* TODO validate that v is a probably legal action name alpha() */
130   if (webgit_validate_string (v, v_sz))
131     {
132       free (q->action);
133       q->action = cwa_strndup (v, v_sz);
134     }
135 }
136
137
138 static void
139 webgit_object_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
140 {
141   (void) self;
142   struct webgit_query* q = (struct webgit_query*) u_dat;
143
144   if (!q->action)
145     q->action = cwa_strndup ("object", SIZE_MAX);
146
147   /* TODO validate that v is a probably sha1 (<=40 chars, hex) */
148   if (webgit_validate_string (v, v_sz))
149     {
150       free (q->object);
151       q->object = cwa_strndup (v, v_sz);
152     }
153 }
154
155
156 static void
157 webgit_ref_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   /* TODO validate that v is a probably legal reference (alnum() || one of '_/.') */
163   if (webgit_validate_string (v, v_sz))
164     {
165       free (q->head);
166       q->head = cwa_strndup (v, v_sz);
167     }
168 }
169
170
171 static void
172 webgit_path_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
173 {
174   (void) self;
175   struct webgit_query* q = (struct webgit_query*) u_dat;
176
177   /* TODO validate that v is a probably legal reference (alnum() || one of '_/.') */
178   if (webgit_validate_string (v, v_sz))
179     {
180       free (q->path);
181       q->path = cwa_strndup (v, v_sz);
182     }
183 }
184
185
186 static void
187 webgit_blob_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
188 {
189   (void) self;
190   struct webgit_query* q = (struct webgit_query*) u_dat;
191
192   free (q->blob);
193   q->blob = cwa_malloc (v_sz + 1);
194   q->blob_size = v_sz;
195   memcpy (q->blob, v, v_sz);
196   q->blob[v_sz] = '\0';
197 }
198
199
200 static void
201 webgit_count_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
202 {
203   (void) self;
204   struct webgit_query* q = (struct webgit_query*) u_dat;
205
206   /* TODO validate that v is a probably legal reference (alnum() || one of '_/.') */
207   if (webgit_validate_string (v, v_sz))
208     {
209       q->count = atoi (v);
210     }
211 }
212
213
214 void
215 webgit_param_dispatch (const Cgi self,
216                       const char* name,
217                       const char* value,
218                       size_t value_len,
219                       void* user_data)
220 {
221 #define WEBGIT_PARAM(name, _) {#name, webgit_##name##_param},
222   struct param_table{
223     char* name;
224     void (*cb)(const Cgi, const char* v, size_t v_sz, void* u_dat);
225   } cmds[] = {WEBGIT_PARAMS {"", NULL}};
226 #undef WEBGIT_PARAMS
227
228   for (struct param_table* j = cmds; j->cb; ++j)
229     {
230       if (!strcmp (j->name, name))
231         {
232           j->cb (self, value, value_len, user_data);
233           break;
234         }
235     }
236 }