223 lines · 4.6 KB · C
RawDownload
/* parsing.c: parsing of config files * * Copyright (C) 2006-2014 cgit Development Team <cgit@lists.zx2c4.com> * * Licensed under GNU General Public License v2 *   (see COPYING for full license text) */ #include "cgit.h" /* * url syntax: [repo ['/' cmd [ '/' path]]] *   repo: any valid repo url, may contain '/' *   cmd:  log | commit | diff | tree | view | blob | snapshot *   path: any valid path, may contain '/' * */void cgit_parse_url(const char *url){	char *c, *cmd, *p;	struct cgit_repo *repo; 	if (!url || url[0] == '\0')		return; 	ctx.qry.page = NULL;	ctx.repo = cgit_get_repoinfo(url);	if (ctx.repo) {		ctx.qry.repo = ctx.repo->url;		return;	} 	cmd = NULL;	c = strchr(url, '/');	while (c) {		c[0] = '\0';		repo = cgit_get_repoinfo(url);		if (repo) {			ctx.repo = repo;			cmd = c;		}		c[0] = '/';		c = strchr(c + 1, '/');	} 	if (ctx.repo) {		ctx.qry.repo = ctx.repo->url;		p = strchr(cmd + 1, '/');		if (p) {			p[0] = '\0';			if (p[1])				ctx.qry.path = trim_end(p + 1, '/');		}		if (cmd[1])			ctx.qry.page = xstrdup(cmd + 1);	}} static char *substr(const char *head, const char *tail){	char *buf; 	if (tail < head)		return xstrdup("");	buf = xmalloc(tail - head + 1);	strlcpy(buf, head, tail - head + 1);	return buf;} static void parse_user(const char *t, char **name, char **email, unsigned long *date, int *tz){	struct ident_split ident;	unsigned email_len; 	if (!split_ident_line(&ident, t, strchrnul(t, '\n') - t)) {		*name = substr(ident.name_begin, ident.name_end); 		email_len = ident.mail_end - ident.mail_begin;		*email = xmalloc(strlen("<") + email_len + strlen(">") + 1);		xsnprintf(*email, email_len + 3, "<%.*s>", email_len, ident.mail_begin); 		if (ident.date_begin)			*date = strtoul(ident.date_begin, NULL, 10);		if (ident.tz_begin)			*tz = atoi(ident.tz_begin);	}} #ifdef NO_ICONV#define reencode(a, b, c)#elsestatic const char *reencode(char **txt, const char *src_enc, const char *dst_enc){	char *tmp; 	if (!txt)		return NULL; 	if (!*txt || !src_enc || !dst_enc)		return *txt; 	/* no encoding needed if src_enc equals dst_enc */	if (!strcasecmp(src_enc, dst_enc))		return *txt; 	tmp = reencode_string(*txt, dst_enc, src_enc);	if (tmp) {		free(*txt);		*txt = tmp;	}	return *txt;}#endif static const char *next_header_line(const char *p){	p = strchr(p, '\n');	if (!p)		return NULL;	return p + 1;} static int end_of_header(const char *p){	return !p || (*p == '\n');} struct commitinfo *cgit_parse_commit(struct commit *commit){	struct commitinfo *ret;	const char *p = repo_get_commit_buffer(the_repository, commit, NULL);	const char *t; 	ret = xcalloc(1, sizeof(struct commitinfo));	ret->commit = commit; 	if (!p)		return ret; 	if (!skip_prefix(p, "tree ", &p))		die("Bad commit: %s", oid_to_hex(&commit->object.oid));	p += the_hash_algo->hexsz + 1; 	while (skip_prefix(p, "parent ", &p))		p += the_hash_algo->hexsz + 1; 	if (p && skip_prefix(p, "author ", &p)) {		parse_user(p, &ret->author, &ret->author_email,			&ret->author_date, &ret->author_tz);		p = next_header_line(p);	} 	if (p && skip_prefix(p, "committer ", &p)) {		parse_user(p, &ret->committer, &ret->committer_email,			&ret->committer_date, &ret->committer_tz);		p = next_header_line(p);	} 	if (p && skip_prefix(p, "encoding ", &p)) {		t = strchr(p, '\n');		if (t) {			ret->msg_encoding = substr(p, t + 1);			p = t + 1;		}	} 	if (!ret->msg_encoding)		ret->msg_encoding = xstrdup("UTF-8"); 	while (!end_of_header(p))		p = next_header_line(p);	while (p && *p == '\n')		p++;	if (!p)		return ret; 	t = strchrnul(p, '\n');	ret->subject = substr(p, t);	while (*t == '\n')		t++;	ret->msg = xstrdup(t); 	reencode(&ret->author, ret->msg_encoding, PAGE_ENCODING);	reencode(&ret->author_email, ret->msg_encoding, PAGE_ENCODING);	reencode(&ret->committer, ret->msg_encoding, PAGE_ENCODING);	reencode(&ret->committer_email, ret->msg_encoding, PAGE_ENCODING);	reencode(&ret->subject, ret->msg_encoding, PAGE_ENCODING);	reencode(&ret->msg, ret->msg_encoding, PAGE_ENCODING); 	return ret;} struct taginfo *cgit_parse_tag(struct tag *tag){	void *data;	enum object_type type;	unsigned long size;	const char *p;	struct taginfo *ret = NULL; 	data = read_object_file(&tag->object.oid, &type, &size);	if (!data || type != OBJ_TAG)		goto cleanup; 	ret = xcalloc(1, sizeof(struct taginfo)); 	for (p = data; !end_of_header(p); p = next_header_line(p)) {		if (skip_prefix(p, "tagger ", &p)) {			parse_user(p, &ret->tagger, &ret->tagger_email,				&ret->tagger_date, &ret->tagger_tz);		}	} 	while (p && *p == '\n')		p++; 	if (p && *p)		ret->msg = xstrdup(p); cleanup:	free(data);	return ret;}