Diff options
Diffstat (limited to '')
| -rw-r--r-- | source/html.c | 136 |
1 file changed, 41 insertions, 95 deletions
diff --git a/source/html.c b/source/html.c index d13ac5b..bc7a722 100644 --- a/source/html.c +++ b/source/html.c @@ -16,7 +16,11 @@ #define HTML_WRITE_BUFSIZE (64 * 1024) // The percent encoding for each byte, with NULL marking the bytes a URL may -// carry as themselves. Those are the letters, the digits, and !$()*,-./:;@[]_~ +// carry as themselves. An ampersand or plus is legal in a path but encoded all +// the same, since a bare plus in a query argument decodes back as a space, and +// an ampersand in an attribute value can start a character reference and +// quietly turn "a©.txt" into a different filename. The bytes left as +// themselves are the letters, the digits, and !$()*,-./:;@[]_~ static const char *url_escape_table[256] = { "%00", "%01", "%02", "%03", "%04", "%05", "%06", "%07", "%08", "%09", "%0A", "%0B", "%0C", "%0D", "%0E", "%0F", @@ -122,18 +126,6 @@ char *cgit_fmt(const char *format, ...) return buf[slot]; } -char *cgit_fmtalloc(const char *format, ...) -{ - struct strbuf sb = STRBUF_INIT; - va_list args; - - va_start(args, format); - strbuf_vaddf(&sb, format, args); - va_end(args); - - return strbuf_detach(&sb, NULL); -} - void html_flush(void) { size_t len = out_len; @@ -218,6 +210,24 @@ void html_vtxtf(const char *format, va_list ap) strbuf_release(&sb); } +/* + * The entity for a character that page text would otherwise read as markup, or + * NULL for any other character. + */ +static const char *txt_entity(int c) +{ + switch (c) { + case '<': + return "<"; + case '>': + return ">"; + case '&': + return "&"; + default: + return NULL; + } +} + void html_txt(const char *txt) { if (txt) @@ -234,15 +244,11 @@ ssize_t html_ntxt(const char *txt, size_t len) left = (ssize_t)len; while (p && *p && left--) { - int c = *p; - if (c == '<' || c == '>' || c == '&') { + const char *entity = txt_entity(*p); + + if (entity) { html_raw(txt, p - txt); - if (c == '>') - html(">"); - else if (c == '<') - html("<"); - else if (c == '&') - html("&"); + html(entity); txt = p + 1; } p++; @@ -308,16 +314,10 @@ void html_blob_txt(const char *txt, size_t len) const char *p; for (p = txt; p < end; p++) { - const char *entity = NULL, *esc = NULL; + const char *entity = txt_entity(*p), *esc = NULL; size_t width = 1; - if (*p == '<') - entity = "<"; - else if (*p == '>') - entity = ">"; - else if (*p == '&') - entity = "&"; - else + if (!entity) esc = html_line_break_escape(p, end, &width); if (!entity && !esc) continue; @@ -355,19 +355,17 @@ void html_attr(const char *txt) const char *p = txt; while (p && *p) { - int c = *p; - if (c == '<' || c == '>' || c == '\'' || c == '\"' || c == '&') { + const char *entity; + + if (*p == '\'') + entity = "'"; + else if (*p == '"') + entity = """; + else + entity = txt_entity(*p); + if (entity) { html_raw(txt, p - txt); - if (c == '>') - html(">"); - else if (c == '<') - html("<"); - else if (c == '\'') - html("'"); - else if (c == '"') - html("""); - else if (c == '&') - html("&"); + html(entity); txt = p + 1; } p++; @@ -382,11 +380,6 @@ void html_url_path(const char *txt) while (p && *p) { unsigned char c = *p; - // A raw ampersand or plus is legal in a URL path, but this - // table is shared with html_url_arg, where a bare plus decodes - // back as a space, and the paths written here land in attribute - // values, where an ampersand can start a character reference - // and quietly turn "a©.txt" into a different filename. const char *esc = url_escape_table[c]; if (esc) { html_raw(txt, p - txt); @@ -511,36 +504,7 @@ void html_intoption(int value, const char *text, int selected_value) html("</option>\n"); } -void html_link_open(const char *url, const char *title, const char *class) -{ - html("<a href='"); - html_attr(url); - if (title) { - html("' title='"); - html_attr(title); - } - if (class) { - html("' class='"); - html_attr(class); - } - html("'>"); -} - -void html_link_close(void) -{ - html("</a>"); -} - -/* - * Render one permission triplet, so a caller prints a whole mode by passing it - * shifted right by six, then by three, then unshifted. - */ -void html_fileperm(unsigned short mode) -{ - htmlf("%c%c%c", (mode & 4 ? 'r' : '-'), (mode & 2 ? 'w' : '-'), (mode & 1 ? 'x' : '-')); -} - -int html_include(const char *filename) +void html_include(const char *filename) { FILE *f; char buf[4096]; @@ -548,27 +512,9 @@ int html_include(const char *filename) if (!(f = fopen(filename, "r"))) { fprintf(stderr, "[cgit] Unable to include %s: %s (%d)\n", filename, strerror(errno), errno); - return -1; + return; } while ((len = fread(buf, 1, sizeof(buf), f)) > 0) html_raw(buf, len); fclose(f); - return 0; -} - -void http_parse_querystring(const char *txt, void (*fn)(const char *name, const char *value)) -{ - const char *p = txt; - - while (p && *p) { - char *name = url_decode_parameter_name(&p); - // A name ends at an equals sign or an ampersand, and only the - // first is followed by a value. - if (*name) { - char *value = p[-1] == '=' ? url_decode_parameter_value(&p) : xstrdup(""); - fn(name, value); - free(value); - } - free(name); - } } |
