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