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