Skip to content

Commit 09bcfa2

Browse files
committed
Make major improvements to redbean
- lua server pages - lua http library - http v0.9 support - request uri parsing - fork failure recovery - accelerated redirects - http pipelining support - lenient message framing - html / uri / js escaping - fix shutdown signal handling
1 parent 6b90ff6 commit 09bcfa2

23 files changed

+2173
-546
lines changed

libc/zip.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
#define kZipLfileOffsetLastmodifieddate 12
7070
#define kZipLfileOffsetCrc32 14
7171
#define kZipLfileOffsetCompressedsize 18
72+
#define kZipLfileOffsetUncompressedsize 22
7273

7374
#define kZipGflagUtf8 0x800
7475

@@ -140,11 +141,12 @@
140141
#define ZIP_LFILE_CRC32(P) READ32LE((P) + kZipLfileOffsetCrc32)
141142
#define ZIP_LFILE_COMPRESSEDSIZE(P) \
142143
READ32LE((P) + kZipLfileOffsetCompressedsize)
143-
#define ZIP_LFILE_UNCOMPRESSEDSIZE(P) READ32LE((P) + 22)
144-
#define ZIP_LFILE_NAMESIZE(P) READ16LE((P) + 26)
145-
#define ZIP_LFILE_EXTRASIZE(P) READ16LE((P) + 28)
146-
#define ZIP_LFILE_NAME(P) ((const char *)(&(P)[30]))
147-
#define ZIP_LFILE_EXTRA(P) (&(P)[30 + ZIP_LFILE_NAMESIZE(P)])
144+
#define ZIP_LFILE_UNCOMPRESSEDSIZE(P) \
145+
READ32LE((P) + kZipLfileOffsetUncompressedsize)
146+
#define ZIP_LFILE_NAMESIZE(P) READ16LE((P) + 26)
147+
#define ZIP_LFILE_EXTRASIZE(P) READ16LE((P) + 28)
148+
#define ZIP_LFILE_NAME(P) ((const char *)(&(P)[30]))
149+
#define ZIP_LFILE_EXTRA(P) (&(P)[30 + ZIP_LFILE_NAMESIZE(P)])
148150
#define ZIP_LFILE_HDRSIZE(P) \
149151
(ZIP_LFILE_NAMESIZE(P) + ZIP_LFILE_EXTRASIZE(P) + kZipLfileHdrMinSize)
150152
#define ZIP_LFILE_CONTENT(P) ((P) + ZIP_LFILE_HDRSIZE(P))

net/http/escape.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#ifndef COSMOPOLITAN_NET_HTTP_ESCAPE_H_
2+
#define COSMOPOLITAN_NET_HTTP_ESCAPE_H_
3+
#if !(__ASSEMBLER__ + __LINKER__ + 0)
4+
COSMOPOLITAN_C_START_
5+
6+
struct EscapeResult {
7+
char *data;
8+
size_t size;
9+
};
10+
11+
struct EscapeResult EscapeHtml(const char *, size_t);
12+
struct EscapeResult EscapeUrl(const char *, size_t, const char[hasatleast 256]);
13+
struct EscapeResult EscapeUrlPath(const char *, size_t);
14+
struct EscapeResult EscapeUrlParam(const char *, size_t);
15+
struct EscapeResult EscapeUrlFragment(const char *, size_t);
16+
struct EscapeResult EscapeUrlPathSegment(const char *, size_t);
17+
struct EscapeResult EscapeJsStringLiteral(const char *, size_t);
18+
19+
COSMOPOLITAN_C_END_
20+
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
21+
#endif /* COSMOPOLITAN_NET_HTTP_ESCAPE_H_ */

