Diff options
Diffstat (limited to '')
-rw-r--r--source/parsing.c76
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);
+}