tpercent encode characters in path names - stagit - [fork] customized build of stagit, the static git page generator
 (HTM) git clone git://src.adamsgaard.dk/stagit
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 5b88f7cee4ac2e79072fd7c31e5dafbdfd527faa
 (DIR) parent 937dd3bc3e623be46b4795afc71aa28134919911
 (HTM) Author: Hiltjo Posthuma <hiltjo@codemadness.org>
       Date:   Tue, 16 Nov 2021 14:16:46 +0100
       
       percent encode characters in path names
       
       Paths could contain characters like # (fragment), '?', control-characters, etc.
       
       Diffstat:
         M stagit-index.c                      |      24 +++++++++++++++++++++++-
         M stagit.c                            |      32 ++++++++++++++++++++++++++-----
       
       2 files changed, 50 insertions(+), 6 deletions(-)
       ---
 (DIR) diff --git a/stagit-index.c b/stagit-index.c
       t@@ -30,6 +30,28 @@ joinpath(char *buf, size_t bufsiz, const char *path, const char *path2)
                                path, path[0] && path[strlen(path) - 1] != '/' ? "/" : "", path2);
        }
        
       +/* Percent-encode, see RFC3986 section 2.1. */
       +void
       +percentencode(FILE *fp, const char *s, size_t len)
       +{
       +        static char tab[] = "0123456789ABCDEF";
       +        unsigned char uc;
       +        size_t i;
       +
       +        for (i = 0; *s && i < len; s++, i++) {
       +                uc = *s;
       +                /* NOTE: do not encode '/' for paths */
       +                if (uc < '/' || uc >= 127 || (uc >= ':' && uc <= '@') ||
       +                    uc == '[' || uc == ']') {
       +                        putc('%', fp);
       +                        putc(tab[(uc >> 4) & 0x0f], fp);
       +                        putc(tab[uc & 0x0f], fp);
       +                } else {
       +                        putc(uc, fp);
       +                }
       +        }
       +}
       +
        /* Escape characters below as HTML 2.0 / XML 1.0. */
        void
        xmlencode(FILE *fp, const char *s, size_t len)
       t@@ -123,7 +145,7 @@ writelog(FILE *fp)
                                *p = '\0';
        
                fputs("<tr><td><a href=\"", fp);
       -        xmlencode(fp, stripped_name, strlen(stripped_name));
       +        percentencode(fp, stripped_name, strlen(stripped_name));
                fputs("/log.html\">", fp);
                xmlencode(fp, stripped_name, strlen(stripped_name));
                fputs("</a></td><td>", fp);
 (DIR) diff --git a/stagit.c b/stagit.c
       t@@ -362,6 +362,28 @@ efopen(const char *filename, const char *flags)
                return fp;
        }
        
       +/* Percent-encode, see RFC3986 section 2.1. */
       +void
       +percentencode(FILE *fp, const char *s, size_t len)
       +{
       +        static char tab[] = "0123456789ABCDEF";
       +        unsigned char uc;
       +        size_t i;
       +
       +        for (i = 0; *s && i < len; s++, i++) {
       +                uc = *s;
       +                /* NOTE: do not encode '/' for paths */
       +                if (uc < '/' || uc >= 127 || (uc >= ':' && uc <= '@') ||
       +                    uc == '[' || uc == ']') {
       +                        putc('%', fp);
       +                        putc(tab[(uc >> 4) & 0x0f], fp);
       +                        putc(tab[uc & 0x0f], fp);
       +                } else {
       +                        putc(uc, fp);
       +                }
       +        }
       +}
       +
        /* Escape characters below as HTML 2.0 / XML 1.0. */
        void
        xmlencode(FILE *fp, const char *s, size_t len)
       t@@ -500,7 +522,7 @@ writeheader(FILE *fp, const char *title)
                fputs("</span></td></tr>", fp);
                if (cloneurl[0]) {
                        fputs("<tr class=\"url\"><td></td><td>git clone <a href=\"", fp);
       -                xmlencode(fp, cloneurl, strlen(cloneurl));
       +                xmlencode(fp, cloneurl, strlen(cloneurl)); /* not percent-encoded */
                        fputs("\">", fp);
                        xmlencode(fp, cloneurl, strlen(cloneurl));
                        fputs("</a>", fp);
       t@@ -583,7 +605,7 @@ printcommit(FILE *fp, struct commitinfo *ci)
                        fputs("<b>Author:</b> ", fp);
                        xmlencode(fp, ci->author->name, strlen(ci->author->name));
                        fputs(" &lt;<a href=\"mailto:", fp);
       -                xmlencode(fp, ci->author->email, strlen(ci->author->email));
       +                xmlencode(fp, ci->author->email, strlen(ci->author->email)); /* not percent-encoded */
                        fputs("\">", fp);
                        xmlencode(fp, ci->author->email, strlen(ci->author->email));
                        fputs("</a>&gt;\n<b>Date:</b>   ", fp);
       t@@ -678,11 +700,11 @@ printshowfile(FILE *fp, struct commitinfo *ci)
                        patch = ci->deltas[i]->patch;
                        delta = git_patch_get_delta(patch);
                        fprintf(fp, "<b>diff --git a/<a id=\"h%zu\" href=\"%sfile/", i, relpath);
       -                xmlencode(fp, delta->old_file.path, strlen(delta->old_file.path));
       +                percentencode(fp, delta->old_file.path, strlen(delta->old_file.path));
                        fputs(".html\">", fp);
                        xmlencode(fp, delta->old_file.path, strlen(delta->old_file.path));
                        fprintf(fp, "</a> b/<a href=\"%sfile/", relpath);
       -                xmlencode(fp, delta->new_file.path, strlen(delta->new_file.path));
       +                percentencode(fp, delta->new_file.path, strlen(delta->new_file.path));
                        fprintf(fp, ".html\">");
                        xmlencode(fp, delta->new_file.path, strlen(delta->new_file.path));
                        fprintf(fp, "</a></b>\n");
       t@@ -1050,7 +1072,7 @@ writefilestree(FILE *fp, git_tree *tree, const char *path)
                                fputs("<tr><td>", fp);
                                fputs(filemode(git_tree_entry_filemode(entry)), fp);
                                fprintf(fp, "</td><td><a href=\"%s", relpath);
       -                        xmlencode(fp, filepath, strlen(filepath));
       +                        percentencode(fp, filepath, strlen(filepath));
                                fputs("\">", fp);
                                xmlencode(fp, entrypath, strlen(entrypath));
                                fputs("</a></td><td class=\"num\" align=\"right\">", fp);