net/http/escapehtml.c

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
2+
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
3+
╞══════════════════════════════════════════════════════════════════════════════╡
4+
│ Copyright 2021 Justine Alexandra Roberts Tunney │
5+
│ │
6+
│ Permission to use, copy, modify, and/or distribute this software for │
7+
│ any purpose with or without fee is hereby granted, provided that the │
8+
│ above copyright notice and this permission notice appear in all copies. │
9+
│ │
10+
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
11+
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
12+
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
13+
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
14+
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
15+
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
16+
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
17+
│ PERFORMANCE OF THIS SOFTWARE. │
18+
╚─────────────────────────────────────────────────────────────────────────────*/
19+
#include "libc/x/x.h"
20+
#include "net/http/escape.h"
21+
22+
/**
23+
* Escapes HTML entities.
24+
*/
25+
struct EscapeResult EscapeHtml(const char *data, size_t size) {
26+
int c;
27+
char *p;
28+
size_t i;
29+
struct EscapeResult r;
30+
p = r.data = xmalloc(size * 6 + 1);
31+
for (i = 0; i < size; ++i) {
32+
switch ((c = data[i])) {
33+
case '&':
34+
p[0] = '&';
35+
p[1] = 'a';
36+
p[2] = 'm';
37+
p[3] = 'p';
38+
p[4] = ';';
39+
p += 5;
40+
break;
41+
case '<':
42+
p[0] = '&';
43+
p[1] = 'l';
44+
p[2] = 't';
45+
p[3] = ';';
46+
p += 4;
47+
break;
48+
case '>':
49+
p[0] = '&';
50+
p[1] = 'g';
51+
p[2] = 't';
52+
p[3] = ';';
53+
p += 4;
54+
break;
55+
case '"':
56+
p[0] = '&';
57+
p[1] = 'q';
58+
p[2] = 'u';
59+
p[3] = 'o';
60+
p[4] = 't';
61+
p[5] = ';';
62+
p += 6;
63+
break;
64+
case '\'':
65+
p[0] = '&';
66+
p[1] = '#';
67+
p[2] = '3';
68+
p[3] = '9';
69+
p[4] = ';';
70+
p += 5;
71+
break;
72+
default:
73+
*p++ = c;
74+
break;
75+
}
76+
}
77+
r.size = p - r.data;
78+
r.data = xrealloc(r.data, r.size + 1);
79+
r.data[r.size] = '\0';
80+
return r;
81+
}

net/http/escapejsstringliteral.c

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
2+
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
3+
╞══════════════════════════════════════════════════════════════════════════════╡
4+
│ Copyright 2021 Justine Alexandra Roberts Tunney │
5+
│ │
6+
│ Permission to use, copy, modify, and/or distribute this software for │
7+
│ any purpose with or without fee is hereby granted, provided that the │
8+
│ above copyright notice and this permission notice appear in all copies. │
9+
│ │
10+
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
11+
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
12+
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
13+
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
14+
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
15+
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
16+
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
17+
│ PERFORMANCE OF THIS SOFTWARE. │
18+
╚─────────────────────────────────────────────────────────────────────────────*/
19+
#include "libc/str/thompike.h"
20+
#include "libc/str/utf16.h"
21+
#include "libc/x/x.h"
22+
#include "net/http/escape.h"
23+
24+
/**
25+
* Escapes UTF-8 data for JavaScript or JSON string literal.
26+
*
27+
* HTML entities and forward slash are escaped too for added safety.
28+
*
29+
* We assume the UTF-8 is well-formed and can be represented as UTF-16.
30+
* Things that can't be decoded or encoded will be replaced with invalid
31+
* code-point markers. This function is agnostic to numbers that have
32+
* been used with malicious intent in the past under buggy software.
33+
* Noncanonical encodings such as overlong NUL are canonicalized as NUL.
34+
*/
35+
struct EscapeResult EscapeJsStringLiteral(const char *data, size_t size) {
36+
char *p;
37+
size_t i;
38+
unsigned n;
39+
uint64_t w;
40+
wint_t x, y;
41+
struct EscapeResult r;
42+
p = r.data = xmalloc(size * 6 + 6 + 1);
43+
for (i = 0; i < size;) {
44+
x = data[i++] & 0xff;
45+
if (x >= 0200) {
46+
if (x >= 0300) {
47+
n = ThomPikeLen(x);
48+
x = ThomPikeByte(x);
49+
while (--n) {
50+
if (i < size) {
51+
y = data[i++] & 0xff;
52+
if (ThomPikeCont(y)) {
53+
x = ThomPikeMerge(x, y);
54+
} else {
55+
x = 0xFFFD;
56+
break;
57+
}
58+
} else {
59+
x = 0xFFFD;
60+
break;
61+
}
62+
}
63+
} else {
64+
x = 0xFFFD;
65+
}
66+
}
67+
switch (x) {
68+
case '\t':
69+
p[0] = '\\';
70+
p[1] = 't';
71+
p += 2;
72+
break;
73+
case '\n':
74+
p[0] = '\\';
75+
p[1] = 'n';
76+
p += 2;
77+
break;
78+
case '\r':
79+
p[0] = '\\';
80+
p[1] = 'r';
81+
p += 2;
82+
break;
83+
case '\f':
84+
p[0] = '\\';
85+
p[1] = 'f';
86+
p += 2;
87+
break;
88+
case '\\':
89+
p[0] = '\\';
90+
p[1] = '\\';
91+
p += 2;
92+
break;
93+
case '/':
94+
p[0] = '\\';
95+
p[1] = '/';
96+
p += 2;
97+
break;
98+
case '"':
99+
p[0] = '\\';
100+
p[1] = '"';
101+
p += 2;
102+
break;
103+
case '\'':
104+
p[0] = '\\';
105+
p[1] = '\'';
106+
p += 2;
107+
break;
108+
default:
109+
if (0x20 <= x && x < 0x7F) {
110+
*p++ = x;
111+
break;
112+
}
113+
/* fallthrough */
114+
case '<':
115+
case '>':
116+
case '&':
117+
case '=':
118+
w = EncodeUtf16(x);
119+
do {
120+
p[0] = '\\';
121+
p[1] = 'u';
122+
p[2] = "0123456789ABCDEF"[(w & 0xF000) >> 014];
123+
p[3] = "0123456789ABCDEF"[(w & 0x0F00) >> 010];
124+
p[4] = "0123456789ABCDEF"[(w & 0x00F0) >> 004];
125+
p[5] = "0123456789ABCDEF"[(w & 0x000F) >> 000];
126+
p += 6;
127+
} while ((w >>= 16));
128+
break;
129+
}
130+
}
131+
r.size = p - r.data;
132+
r.data = xrealloc(r.data, r.size + 1);
133+
r.data[r.size] = '\0';
134+
return r;
135+
}

