/* parsing.c: parsing of config files * * Copyright (C) 2006-2014 cgit Development Team * * 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 *cmd, *p; ctx.repo = NULL; if (!url || url[0] == '\0') return; ctx.repo = cgit_get_repoinfo(url); if (ctx.repo) { ctx.qry.repo = ctx.repo->url; return; } cmd = strchr(url, '/'); while (!ctx.repo && cmd) { cmd[0] = '\0'; ctx.repo = cgit_get_repoinfo(url); if (ctx.repo == NULL) { cmd[0] = '/'; cmd = strchr(cmd + 1, '/'); continue; } 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); return; } } static char *substr(const char *head, const char *tail) { char *buf; if (tail < head) return xstrdup(""); buf = xmalloc(tail - head + 1); strncpy(buf, head, tail - head); buf[tail - head] = '\0'; return buf; } static char *parse_user(char *t, char **name, char **email, unsigned long *date) { char *p = t; int mode = 1; while (p && *p) { if (mode == 1 && *p == '<') { *name = substr(t, p - 1); t = p; mode++; } else if (mode == 1 && *p == '\n') { *name = substr(t, p); p++; break; } else if (mode == 2 && *p == '>') { *email = substr(t, p + 1); t = p; mode++; } else if (mode == 2 && *p == '\n') { *email = substr(t, p); p++; break; } else if (mode == 3 && isdigit(*p)) { *date = atol(p); mode++; } else if (*p == '\n') { p++; break; } p++; } return p; } #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 struct commitinfo *cgit_parse_commit(struct commit *commit) { struct commitinfo *ret; char *p = commit->buffer, *t; ret = xmalloc(sizeof(*ret)); ret->commit = commit; ret->author = NULL; ret->author_email = NULL; ret->committer = NULL; ret->committer_email = NULL; ret->subject = NULL; ret->msg = NULL; ret->msg_encoding = NULL; if (p == NULL) return ret; if (prefixcmp(p, "tree ")) die("Bad commit: %s", sha1_to_hex(commit->object.sha1)); else p += 46; // "tree " + hex[40] + "\n" while (!prefixcmp(p, "parent ")) p += 48; // "parent " + hex[40] + "\n" if (p && !prefixcmp(p, "author ")) { p = parse_user(p + 7, &ret->author, &ret->author_email, &ret->author_date); } if (p && !prefixcmp(p, "committer ")) { p = parse_user(p + 10, &ret->committer, &ret->committer_email, June McEnroe2020-02-13 | | | | Copied from pounce. * Make sure -D_GNU_SOURCE ends up in CFLAGS on LinuxJune McEnroe2020-02-11 | * Use pkg(8) to configure on FreeBSDJune McEnroe2020-02-11 | * Add simple configure scriptJune McEnroe2020-02-06 Mostly motivated by wanting to build with the ncurses in pkgsrc because it supports italics.