crude input validation against a blacklist
[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 ctgit_query_init (struct ctgit_query* q)
33 {
34   q->request = NULL;
35   q->now = time (NULL);
36
37   q->repo = NULL;
38   q->action = NULL;
39   q->object = NULL;
40   q->head = NULL;
41   llist_init (&q->repos);
42 }
43
44 struct ctgit_query*
45 ctgit_query_destroy (struct ctgit_query* q)
46 {
47   cgi_free (q->request);
48
49   free (q->repo);
50   free (q->action);
51   free (q->object);
52   free (q->head);
53
54   LLIST_WHILE_HEAD (&q->repos, head)
55     ctgit_repoinfo_free ((struct ctgit_repo_info*) head);
56
57   return q;
58 }
59
60
61 void
62 ctgit_query_add_repo (struct ctgit_query* q, const char* path)
63 {
64   struct ctgit_repo_info* ri = ctgit_repoinfo_new (q, path);
65   if (!ri)
66     return;
67
68   LList p = &q->repos;
69   LLIST_FOREACH (&q->repos, node)
70     {
71       struct ctgit_repo_info* n = (struct ctgit_repo_info*)node;
72       if (strcmp (n->name, ri->name) > 0)
73         break;
74       p = node;
75     }
76   llist_insert_next (p, &ri->node);
77 }
78
79 const int
80 ctgit_validate_string (const char *s, size_t v_sz)
81 {
82   for (const char* c = ";$&|<>!`#"; *c; ++c)
83     if (memchr (s, *c, v_sz))
84       return 0;
85
86   return 1;
87 }
88
89 static void
90 ctgit_repo_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
91 {
92   (void) self;
93   struct ctgit_query* q = (struct ctgit_query*) u_dat;
94
95   /* TODO validate that v is a probably legal repo name (alnum()) */
96   if (ctgit_validate_string (v, v_sz))
97     {
98       free (q->repo);
99       q->repo = cwa_strndup (v, v_sz);
100     }
101 }
102
103
104 static void
105 ctgit_action_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
106 {
107   (void) self;
108   struct ctgit_query* q = (struct ctgit_query*) u_dat;
109
110   /* TODO validate that v is a probably legal action name alpha() */
111   if (ctgit_validate_string (v, v_sz))
112     {
113       free (q->action);
114       q->action = cwa_strndup (v, v_sz);
115     }
116 }
117
118
119 static void
120 ctgit_object_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
121 {
122   (void) self;
123   struct ctgit_query* q = (struct ctgit_query*) u_dat;
124
125   if (!q->action)
126     q->action = cwa_strndup ("object", SIZE_MAX);
127
128   /* TODO validate that v is a probably sha1 (<=40 chars, hex) */
129   if (ctgit_validate_string (v, v_sz))
130     {
131       free (q->object);
132       q->object = cwa_strndup (v, v_sz);
133     }
134 }
135
136
137 static void
138 ctgit_ref_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
139 {
140   (void) self;
141   struct ctgit_query* q = (struct ctgit_query*) u_dat;
142
143   /* TODO validate that v is a probably legal reference (alnum() || one of '_/.') */
144   if (ctgit_validate_string (v, v_sz))
145     {
146       free (q->head);
147       q->head = cwa_strndup (v, v_sz);
148     }
149 }
150
151
152 void
153 ctgit_param_dispatch (const Cgi self,
154                       const char* name,
155                       const char* value,
156                       size_t value_len,
157                       void* user_data)
158 {
159 #define CTGIT_PARAM(name, _) {#name, ctgit_##name##_param},
160   struct param_table{
161     char* name;
162     void (*cb)(const Cgi, const char* v, size_t v_sz, void* u_dat);
163   } cmds[] = {CTGIT_PARAMS {"", NULL}};
164 #undef CTGIT_PARAMS
165
166   for (struct param_table* j = cmds; j->cb; ++j)
167     {
168       if (!strcmp (j->name, name))
169         {
170           j->cb (self, value, value_len, user_data);
171           break;
172         }
173     }
174 }