Diff options
Diffstat (limited to '')
| -rw-r--r-- | source/parsing.c | 76 |
1 file changed, 43 insertions, 33 deletions
diff --git a/source/parsing.c b/source/parsing.c index 71ecdb7..f684241 100644 --- a/source/parsing.c +++ b/source/parsing.c @@ -4,7 +4,8 @@ * the request path settles which repository and which page the request works * on. Commit and tag objects arrive as header lines, a blank line, and then * the message, so the readers here walk the headers, copy out the fields the - * pages need, and re-encode the message into the page encoding. + * pages need, and re-encode the message into the page encoding. The records + * they return are freed here too. */ #define USE_THE_REPOSITORY_VARIABLE @@ -15,22 +16,6 @@ #include <mailmap.h> -static char *substr(const char *start, const char *end) -{ - size_t len; - char *buf; - - if (end < start) - return xstrdup(""); - // start points into the object buffer, so strlcpy would measure the - // whole rest of the object to copy a name off the front of it. - len = end - start; - buf = xmalloc(len + 1); - memcpy(buf, start, len); - buf[len] = '\0'; - return buf; -} - // The repository's mailmap, read once per request and applied to every ident a // page shows. Only the blob at HEAD is read, the way git reads a bare // repository, so a repository cannot point the reader at a file on the server. @@ -112,22 +97,21 @@ static int end_of_header(const char *p) * not UTF-8 has its stray bytes replaced, and a page declared UTF-8 never * carries any. */ -static const char *reencode(char **text, const char *from, const char *to) +static void reencode(char **text, const char *encoding) { char *converted; - if (!*text || !from || !to) - return *text; + if (!*text) + return; - if (strcasecmp(from, to)) { - converted = reencode_string(*text, to, from); + if (strcasecmp(encoding, PAGE_ENCODING)) { + converted = reencode_string(*text, PAGE_ENCODING, encoding); if (converted) { free(*text); *text = converted; } } cgit_utf8_sanitize(*text); - return *text; } /* @@ -182,6 +166,7 @@ struct commitinfo *cgit_parse_commit(struct commit *commit) struct commitinfo *info; const char *p = repo_get_commit_buffer(the_repository, commit, NULL); const char *eol; + char *encoding = NULL; info = xcalloc(1, sizeof(struct commitinfo)); info->commit = commit; @@ -210,15 +195,15 @@ struct commitinfo *cgit_parse_commit(struct commit *commit) if (p && skip_prefix(p, "encoding ", &p)) { eol = strchr(p, '\n'); if (eol) { - info->msg_encoding = substr(p, eol); + encoding = xmemdupz(p, eol - p); p = eol + 1; } } // Git only writes the header when the message is in something other // than UTF-8, so its absence means UTF-8. - if (!info->msg_encoding) - info->msg_encoding = xstrdup("UTF-8"); + if (!encoding) + encoding = xstrdup("UTF-8"); while (!end_of_header(p)) p = next_header_line(p); @@ -227,7 +212,7 @@ struct commitinfo *cgit_parse_commit(struct commit *commit) if (p) { eol = strchrnul(p, '\n'); - info->subject = substr(p, eol); + info->subject = xmemdupz(p, eol - p); while (*eol == '\n') eol++; info->msg = xstrdup(eol); @@ -238,16 +223,28 @@ struct commitinfo *cgit_parse_commit(struct commit *commit) info->msg = xstrdup(""); } - reencode(&info->author, info->msg_encoding, PAGE_ENCODING); - reencode(&info->author_email, info->msg_encoding, PAGE_ENCODING); - reencode(&info->committer, info->msg_encoding, PAGE_ENCODING); - reencode(&info->committer_email, info->msg_encoding, PAGE_ENCODING); - reencode(&info->subject, info->msg_encoding, PAGE_ENCODING); - reencode(&info->msg, info->msg_encoding, PAGE_ENCODING); + reencode(&info->author, encoding); + reencode(&info->author_email, encoding); + reencode(&info->committer, encoding); + reencode(&info->committer_email, encoding); + reencode(&info->subject, encoding); + reencode(&info->msg, encoding); + free(encoding); return info; } +void cgit_free_commitinfo(struct commitinfo *info) +{ + free(info->author); + free(info->author_email); + free(info->committer); + free(info->committer_email); + free(info->subject); + free(info->msg); + free(info); +} + struct taginfo *cgit_parse_tag(struct tag *tag) { void *data; @@ -283,3 +280,16 @@ cleanup: free(data); return info; } + +void cgit_free_taginfo(struct taginfo *info) +{ + // NULL is accepted because cgit_parse_tag returns it for a tag object + // that cannot be read, and a ref left holding that still gets freed + // along with the rest of its list. + if (!info) + return; + free(info->tagger); + free(info->tagger_email); + free(info->msg); + free(info); +} |
