1 /* config.c: parsing of config files
3 * Copyright (C) 2006 Lars Hjemli
5 * Licensed under GNU General Public License v2
6 * (see COPYING for full license text)
13 int next_char(FILE *f)
26 void skip_line(FILE *f)
30 while((c=next_char(f)) && c!='\n' && c!=EOF)
34 int read_config_line(FILE *f, char *line, const char **value, int bufsize)
36 int i = 0, isname = 0;
41 if (!isname && (c=='#' || c==';')) {
45 if (!isname && isspace(c))
48 if (c=='=' && !*value) {
51 } else if (c=='\n' && !isname) {
54 } else if (c=='\n' || c==EOF) {
67 int cgit_read_config(const char *filename, configfn fn)
75 /* cancel deeply nested include-commands */
78 if (!(f = fopen(filename, "r")))
81 while((len = read_config_line(f, line, &value, sizeof(line))) > 0)
88 char *convert_query_hexchar(char *txt)
91 if (strlen(txt) < 3) {
95 d1 = hextoint(*(txt+1));
96 d2 = hextoint(*(txt+2));
102 strcpy(txt+1, txt+3);
107 int cgit_parse_query(char *txt, configfn fn)
109 char *t, *value = NULL, c;
114 t = txt = xstrdup(txt);
116 while((c=*t) != '\0') {
123 t = convert_query_hexchar(t);
138 * url syntax: [repo ['/' cmd [ '/' path]]]
139 * repo: any valid repo url, may contain '/'
140 * cmd: log | commit | diff | tree | view | blob | snapshot
141 * path: any valid path, may contain '/'
144 void cgit_parse_url(const char *url)
149 if (!url || url[0] == '\0')
152 cgit_repo = cgit_get_repoinfo(url);
154 cgit_query_repo = cgit_repo->url;
158 cmd = strchr(url, '/');
159 while (!cgit_repo && cmd) {
161 cgit_repo = cgit_get_repoinfo(url);
162 if (cgit_repo == NULL) {
164 cmd = strchr(cmd + 1, '/');
168 cgit_query_repo = cgit_repo->url;
169 p = strchr(cmd + 1, '/');
173 cgit_query_path = trim_end(p + 1, '/');
175 cgit_cmd = cgit_get_cmd_index(cmd + 1);
176 cgit_query_page = xstrdup(cmd + 1);
181 static char *iconv_msg(char *msg, const char *encoding)
183 iconv_t msg_conv = iconv_open(PAGE_ENCODING, encoding);
184 size_t inlen = strlen(msg);
194 if(msg_conv == (iconv_t)-1)
198 buf = xmalloc(buf_sz+1);
205 iconv(msg_conv, &in, &inleft, &out, &outleft);
210 } else if(inleft != 0 && errno == E2BIG) {
216 buf = xmalloc(buf_sz+1);
221 } while(again && !fail);
227 buf = xrealloc(buf, out - buf);
232 iconv_close(msg_conv);
237 char *substr(const char *head, const char *tail)
241 buf = xmalloc(tail - head + 1);
242 strncpy(buf, head, tail - head);
243 buf[tail - head] = '\0';
247 struct commitinfo *cgit_parse_commit(struct commit *commit)
249 struct commitinfo *ret;
250 char *p = commit->buffer, *t = commit->buffer;
252 ret = xmalloc(sizeof(*ret));
253 ret->commit = commit;
255 ret->author_email = NULL;
256 ret->committer = NULL;
257 ret->committer_email = NULL;
260 ret->msg_encoding = NULL;
265 if (strncmp(p, "tree ", 5))
266 die("Bad commit: %s", sha1_to_hex(commit->object.sha1));
268 p += 46; // "tree " + hex[40] + "\n"
270 while (!strncmp(p, "parent ", 7))
271 p += 48; // "parent " + hex[40] + "\n"
273 if (!strncmp(p, "author ", 7)) {
275 t = strchr(p, '<') - 1;
276 ret->author = substr(p, t);
278 t = strchr(t, '>') + 1;
279 ret->author_email = substr(p, t);
280 ret->author_date = atol(++t);
281 p = strchr(t, '\n') + 1;
284 if (!strncmp(p, "committer ", 9)) {
286 t = strchr(p, '<') - 1;
287 ret->committer = substr(p, t);
289 t = strchr(t, '>') + 1;
290 ret->committer_email = substr(p, t);
291 ret->committer_date = atol(++t);
292 p = strchr(t, '\n') + 1;
295 if (!strncmp(p, "encoding ", 9)) {
297 t = strchr(p, '\n') + 1;
298 ret->msg_encoding = substr(p, t);
301 ret->msg_encoding = xstrdup(PAGE_ENCODING);
303 while (*p && (*p != '\n'))
304 p = strchr(p, '\n') + 1; // skip unknown header fields
307 p = strchr(p, '\n') + 1;
312 ret->subject = "** empty **";
314 ret->subject = substr(p, t);
318 p = strchr(p, '\n') + 1;
319 ret->msg = xstrdup(p);
321 ret->subject = substr(p, p+strlen(p));
323 if(strcmp(ret->msg_encoding, PAGE_ENCODING)) {
324 t = iconv_msg(ret->subject, ret->msg_encoding);
330 t = iconv_msg(ret->msg, ret->msg_encoding);
341 struct taginfo *cgit_parse_tag(struct tag *tag)
344 enum object_type type;
349 data = read_sha1_file(tag->object.sha1, &type, &size);
350 if (!data || type != OBJ_TAG) {
355 ret = xmalloc(sizeof(*ret));
357 ret->tagger_email = NULL;
358 ret->tagger_date = 0;
367 if (!strncmp(p, "tagger ", 7)) {
369 t = strchr(p, '<') - 1;
370 ret->tagger = substr(p, t);
372 t = strchr(t, '>') + 1;
373 ret->tagger_email = substr(p, t);
374 ret->tagger_date = atol(++t);
376 p = strchr(p, '\n') + 1;
379 while (p && *p && (*p != '\n'))
380 p = strchr(p, '\n') + 1; // skip unknown tag fields
382 while (p && (*p == '\n'))
383 p = strchr(p, '\n') + 1;
385 ret->msg = xstrdup(p);