implement action=raw which sends just the data-blob
[webgit] / src / webgit.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 "webgit.h"
24
25 #define WEBGIT_CONFIG "./webgit.conf"
26
27 #ifndef WEBGIT_CONFIG
28 #define WEBGIT_CONFIG "/etc/webgit.conf"
29 #endif
30
31 #include "actions.h"
32 #include "query.h"
33 #include "options.h"
34
35 #include "git/git-compat-util.h"
36
37 #include <cwa.h>
38
39 #include <stdio.h>
40 #include <stdarg.h>
41 #include <string.h>
42 #include <time.h>
43 #include <setjmp.h>
44
45 Html error_log;
46 jmp_buf err_jmp;
47
48 void
49 webgit_err_vargs (const char *err, va_list params)
50 {
51   html_list_append (error_log, html (html_fmt_vargs (err, params), html_tag ("br")));
52   longjmp (err_jmp, 0);
53 }
54
55 void
56 webgit_warn_vargs (const char *err, va_list params)
57 {
58   html_list_append (error_log, html (html_fmt_vargs (err, params), html_tag("br")));
59 }
60
61
62 static void
63 webgit_setup (void)
64 {
65   set_die_routine (webgit_err_vargs);
66   set_error_routine (webgit_err_vargs);
67   set_warn_routine (webgit_warn_vargs);
68 }
69
70
71 Html
72 webgit_email_link (Html name, Html email)
73 {
74   return html (
75                html_tag("a",
76                         html_attr ("href",
77                                    html ("mailto:", email))
78                         ),
79                name
80                );
81 }
82
83
84 void
85 webgit_enter_repository (struct webgit_query* query)
86 {
87   LLIST_FOREACH (&query->repos, node)
88     {
89       struct webgit_repo_info* ri = (struct webgit_repo_info*) node;
90       if (!strcmp (ri->name, query->repo))
91         {
92           if (chdir (ri->path))
93             return die ("error: wrong path %s", ri->path);
94           break;
95         }
96     }
97
98   setup_git_directory ();
99 }
100
101
102 const char*
103 webgit_mimetype (const char* name)
104 {
105   char buf[256];
106
107   if (!name)
108     return NULL;
109
110   char* ext = strrchr (name, '.');
111   if (!ext)
112     return NULL;
113   ++ext;
114   if (!*ext)
115     return NULL;
116
117   FILE* mime_types = fopen ("/etc/mime.types", "r");
118   if (!mime_types)
119     return NULL;
120
121   while (fgets (buf, 256, mime_types))
122     {
123       if (buf[0] == '#' || !strtok (buf, " \t\n"))
124         continue;
125
126       char* suffix;
127       while ((suffix = strtok (NULL, " \t\n")))
128         if (!strcmp (suffix, ext))
129           {
130             fclose (mime_types);
131             return cwa_strndup (buf, SIZE_MAX);
132           }
133     }
134   return NULL;
135 }
136
137
138 int
139 main (int argc, char**argv)
140 {
141   Html page;
142   struct webgit_query query;
143
144   webgit_setup();
145
146   error_log = html_list();
147
148   clock_t timestat = clock();
149
150   webgit_query_init (&query);
151
152   /* set some defaults if not already set */
153   setenv ("REQUEST_METHOD", "GET", 0);
154   setenv ("SCRIPT_NAME", argv[0], 0);
155   setenv ("WEBGIT_CONFIG", WEBGIT_CONFIG, 0);
156
157   /* we can only longjmp out of libgit's error handling */
158   if (setjmp (err_jmp))
159     goto error;
160
161   if (webgit_commandline_dispatch (argc, argv, &query))
162     goto error;
163
164   // read config
165   if (webgit_configfile_dispatch (getenv("WEBGIT_CONFIG"), &query))
166     goto error;
167
168
169   // parse request/query What to show?
170
171   query.request = cgi_new ();
172
173   cgi_run_query (query.request, webgit_param_dispatch, &query);
174
175   /* TODO: if no object given but repo+path+ref are given then compute object */
176
177   /* default action is to show the main page with the list of repos */
178   if (!query.action)
179     query.action = cwa_strndup ("main", SIZE_MAX);
180
181   // query to cache-line
182
183   // check if in cache
184
185   // generate page
186
187   Html content = webgit_action_dispatch (&query);
188
189   if (query.content_type && !strcmp (query.content_type, "text/html"))
190     {
191       /* generate html page */
192       page = html(
193                   html_httpheader(
194                                   html_httpfield(
195                                                  "Content-type",
196                                                  query.content_type,
197                                                  html_attr("charset", "UTF-8")
198                                                  )//,
199                                   //html_httpfield("Last-Modified", cgit_page.modified),
200                                   //html_httpfield("Expires", cgit_page.expires)
201                                   ),
202                   html_document(
203                                 "-//W3C//DTD XHTML 1.0 Transitional//EN",
204                                 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd",
205                                 html_content(
206                                              /*head*/
207                                              html(
208                                                   html(html_tag("title"), "webgit"),
209                                                   html_nl(),
210                                                   html_meta("generator", "webgit")//,
211                                                   //html_link_rel("stylesheet", "text/css", cgit_page.stylesheet)
212                                                   ),
213                                              /*body*/
214                                              html (
215                                                    html (
216                                                          html_tag("div"),
217                                                          content
218                                                          ),
219                                                    html(
220                                                         html_tag("div"),
221                                                         error_log
222                                                         )
223                                                    ),
224                                              html_attr("xmlns", "http://www.w3.org/1999/xhtml"),
225                                              html_attr("xml:lang", "en"),
226                                              html_attr("lang", "en")
227                                              )
228                                 )
229                   );
230
231       timestat = clock() - timestat;
232       html_list_append (error_log, html (
233                                          html_fmt ("processing took %g secs\n", timestat/(float)CLOCKS_PER_SEC),
234                                          html_tag("br")
235                                          )
236                         );
237
238
239     }
240   else
241     {
242       /* diffrent content type, raw content */
243       html_free (error_log);
244
245       page = html(
246                   html_httpheader (
247                                    html_httpfield ("Content-type",
248                                                    query.content_type ?
249                                                    query.content_type
250                                                    : "application/octet-stream")
251                                   ),
252                   content
253                   );
254     }
255
256   html_fprint (stdout, page);
257
258   html_free (page);
259
260   webgit_query_destroy (&query);
261
262   return 0;
263
264  error:
265   page = html(
266               html_httpheader(
267                               html_httpfield(
268                                              "Content-type",
269                                              "text/html",
270                                              html_attr("charset", "UTF-8")
271                                              )                              ),
272               html_document(
273                             "-//W3C//DTD XHTML 1.0 Transitional//EN",
274                             "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd",
275                             html_content(
276                                          /*head*/
277                                          html(
278                                               html(html_tag("title"), "ERROR: webgit"),
279                                               html_nl(),
280                                               html_meta("generator", "webgit")
281                                               ),
282                                          /*body*/
283                                          html(
284                                               html_tag("div"),
285                                               error_log
286                                               ),
287                                          html_attr("xmlns", "http://www.w3.org/1999/xhtml"),
288                                          html_attr("xml:lang", "en"),
289                                          html_attr("lang", "en")
290                                          )
291                             )
292               );
293
294   html_fprint (stdout, page);
295   html_free (page);
296   return 10;
297 }