cgit/parsing.c
Christian Hesse 779631c6dc global: replace references to 'sha1' with 'oid'
For some time now sha1 is considered broken and upstream is working to
replace it with sha256. Replace all references to 'sha1' with 'oid',
just as upstream does.

Signed-off-by: Christian Hesse <mail@eworm.de>
2020-10-20 23:57:12 +02:00

225 lines
4.6 KiB
C

/* 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)
#else
static 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)
{
const int oid_hex_len = 40;
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 += oid_hex_len + 1;
while (skip_prefix(p, "parent ", &p))
p += oid_hex_len + 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;
}