mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-05-27 15:52:28 +00:00
Make more major improvements to redbean
- POSIX regular expressions for Lua - Improved protocol parsing and encoding - Additional APIs for ZIP storage retrieval - Fix st_mode issue on NT for regular files - Generalized APIs for URL and Host handling - Worked out the kinks in resource resolution - Allow for custom error pages like /404.html
This commit is contained in:
parent
26ac6871da
commit
4effa23528
74 changed files with 3710 additions and 14246 deletions
144
net/http/encodeurl.c
Normal file
144
net/http/encodeurl.c
Normal file
|
@ -0,0 +1,144 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "net/http/escape.h"
|
||||
#include "net/http/url.h"
|
||||
|
||||
static size_t DimensionUrl(struct Url *h) {
|
||||
size_t i, n;
|
||||
n = 0;
|
||||
n += h->scheme.n;
|
||||
n += 1;
|
||||
n += 2;
|
||||
n += h->user.n * 3;
|
||||
n += 1;
|
||||
n += h->pass.n * 3;
|
||||
n += 1;
|
||||
n += 1;
|
||||
n += h->host.n * 3;
|
||||
n += 1;
|
||||
n += 1;
|
||||
n += h->port.n * 3;
|
||||
n += 1;
|
||||
n += h->path.n * 3;
|
||||
n += 1;
|
||||
n += h->params.n;
|
||||
for (i = 0; i < h->params.n; ++i) {
|
||||
n += h->params.p[i].key.n * 3;
|
||||
n += 1;
|
||||
n += h->params.p[i].val.n * 3;
|
||||
}
|
||||
n += 1;
|
||||
n += h->fragment.n * 3;
|
||||
n += 1;
|
||||
return n;
|
||||
}
|
||||
|
||||
static bool NeedsSquareBrackets(struct Url *h) {
|
||||
int c;
|
||||
size_t i;
|
||||
if (!memchr(h->host.p, ':', h->host.n)) return false;
|
||||
if (h->pass.p) return true;
|
||||
if (h->host.n >= 4 && h->host.p[0] == 'v' && h->host.p[2] == '.' &&
|
||||
kHexToInt[h->host.p[1] & 0xFF] != -1) {
|
||||
for (i = 3; i < h->host.n; ++i) {
|
||||
if (kEscapeIp[h->host.p[i] & 0xFF]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < h->host.n; ++i) {
|
||||
c = h->host.p[i] & 0xFF;
|
||||
if (!(kHexToInt[c] || c == '.' || c == ':')) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes URL.
|
||||
*
|
||||
* @param z if not null receives string length of result
|
||||
* @return nul-terminated url string needing free
|
||||
* @see ParseUrl()
|
||||
*/
|
||||
char *EncodeUrl(struct Url *h, size_t *z) {
|
||||
size_t i, n;
|
||||
char *m, *p;
|
||||
if ((p = m = malloc(DimensionUrl(h)))) {
|
||||
if (h->scheme.n) {
|
||||
p = mempcpy(p, h->scheme.p, h->scheme.n);
|
||||
*p++ = ':';
|
||||
}
|
||||
if (h->host.p) {
|
||||
*p++ = '/';
|
||||
*p++ = '/';
|
||||
if (h->user.p) {
|
||||
p = EscapeUrlView(p, &h->user, kEscapeAuthority);
|
||||
if (h->pass.p) {
|
||||
*p++ = ':';
|
||||
p = EscapeUrlView(p, &h->pass, kEscapeAuthority);
|
||||
}
|
||||
*p++ = '@';
|
||||
}
|
||||
if (h->host.p) {
|
||||
if (NeedsSquareBrackets(h)) {
|
||||
*p++ = '[';
|
||||
p = EscapeUrlView(p, &h->host, kEscapeIp);
|
||||
*p++ = ']';
|
||||
} else {
|
||||
p = EscapeUrlView(p, &h->host, kEscapeAuthority);
|
||||
}
|
||||
if (h->port.p) {
|
||||
*p++ = ':';
|
||||
p = EscapeUrlView(p, &h->port, kEscapeAuthority);
|
||||
}
|
||||
}
|
||||
if (h->path.n && h->path.p[0] != '/') {
|
||||
*p++ = '/';
|
||||
}
|
||||
}
|
||||
p = EscapeUrlView(p, &h->path, kEscapePath);
|
||||
if (h->params.p) {
|
||||
*p++ = '?';
|
||||
for (i = 0; i < h->params.n; ++i) {
|
||||
if (i) *p++ = '&';
|
||||
p = EscapeUrlView(p, &h->params.p[i].key, kEscapeParam);
|
||||
if (h->params.p[i].val.p) {
|
||||
*p++ = '=';
|
||||
p = EscapeUrlView(p, &h->params.p[i].val, kEscapeParam);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (h->fragment.p) {
|
||||
*p++ = '#';
|
||||
p = EscapeUrlView(p, &h->fragment, kEscapeFragment);
|
||||
}
|
||||
n = p - m;
|
||||
*p++ = '\0';
|
||||
if ((p = realloc(m, p - m))) m = p;
|
||||
} else {
|
||||
n = 0;
|
||||
}
|
||||
if (z) *z = n;
|
||||
return m;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue