stagit

percent encode characters in path names

Paths could contain characters like # (fragment), '?', control-characters, etc.

Hiltjo Posthuma contact@arjunchoudhary.com

commit: 21478cb parent: 502fa4a
2 files changed, 50 insertions(+), 6 deletions(-)
Mstagit-index.c+23-1
Mstagit.c+27-5
M · stagit-index.c +23, -1
 1@@ -28,6 +28,28 @@ joinpath(char *buf, size_t bufsiz, const char *path, const char *path2)
 2 			path, path[0] && path[strlen(path) - 1] != '/' ? "/" : "", path2);
 3 }
 4 
 5+/* Percent-encode, see RFC3986 section 2.1. */
 6+void
 7+percentencode(FILE *fp, const char *s, size_t len)
 8+{
 9+	static char tab[] = "0123456789ABCDEF";
10+	unsigned char uc;
11+	size_t i;
12+
13+	for (i = 0; *s && i < len; s++, i++) {
14+		uc = *s;
15+		/* NOTE: do not encode '/' for paths */
16+		if (uc < '/' || uc >= 127 || (uc >= ':' && uc <= '@') ||
17+		    uc == '[' || uc == ']') {
18+			putc('%', fp);
19+			putc(tab[(uc >> 4) & 0x0f], fp);
20+			putc(tab[uc & 0x0f], fp);
21+		} else {
22+			putc(uc, fp);
23+		}
24+	}
25+}
26+
27 /* Escape characters below as HTML 2.0 / XML 1.0. */
28 void
29 xmlencode(FILE *fp, const char *s, size_t len)
30@@ -118,7 +140,7 @@ writelog(FILE *fp)
31 			*p = '\0';
32 
33 	fputs("<tr><td><a href=\"", fp);
34-	xmlencode(fp, stripped_name, strlen(stripped_name));
35+	percentencode(fp, stripped_name, strlen(stripped_name));
36 	fputs("/log.html\">", fp);
37 	xmlencode(fp, stripped_name, strlen(stripped_name));
38 	fputs("</a></td><td>", fp);
M · stagit.c +27, -5
 1@@ -359,6 +359,28 @@ efopen(const char *filename, const char *flags)
 2 	return fp;
 3 }
 4 
 5+/* Percent-encode, see RFC3986 section 2.1. */
 6+void
 7+percentencode(FILE *fp, const char *s, size_t len)
 8+{
 9+	static char tab[] = "0123456789ABCDEF";
10+	unsigned char uc;
11+	size_t i;
12+
13+	for (i = 0; *s && i < len; s++, i++) {
14+		uc = *s;
15+		/* NOTE: do not encode '/' for paths */
16+		if (uc < '/' || uc >= 127 || (uc >= ':' && uc <= '@') ||
17+		    uc == '[' || uc == ']') {
18+			putc('%', fp);
19+			putc(tab[(uc >> 4) & 0x0f], fp);
20+			putc(tab[uc & 0x0f], fp);
21+		} else {
22+			putc(uc, fp);
23+		}
24+	}
25+}
26+
27 /* Escape characters below as HTML 2.0 / XML 1.0. */
28 void
29 xmlencode(FILE *fp, const char *s, size_t len)
30@@ -497,7 +519,7 @@ writeheader(FILE *fp, const char *title)
31 	fputs("</span></td></tr>", fp);
32 	if (cloneurl[0]) {
33 		fputs("<tr class=\"url\"><td></td><td>git clone <a href=\"", fp);
34-		xmlencode(fp, cloneurl, strlen(cloneurl));
35+		xmlencode(fp, cloneurl, strlen(cloneurl)); /* not percent-encoded */
36 		fputs("\">", fp);
37 		xmlencode(fp, cloneurl, strlen(cloneurl));
38 		fputs("</a></td></tr>", fp);
39@@ -570,7 +592,7 @@ printcommit(FILE *fp, struct commitinfo *ci)
40 		fputs("<b>Author:</b> ", fp);
41 		xmlencode(fp, ci->author->name, strlen(ci->author->name));
42 		fputs(" &lt;<a href=\"mailto:", fp);
43-		xmlencode(fp, ci->author->email, strlen(ci->author->email));
44+		xmlencode(fp, ci->author->email, strlen(ci->author->email)); /* not percent-encoded */
45 		fputs("\">", fp);
46 		xmlencode(fp, ci->author->email, strlen(ci->author->email));
47 		fputs("</a>&gt;\n<b>Date:</b>   ", fp);
48@@ -665,11 +687,11 @@ printshowfile(FILE *fp, struct commitinfo *ci)
49 		patch = ci->deltas[i]->patch;
50 		delta = git_patch_get_delta(patch);
51 		fprintf(fp, "<b>diff --git a/<a id=\"h%zu\" href=\"%sfile/", i, relpath);
52-		xmlencode(fp, delta->old_file.path, strlen(delta->old_file.path));
53+		percentencode(fp, delta->old_file.path, strlen(delta->old_file.path));
54 		fputs(".html\">", fp);
55 		xmlencode(fp, delta->old_file.path, strlen(delta->old_file.path));
56 		fprintf(fp, "</a> b/<a href=\"%sfile/", relpath);
57-		xmlencode(fp, delta->new_file.path, strlen(delta->new_file.path));
58+		percentencode(fp, delta->new_file.path, strlen(delta->new_file.path));
59 		fprintf(fp, ".html\">");
60 		xmlencode(fp, delta->new_file.path, strlen(delta->new_file.path));
61 		fprintf(fp, "</a></b>\n");
62@@ -1037,7 +1059,7 @@ writefilestree(FILE *fp, git_tree *tree, const char *path)
63 			fputs("<tr><td>", fp);
64 			fputs(filemode(git_tree_entry_filemode(entry)), fp);
65 			fprintf(fp, "</td><td><a href=\"%s", relpath);
66-			xmlencode(fp, filepath, strlen(filepath));
67+			percentencode(fp, filepath, strlen(filepath));
68 			fputs("\">", fp);
69 			xmlencode(fp, entrypath, strlen(entrypath));
70 			fputs("</a></td><td class=\"num\" align=\"right\">", fp);