content type handling
[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->repo = NULL;
41   q->action = NULL;
42   q->object = NULL;
43   q->head = NULL;
44   llist_init (&q->repos);
45 }
46
47 struct webgit_query*
48 webgit_query_destroy (struct webgit_query* q)
49 {
50   cgi_free (q->request);
51
52   free (q->content_type);
53   free (q->repo);
54   free (q->action);
55   free (q->object);
56   free (q->head);
57
58   LLIST_WHILE_HEAD (&q->repos, head)
59     webgit_repoinfo_free ((struct webgit_repo_info*) head);
60
61   return q;
62 }
63
64
65 void
66 webgit_query_add_repo (struct webgit_query* q, const char* path)
67 {
68   struct webgit_repo_info* ri = webgit_repoinfo_new (q, path);
69   if (!ri)
70     return;
71
72   LList p = &q->repos;
73   LLIST_FOREACH (&q->repos, node)
74     {
75       struct webgit_repo_info* n = (struct webgit_repo_info*)node;
76       if (strcmp (n->name, ri->name) > 0)
77         break;
78       p = node;
79     }
80   llist_insert_next (p, &ri->node);
81 }
82
83 const int
84 webgit_validate_string (const char *s, size_t v_sz)
85 {
86   for (const char* c = ";$&|<>!`#"; *c; ++c)
87     if (memchr (s, *c, v_sz))
88       return 0;
89
90   return 1;
91 }
92
93 static void
94 webgit_repo_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
95 {
96   (void) self;
97   struct webgit_query* q = (struct webgit_query*) u_dat;
98
99   /* TODO validate that v is a probably legal repo name (alnum()) */
100   if (webgit_validate_string (v, v_sz))
101     {
102       free (q->repo);
103       q->repo = cwa_strndup (v, v_sz);
104     }
105 }
106
107
108 static void
109 webgit_action_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 action name alpha() */
115   if (webgit_validate_string (v, v_sz))
116     {
117       free (q->action);
118       q->action = cwa_strndup (v, v_sz);
119     }
120 }
121
122
123 static void
124 webgit_object_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   if (!q->action)
130     q->action = cwa_strndup ("object", SIZE_MAX);
131
132   /* TODO validate that v is a probably sha1 (<=40 chars, hex) */
133   if (webgit_validate_string (v, v_sz))
134     {
135       free (q->object);
136       q->object = cwa_strndup (v, v_sz);
137     }
138 }
139
140
141 static void
142 webgit_ref_param (const Cgi self, const char* v, size_t v_sz, void* u_dat)
143 {
144   (void) self;
145   struct webgit_query* q = (struct webgit_query*) u_dat;
146
147   /* TODO validate that v is a probably legal reference (alnum() || one of '_/.') */
148   if (webgit_validate_string (v, v_sz))
149     {
150       free (q->head);
151       q->head = cwa_strndup (v, v_sz);
152     }
153 }
154
155
156 void
157 webgit_param_dispatch (const Cgi self,
158                       const char* name,
159                       const char* value,
160                       size_t value_len,
161                       void* user_data)
162 {
163 #define WEBGIT_PARAM(name, _) {#name, webgit_##name##_param},
164   struct param_table{
165     char* name;
166     void (*cb)(const Cgi, const char* v, size_t v_sz, void* u_dat);
167   } cmds[] = {WEBGIT_PARAMS {"", NULL}};
168 #undef WEBGIT_PARAMS
169
170   for (struct param_table* j = cmds; j->cb; ++j)
171     {
172       if (!strcmp (j->name, name))
173         {
174           j->cb (self, value, value_len, user_data);
175           break;
176         }
177     }
178 }