#include "cgit.h"
-int next_char(FILE *f)
-{
- int c = fgetc(f);
- if (c=='\r') {
- c = fgetc(f);
- if (c!='\n') {
- ungetc(c, f);
- c = '\r';
- }
- }
- return c;
-}
-
-void skip_line(FILE *f)
+/*
+ * 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)
{
- int c;
+ char *cmd, *p;
- while((c=next_char(f)) && c!='\n' && c!=EOF)
- ;
-}
+ ctx.repo = NULL;
+ if (!url || url[0] == '\0')
+ return;
-int read_config_line(FILE *f, char *line, const char **value, int bufsize)
-{
- int i = 0, isname = 0;
+ ctx.repo = cgit_get_repoinfo(url);
+ if (ctx.repo) {
+ ctx.qry.repo = ctx.repo->url;
+ return;
+ }
- *value = NULL;
- while(i<bufsize-1) {
- int c = next_char(f);
- if (!isname && (c=='#' || c==';')) {
- skip_line(f);
+ 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;
}
- if (!isname && isspace(c))
- continue;
- if (c=='=' && !*value) {
- line[i] = 0;
- *value = &line[i+1];
- } else if (c=='\n' && !isname) {
- i = 0;
- continue;
- } else if (c=='\n' || c==EOF) {
- line[i] = 0;
- break;
- } else {
- line[i]=c;
+ 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, '/');
}
- isname = 1;
- i++;
+ if (cmd[1])
+ ctx.qry.page = xstrdup(cmd + 1);
+ return;
}
- line[i+1] = 0;
- return i;
-}
-
-int cgit_read_config(const char *filename, configfn fn)
-{
- int ret = 0, len;
- char line[256];
- const char *value;
- FILE *f = fopen(filename, "r");
-
- if (!f)
- return -1;
-
- while((len = read_config_line(f, line, &value, sizeof(line))) > 0)
- (*fn)(line, value);
-
- fclose(f);
- return ret;
-}
-
-char *convert_query_hexchar(char *txt)
-{
- int d1, d2;
- if (strlen(txt) < 3) {
- *txt = '\0';
- return txt-1;
- }
- d1 = hextoint(*(txt+1));
- d2 = hextoint(*(txt+2));
- if (d1<0 || d2<0) {
- strcpy(txt, txt+3);
- return txt-1;
- } else {
- *txt = d1 * 16 + d2;
- strcpy(txt+1, txt+3);
- return txt;
- }
-}
-
-int cgit_parse_query(char *txt, configfn fn)
-{
- char *t, *value = NULL, c;
-
- if (!txt)
- return 0;
-
- t = txt = xstrdup(txt);
-
- while((c=*t) != '\0') {
- if (c=='=') {
- *t = '\0';
- value = t+1;
- } else if (c=='+') {
- *t = ' ';
- } else if (c=='%') {
- t = convert_query_hexchar(t);
- } else if (c=='&') {
- *t = '\0';
- (*fn)(txt, value);
- txt = t+1;
- value = NULL;
- }
- t++;
- }
- if (t!=txt)
- (*fn)(txt, value);
- return 0;
}
char *substr(const char *head, const char *tail)
ret->committer_email = NULL;
ret->subject = NULL;
ret->msg = NULL;
+ ret->msg_encoding = NULL;
+
+ if (p == NULL)
+ return ret;
if (strncmp(p, "tree ", 5))
die("Bad commit: %s", sha1_to_hex(commit->object.sha1));
p = t;
t = strchr(t, '>') + 1;
ret->author_email = substr(p, t);
- ret->author_date = atol(++t);
+ ret->author_date = atol(t+1);
p = strchr(t, '\n') + 1;
}
p = t;
t = strchr(t, '>') + 1;
ret->committer_email = substr(p, t);
- ret->committer_date = atol(++t);
+ ret->committer_date = atol(t+1);
p = strchr(t, '\n') + 1;
}
+ if (!strncmp(p, "encoding ", 9)) {
+ p += 9;
+ t = strchr(p, '\n') + 1;
+ ret->msg_encoding = substr(p, t);
+ p = t;
+ } else
+ ret->msg_encoding = xstrdup(PAGE_ENCODING);
+
+ while (*p && (*p != '\n'))
+ p = strchr(p, '\n') + 1; // skip unknown header fields
+
while (*p == '\n')
p = strchr(p, '\n') + 1;
t = strchr(p, '\n');
- if (t && *t) {
- ret->subject = substr(p, t);
+ if (t) {
+ if (*t == '\0')
+ ret->subject = "** empty **";
+ else
+ ret->subject = substr(p, t);
p = t + 1;
while (*p == '\n')
p = strchr(p, '\n') + 1;
- ret->msg = p;
+ ret->msg = xstrdup(p);
+ } else
+ ret->subject = substr(p, p+strlen(p));
+
+ if(strcmp(ret->msg_encoding, PAGE_ENCODING)) {
+ t = reencode_string(ret->subject, PAGE_ENCODING,
+ ret->msg_encoding);
+ if(t) {
+ free(ret->subject);
+ ret->subject = t;
+ }
+
+ t = reencode_string(ret->msg, PAGE_ENCODING,
+ ret->msg_encoding);
+ if(t) {
+ free(ret->msg);
+ ret->msg = t;
+ }
}
+
return ret;
}
struct taginfo *cgit_parse_tag(struct tag *tag)
{
void *data;
- char type[20];
+ enum object_type type;
unsigned long size;
char *p, *t;
struct taginfo *ret;
- data = read_sha1_file(tag->object.sha1, type, &size);
- if (!data || strcmp(type, tag_type)) {
+ data = read_sha1_file(tag->object.sha1, &type, &size);
+ if (!data || type != OBJ_TAG) {
free(data);
return 0;
}
-
+
ret = xmalloc(sizeof(*ret));
ret->tagger = NULL;
ret->tagger_email = NULL;
p = data;
- while (p) {
+ while (p && *p) {
if (*p == '\n')
break;
p = t;
t = strchr(t, '>') + 1;
ret->tagger_email = substr(p, t);
- ret->tagger_date = atol(++t);
+ ret->tagger_date = atol(t+1);
}
p = strchr(p, '\n') + 1;
}
+ while (p && *p && (*p != '\n'))
+ p = strchr(p, '\n') + 1; // skip unknown tag fields
+
while (p && (*p == '\n'))
p = strchr(p, '\n') + 1;
- if (p)
+ if (p && *p)
ret->msg = xstrdup(p);
free(data);
return ret;