net/http/escapeurl.c

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
2+
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
3+
╞══════════════════════════════════════════════════════════════════════════════╡
4+
│ Copyright 2021 Justine Alexandra Roberts Tunney │
5+
│ │
6+
│ Permission to use, copy, modify, and/or distribute this software for │
7+
│ any purpose with or without fee is hereby granted, provided that the │
8+
│ above copyright notice and this permission notice appear in all copies. │
9+
│ │
10+
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
11+
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
12+
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
13+
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
14+
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
15+
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
16+
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
17+
│ PERFORMANCE OF THIS SOFTWARE. │
18+
╚─────────────────────────────────────────────────────────────────────────────*/
19+
#include "libc/x/x.h"
20+
#include "net/http/escape.h"
21+
22+
/**
23+
* Escapes URL component using generic table.
24+
*
25+
* This function is agnostic to the underlying charset.
26+
* Always using UTF-8 is a good idea.
27+
*
28+
* @see EscapeUrlParam
29+
* @see EscapeUrlFragment
30+
* @see EscapeUrlPathSegment
31+
*/
32+
struct EscapeResult EscapeUrl(const char *data, size_t size,
33+
const char xlat[hasatleast 256]) {
34+
int c;
35+
char *p;
36+
size_t i;
37+
struct EscapeResult r;
38+
p = r.data = xmalloc(size * 6 + 1);
39+
for (i = 0; i < size; ++i) {
40+
switch (xlat[(c = data[i] & 0xff)]) {
41+
case 0:
42+
*p++ = c;
43+
break;
44+
case 1:
45+
*p++ = '+';
46+
break;
47+
case 2:
48+
p[0] = '%';
49+
p[1] = "0123456789ABCDEF"[(c & 0xF0) >> 4];
50+
p[2] = "0123456789ABCDEF"[(c & 0x0F) >> 0];
51+
p += 3;
52+
break;
53+
default:
54+
unreachable;
55+
}
56+
}
57+
r.size = p - r.data;
58+
r.data = xrealloc(r.data, r.size + 1);
59+
r.data[r.size] = '\0';
60+
return r;
61+
}

net/http/escapeurlfragment.c

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
2+
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
3+
╞══════════════════════════════════════════════════════════════════════════════╡
4+
│ Copyright 2021 Justine Alexandra Roberts Tunney │
5+
│ │
6+
│ Permission to use, copy, modify, and/or distribute this software for │
7+
│ any purpose with or without fee is hereby granted, provided that the │
8+
│ above copyright notice and this permission notice appear in all copies. │
9+
│ │
10+
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
11+
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
12+
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
13+
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
14+
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
15+
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
16+
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
17+
│ PERFORMANCE OF THIS SOFTWARE. │
18+
╚─────────────────────────────────────────────────────────────────────────────*/
19+
#include "libc/x/x.h"
20+
#include "net/http/escape.h"
21+
22+
// url fragment dispatch
23+
// - 0 is -/?.~_@:!$&'()*+,;=0-9A-Za-z
24+
// - 2 is everything else which needs uppercase hex %XX
25+
// note that '& can break html
26+
// note that '() can break css urls
27+
// note that unicode can still be wild
28+
static const char kEscapeUrlFragment[256] = {
29+
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0x00
30+
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0x10
31+
2, 0, 2, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x20
32+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, // 0x30
33+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x40
34+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, // 0x50
35+
2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x60
36+
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, 2, // 0x70
37+
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0x80
38+
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0x90
39+
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xa0
40+
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xb0
41+
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xc0
42+
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xd0
43+
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xe0
44+
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xf0
45+
};
46+
47+
/**
48+
* Escapes URL fragment.
49+
*/
50+
struct EscapeResult EscapeUrlFragment(const char *data, size_t size) {
51+
return EscapeUrl(data, size, kEscapeUrlFragment);
52+
}

0 commit comments

Comments
 (0)