commit f2f8eb35c86c4e1c1d858e782c864deac0511cd3 from: Omar Polo date: Mon Jul 04 09:31:36 2022 UTC encode file names in the directory index Spotted the hard way by cage commit - 3bd4a6dea08fc977e314877cefed1c6fdd6b1613 commit + f2f8eb35c86c4e1c1d858e782c864deac0511cd3 blob - cc6253a87732028a882fa4e58463565bd9d82732 blob + a866109d8595001d91cc300ee49c947625588558 --- gmid.h +++ gmid.h @@ -427,6 +427,7 @@ char *utf8_nth(char*, size_t); /* iri.c */ int parse_iri(char*, struct iri*, const char**); int serialize_iri(struct iri*, char*, size_t); +int encode_path(char *, size_t, const char *); char *pct_decode_str(char *); /* proxy.c */ blob - f34b800bae813b3cf0b3f839acabeb9754ba63bb blob + 4224e6166e867cbd1c214fb6c504c684f40f21b0 --- iri.c +++ iri.c @@ -443,7 +443,44 @@ serialize_iri(struct iri *i, char *buf, size_t len) return l < len; } + +int +encode_path(char *buf, size_t len, const char *path) +{ + char *p = buf; + int a, b; + + memset(buf, 0, len); + while (*path != '\0') { + if (len == 1) /* NUL */ + return -1; + if (unreserved(*path) || + sub_delimiters(*path) || + *path == '@' || + *path == ':' || + *path == '/') { + *p++ = *path++; + len--; + } else if (len < 4) + return -1; + else { + a = (*path & 0xF0) >> 4; + b = (*path & 0x0F); + + p[0] = '%'; + p[1] = a <= 9 ? ('0' + a) : ('7' + a); + p[2] = b <= 9 ? ('0' + b) : ('7' + b); + + path++; + p += 3; + len -= 3; + } + } + + return 0; +} + char * pct_decode_str(char *s) { blob - c69c13daee56925c9114387cc7dd917ebab1ebaa blob + 27227dd9a1e373033c048acdde32447e5ef3f5f0 --- server.c +++ server.c @@ -1070,6 +1070,7 @@ client_write(struct bufferevent *bev, void *d) { struct client *c = d; struct evbuffer *out = EVBUFFER_OUTPUT(bev); + char nam[PATH_MAX]; char buf[BUFSIZ]; ssize_t r; @@ -1097,8 +1098,9 @@ client_write(struct bufferevent *bev, void *d) case REQUEST_DIR: /* TODO: handle big big directories better */ for (c->diroff = 0; c->diroff < c->dirlen; ++c->diroff) { - evbuffer_add_printf(out, "=> %s\n", + encode_path(nam, sizeof(nam), c->dir[c->diroff]->d_name); + evbuffer_add_printf(out, "=> ./%s\n", nam); free(c->dir[c->diroff]); } free(c->dir);