all repos — cgit @ 48dc00342effe3ba530ff6cbb79e5d0d5fc740fd

a hyperfast web frontend for git written in c

parsing.c (view raw)

  1/* config.c: parsing of config files
  2 *
  3 * Copyright (C) 2006 Lars Hjemli
  4 *
  5 * Licensed under GNU General Public License v2
  6 *   (see COPYING for full license text)
  7 */
  8
  9#include "cgit.h"
 10
 11int next_char(FILE *f)
 12{
 13	int c = fgetc(f);
 14	if (c=='\r') {
 15		c = fgetc(f);
 16		if (c!='\n') {
 17			ungetc(c, f);
 18			c = '\r';
 19		}
 20	}
 21	return c;
 22}
 23
 24void skip_line(FILE *f)
 25{
 26	int c;
 27
 28	while((c=next_char(f)) && c!='\n' && c!=EOF)
 29		;
 30}
 31
 32int read_config_line(FILE *f, char *line, const char **value, int bufsize)
 33{
 34	int i = 0, isname = 0;
 35
 36	*value = NULL;
 37	while(i<bufsize-1) {
 38		int c = next_char(f);
 39		if (!isname && (c=='#' || c==';')) {
 40			skip_line(f);
 41			continue;
 42		}
 43		if (!isname && isspace(c))
 44			continue;
 45
 46		if (c=='=' && !*value) {
 47			line[i] = 0;
 48			*value = &line[i+1];
 49		} else if (c=='\n' && !isname) {
 50			i = 0;
 51			continue;
 52		} else if (c=='\n' || c==EOF) {
 53			line[i] = 0;
 54			break;
 55		} else {
 56			line[i]=c;
 57		}
 58		isname = 1;
 59		i++;
 60	}
 61	line[i+1] = 0;
 62	return i;
 63}
 64
 65int cgit_read_config(const char *filename, configfn fn)
 66{
 67	int ret = 0, len;
 68	char line[256];
 69	const char *value;
 70	FILE *f = fopen(filename, "r");
 71
 72	if (!f)
 73		return -1;
 74
 75	while((len = read_config_line(f, line, &value, sizeof(line))) > 0)
 76		(*fn)(line, value);
 77
 78	fclose(f);
 79	return ret;
 80}
 81
 82char *convert_query_hexchar(char *txt)
 83{
 84	int d1, d2;
 85	if (strlen(txt) < 3) {
 86		*txt = '\0';
 87		return txt-1;
 88	}
 89	d1 = hextoint(*(txt+1));
 90	d2 = hextoint(*(txt+2));
 91	if (d1<0 || d2<0) {
 92		strcpy(txt, txt+3);
 93		return txt-1;
 94	} else {
 95		*txt = d1 * 16 + d2;
 96		strcpy(txt+1, txt+3);
 97		return txt;
 98	}
 99}
100
101int cgit_parse_query(char *txt, configfn fn)
102{
103	char *t, *value = NULL, c;
104
105	if (!txt)
106		return 0;
107
108	t = txt = xstrdup(txt);
109 
110	while((c=*t) != '\0') {
111		if (c=='=') {
112			*t = '\0';
113			value = t+1;
114		} else if (c=='+') {
115			*t = ' ';
116		} else if (c=='%') {
117			t = convert_query_hexchar(t);
118		} else if (c=='&') {
119			*t = '\0';
120			(*fn)(txt, value);
121			txt = t+1;
122			value = NULL;
123		}
124		t++;
125	}
126	if (t!=txt)
127		(*fn)(txt, value);
128	return 0;
129}
130
131char *substr(const char *head, const char *tail)
132{
133	char *buf;
134
135	buf = xmalloc(tail - head + 1);
136	strncpy(buf, head, tail - head);
137	buf[tail - head] = '\0';
138	return buf;
139}
140
141struct commitinfo *cgit_parse_commit(struct commit *commit)
142{
143	struct commitinfo *ret;
144	char *p = commit->buffer, *t = commit->buffer;
145
146	ret = xmalloc(sizeof(*ret));
147	ret->commit = commit;
148	ret->author = NULL;
149	ret->author_email = NULL;
150	ret->committer = NULL;
151	ret->committer_email = NULL;
152	ret->subject = NULL;
153	ret->msg = NULL;
154
155	if (strncmp(p, "tree ", 5))
156		die("Bad commit: %s", sha1_to_hex(commit->object.sha1));
157	else
158		p += 46; // "tree " + hex[40] + "\n"
159
160	while (!strncmp(p, "parent ", 7))
161		p += 48; // "parent " + hex[40] + "\n"
162
163	if (!strncmp(p, "author ", 7)) {
164		p += 7;
165		t = strchr(p, '<') - 1;
166		ret->author = substr(p, t);
167		p = t;
168		t = strchr(t, '>') + 1;
169		ret->author_email = substr(p, t);
170		ret->author_date = atol(++t);
171		p = strchr(t, '\n') + 1;
172	}
173
174	if (!strncmp(p, "committer ", 9)) {
175		p += 9;
176		t = strchr(p, '<') - 1;
177		ret->committer = substr(p, t);
178		p = t;
179		t = strchr(t, '>') + 1;
180		ret->committer_email = substr(p, t);
181		ret->committer_date = atol(++t);
182		p = strchr(t, '\n') + 1;
183	}
184
185	while (*p == '\n')
186		p = strchr(p, '\n') + 1;
187
188	t = strchr(p, '\n');
189	if (t && *t) {
190		ret->subject = substr(p, t);
191		p = t + 1;
192
193		while (*p == '\n')
194			p = strchr(p, '\n') + 1;
195		ret->msg = p;
196	}
197	return ret;
198}
199
200
201struct taginfo *cgit_parse_tag(struct tag *tag)
202{
203	void *data;
204	enum object_type type;
205	unsigned long size;
206	char *p, *t;
207	struct taginfo *ret;
208
209	data = read_sha1_file(tag->object.sha1, &type, &size);
210	if (!data || type != OBJ_TAG) {
211		free(data);
212		return 0;
213	}
214	
215	ret = xmalloc(sizeof(*ret));
216	ret->tagger = NULL;
217	ret->tagger_email = NULL;
218	ret->tagger_date = 0;
219	ret->msg = NULL;
220
221	p = data;
222
223	while (p && *p) {
224		if (*p == '\n')
225			break;
226
227		if (!strncmp(p, "tagger ", 7)) {
228			p += 7;
229			t = strchr(p, '<') - 1;
230			ret->tagger = substr(p, t);
231			p = t;
232			t = strchr(t, '>') + 1;
233			ret->tagger_email = substr(p, t);
234			ret->tagger_date = atol(++t);
235		}
236		p = strchr(p, '\n') + 1;
237	}
238
239	while (p && (*p == '\n'))
240		p = strchr(p, '\n') + 1;
241	if (p && *p)
242		ret->msg = xstrdup(p);
243	free(data);
244	return ret;
245}