X-Git-Url: https://gitweb.ps.run/ps-cgit/blobdiff_plain/2101e26fd68f816e77de62b93df4c32fd1110d0c..20a33548b9a87a6eb23162ee5d137daa46d78613:/parsing.c diff --git a/parsing.c b/parsing.c index 6cab0e9..9a4a7a3 100644 --- a/parsing.c +++ b/parsing.c @@ -8,75 +8,23 @@ #include "cgit.h" -int next_char(FILE *f) +char *convert_query_hexchar(char *txt) { - int c = fgetc(f); - if (c=='\r') { - c = fgetc(f); - if (c!='\n') { - ungetc(c, f); - c = '\r'; - } + int d1, d2; + if (strlen(txt) < 3) { + *txt = '\0'; + return txt-1; } - return c; -} - -void skip_line(FILE *f) -{ - int c; - - while((c=next_char(f)) && c!='\n' && c!=EOF) - ; -} - -int read_config_line(FILE *f, char *line, const char **value, int bufsize) -{ - int i = 0, isname = 0; - - *value = NULL; - while(i 0) - (*fn)(line, value); - - fclose(f); - return ret; } int cgit_parse_query(char *txt, configfn fn) @@ -87,11 +35,15 @@ int cgit_parse_query(char *txt, configfn fn) 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); @@ -105,6 +57,50 @@ int cgit_parse_query(char *txt, configfn fn) return 0; } +/* + * 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; + } +} + char *substr(const char *head, const char *tail) { char *buf; @@ -122,6 +118,16 @@ struct commitinfo *cgit_parse_commit(struct commit *commit) 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 (strncmp(p, "tree ", 5)) die("Bad commit: %s", sha1_to_hex(commit->object.sha1)); @@ -135,25 +141,117 @@ struct commitinfo *cgit_parse_commit(struct commit *commit) p += 7; t = strchr(p, '<') - 1; ret->author = substr(p, t); - p = strchr(p, '\n') + 1; + p = t; + t = strchr(t, '>') + 1; + ret->author_email = substr(p, t); + ret->author_date = atol(t+1); + p = strchr(t, '\n') + 1; } if (!strncmp(p, "committer ", 9)) { p += 9; t = strchr(p, '<') - 1; ret->committer = substr(p, t); - p = strchr(p, '\n') + 1; + p = t; + t = strchr(t, '>') + 1; + ret->committer_email = substr(p, 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'); - 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') + while (*p == '\n') + p = strchr(p, '\n') + 1; + 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; + enum object_type type; + unsigned long size; + char *p, *t; + struct taginfo *ret; + + 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; + ret->tagger_date = 0; + ret->msg = NULL; + + p = data; + + while (p && *p) { + if (*p == '\n') + break; + + if (!strncmp(p, "tagger ", 7)) { + p += 7; + t = strchr(p, '<') - 1; + ret->tagger = substr(p, t); + p = t; + t = strchr(t, '>') + 1; + ret->tagger_email = substr(p, t); + ret->tagger_date = atol(t+1); + } p = strchr(p, '\n') + 1; - ret->msg = p; + } + 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 && *p) + ret->msg = xstrdup(p); + free(data); return ret; }