mirror of
https://github.com/emikulic/darkhttpd.git
synced 2023-08-10 21:13:08 +03:00
Escape URLs according to RFC3986.
Previously, we weren't escaping parentheses when generating directory listings. Pointed out by: Wijatmoko U. Prayitno
This commit is contained in:
parent
c4c0034242
commit
1c5fdb5607
29
darkhttpd.c
29
darkhttpd.c
|
@ -1675,25 +1675,24 @@ static void cleanup_sorted_dirlist(struct dlent **list, const ssize_t size) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Should this character be urlencoded? (according to RFC1738)
|
/* Is this an unreserved character according to
|
||||||
* Contributed by nf.
|
* https://tools.ietf.org/html/rfc3986#section-2.3
|
||||||
*/
|
*/
|
||||||
static int needs_urlencoding(const unsigned char c) {
|
static int is_unreserved(const unsigned char c) {
|
||||||
unsigned int i;
|
if (c >= 'a' && c <= 'z') return 1;
|
||||||
static const char bad[] = "<>\"%{}|^~[]`\\;:/?@#=&";
|
if (c >= 'A' && c <= 'Z') return 1;
|
||||||
|
if (c >= '0' && c <= '9') return 1;
|
||||||
/* Non-US-ASCII characters */
|
switch (c) {
|
||||||
if ((c <= 0x1F) || (c >= 0x7F))
|
case '-':
|
||||||
|
case '.':
|
||||||
|
case '_':
|
||||||
|
case '~':
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
for (i = 0; i < sizeof(bad) - 1; i++)
|
|
||||||
if (c == bad[i])
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Encode string to be an RFC1738-compliant URL part.
|
/* Encode string to be an RFC3986-compliant URL part.
|
||||||
* Contributed by nf.
|
* Contributed by nf.
|
||||||
*/
|
*/
|
||||||
static void urlencode(const char *src, char *dest) {
|
static void urlencode(const char *src, char *dest) {
|
||||||
|
@ -1701,7 +1700,7 @@ static void urlencode(const char *src, char *dest) {
|
||||||
int i, j;
|
int i, j;
|
||||||
|
|
||||||
for (i = j = 0; src[i] != '\0'; i++) {
|
for (i = j = 0; src[i] != '\0'; i++) {
|
||||||
if (needs_urlencoding((unsigned char)src[i])) {
|
if (!is_unreserved((unsigned char)src[i])) {
|
||||||
dest[j++] = '%';
|
dest[j++] = '%';
|
||||||
dest[j++] = hex[(src[i] >> 4) & 0xF];
|
dest[j++] = hex[(src[i] >> 4) & 0xF];
|
||||||
dest[j++] = hex[ src[i] & 0xF];
|
dest[j++] = hex[ src[i] & 0xF];
|
||||||
|
|
|
@ -151,7 +151,7 @@ class TestHelper(unittest.TestCase):
|
||||||
|
|
||||||
class TestDirList(TestHelper):
|
class TestDirList(TestHelper):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.fn = WWWROOT+"/escape#this"
|
self.fn = WWWROOT+"/escape(this)name"
|
||||||
open(self.fn, "w").write("x"*12345)
|
open(self.fn, "w").write("x"*12345)
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
|
@ -161,7 +161,7 @@ class TestDirList(TestHelper):
|
||||||
resp = self.get("/")
|
resp = self.get("/")
|
||||||
status, hdrs, body = parse(resp)
|
status, hdrs, body = parse(resp)
|
||||||
self.assertEquals(ord("#"), 0x23)
|
self.assertEquals(ord("#"), 0x23)
|
||||||
self.assertContains(body, "escape%23this", "12345")
|
self.assertContains(body, "escape%28this%29name", "12345")
|
||||||
|
|
||||||
class TestCases(TestHelper):
|
class TestCases(TestHelper):
|
||||||
pass # these get autogenerated in setUpModule()
|
pass # these get autogenerated in setUpModule()
|
||||||
|
|
Loading…
Reference in New Issue
Block a user