mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-05-23 05:42:29 +00:00
Add /statusz page to redbean plus other enhancements
redbean improvements: - Explicitly disable corking - Simulate Python regex API for Lua - Send warmup requests in main process on startup - Add Class-A granular IPv4 network classification - Add /statusz page so you can monitor your redbean's health - Fix regressions on OpenBSD/NetBSD caused by recent changes - Plug Authorization header into Lua GetUser and GetPass APIs - Recognize X-Forwarded-{For,Host} from local reverse proxies - Add many additional functions to redbean Lua server page API - Report resource usage of child processes on `/` listing page - Introduce `-a` flag for logging child process resource usage - Introduce `-t MILLIS` flag and `ProgramTimeout(ms)` init API - Introduce `-H "Header: value"` flag and `ProgramHeader(k,v)` API Cosmopolitan Libc improvements: - Make strerror() simpler - Make inet_pton() not depend on sscanf() - Fix OpenExecutable() which broke .data section earlier - Fix stdio in cases where it overflows kernel tty buffer - Fix bugs in crash reporting w/o .com.dbg binary present - Add polyfills for SO_LINGER, SO_RCVTIMEO, and SO_SNDTIMEO - Polyfill TCP_CORK on BSD and XNU using TCP_NOPUSH magnums New netcat clone in examples/nc.c: While testing some of the failure conditions for redbean, I noticed that BusyBox's `nc` command is pretty busted, if you use it as an interactive tool, rather than having it be part of a pipeline. Unfortunately this'll only work on UNIX since Windows doesn't let us poll on stdio and sockets at the same time because I don't think they want tools like this running on their platform. So if you want forbidden fruit, it's here so enjoy it
This commit is contained in:
parent
4effa23528
commit
b107d2709f
163 changed files with 4425 additions and 2104 deletions
|
@ -1,11 +0,0 @@
|
|||
#ifndef COSMOPOLITAN_NET_HTTP_BASE64_H_
|
||||
#define COSMOPOLITAN_NET_HTTP_BASE64_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
char *EncodeBase64(const void *, size_t, size_t *);
|
||||
void *DecodeBase64(const char *, size_t, size_t *);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_NET_HTTP_BASE64_H_ */
|
50
net/http/categorizeip.c
Normal file
50
net/http/categorizeip.c
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*-*- 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 "net/http/ip.h"
|
||||
|
||||
/**
|
||||
* Classifies IP address.
|
||||
*
|
||||
* @return integer e.g. kIpLoopback, kIpPrivate, etc.
|
||||
* @see GetIpCategoryName()
|
||||
*/
|
||||
int CategorizeIp(uint32_t x) {
|
||||
int a;
|
||||
if (IsAnonymousIp(x)) return kIpAnonymous;
|
||||
if (IsMulticastIp(x)) return kIpMulticast;
|
||||
if (IsLoopbackIp(x)) return kIpLoopback;
|
||||
if (IsPrivateIp(x)) return kIpPrivate;
|
||||
if (IsTestnetIp(x)) return kIpTestnet;
|
||||
if (IsAfrinicIp(x)) return kIpAfrinic;
|
||||
if (IsLacnicIp(x)) return kIpLacnic;
|
||||
if (IsApnicIp(x)) return kIpApnic;
|
||||
if (IsArinIp(x)) return kIpArin;
|
||||
if (IsRipeIp(x)) return kIpRipe;
|
||||
if (IsDodIp(x)) return kIpDod;
|
||||
a = (x & 0xff000000) >> 24;
|
||||
if (a == 12) return kIpAtt;
|
||||
if (a == 17) return kIpApple;
|
||||
if (a == 19) return kIpFord;
|
||||
if (a == 38) return kIpCogent;
|
||||
if (a == 48) return kIpPrudential;
|
||||
if (a == 56) return kIpUsps;
|
||||
if (a == 73) return kIpComcast;
|
||||
if (a >= 240) return kIpFuture;
|
||||
return kIpUnknown;
|
||||
}
|
|
@ -18,7 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "net/http/base64.h"
|
||||
#include "net/http/escape.h"
|
||||
|
||||
static const signed char kBase64[256] = {
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0x00
|
||||
|
@ -47,7 +47,7 @@ static const signed char kBase64[256] = {
|
|||
* @param out_size if non-NULL receives output length
|
||||
* @return allocated NUL-terminated buffer, or NULL w/ errno
|
||||
*/
|
||||
void *DecodeBase64(const char *data, size_t size, size_t *out_size) {
|
||||
char *DecodeBase64(const char *data, size_t size, size_t *out_size) {
|
||||
size_t n;
|
||||
char *r, *q;
|
||||
int a, b, c, d, w;
|
||||
|
|
|
@ -20,28 +20,35 @@
|
|||
#include "libc/intrin/pmovmskb.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "net/http/http.h"
|
||||
#include "net/http/escape.h"
|
||||
|
||||
/**
|
||||
* Decodes ISO-8859-1 to UTF-8.
|
||||
*
|
||||
* @param data is input value
|
||||
* @param size if -1 implies strlen
|
||||
* @param out_size if non-NULL receives output length
|
||||
* @param p is input value
|
||||
* @param n if -1 implies strlen
|
||||
* @param z if non-NULL receives output length
|
||||
* @return allocated NUL-terminated buffer, or NULL w/ errno
|
||||
*/
|
||||
char *DecodeLatin1(const char *data, size_t size, size_t *out_size) {
|
||||
char *DecodeLatin1(const char *p, size_t n, size_t *z) {
|
||||
int c;
|
||||
size_t n;
|
||||
size_t i;
|
||||
char *r, *q;
|
||||
const char *p, *e;
|
||||
if (size == -1) size = data ? strlen(data) : 0;
|
||||
if ((r = malloc(size * 2 + 1))) {
|
||||
q = r;
|
||||
p = data;
|
||||
e = p + size;
|
||||
while (p < e) {
|
||||
c = *p++ & 0xff;
|
||||
int8_t v1[16], v2[16], vz[16];
|
||||
if (z) *z = 0;
|
||||
if (n == -1) n = p ? strlen(p) : 0;
|
||||
if ((q = r = malloc(n * 2 + 1))) {
|
||||
for (i = 0; i < n;) {
|
||||
memset(vz, 0, 16); /* 3x speedup for ASCII */
|
||||
while (i + 16 < n) {
|
||||
memcpy(v1, p + i, 16);
|
||||
pcmpgtb(v2, v1, vz);
|
||||
if (pmovmskb((void *)v2) != 0xFFFF) break;
|
||||
memcpy(q, v1, 16);
|
||||
q += 16;
|
||||
i += 16;
|
||||
}
|
||||
c = p[i++] & 0xff;
|
||||
if (c < 0200) {
|
||||
*q++ = c;
|
||||
} else {
|
||||
|
@ -49,14 +56,9 @@ char *DecodeLatin1(const char *data, size_t size, size_t *out_size) {
|
|||
*q++ = 0200 | c & 077;
|
||||
}
|
||||
}
|
||||
n = q - r;
|
||||
if (z) *z = q - r;
|
||||
*q++ = '\0';
|
||||
if ((q = realloc(r, n + 1))) r = q;
|
||||
} else {
|
||||
n = 0;
|
||||
}
|
||||
if (out_size) {
|
||||
*out_size = n;
|
||||
if ((q = realloc(r, q - r))) r = q;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "net/http/base64.h"
|
||||
#include "net/http/escape.h"
|
||||
|
||||
#define CHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
|
||||
|
||||
|
@ -30,7 +30,7 @@
|
|||
* @param out_size if non-NULL receives output length
|
||||
* @return allocated NUL-terminated buffer, or NULL w/ errno
|
||||
*/
|
||||
char *EncodeBase64(const void *data, size_t size, size_t *out_size) {
|
||||
char *EncodeBase64(const char *data, size_t size, size_t *out_size) {
|
||||
size_t n;
|
||||
unsigned w;
|
||||
char *r, *q;
|
||||
|
@ -39,7 +39,7 @@ char *EncodeBase64(const void *data, size_t size, size_t *out_size) {
|
|||
if ((n = size) % 3) n += 3 - size % 3;
|
||||
n /= 3, n *= 4;
|
||||
if ((r = malloc(n + 1))) {
|
||||
for (q = r, p = data, pe = p + size; p < pe; p += 3) {
|
||||
for (q = r, p = (void *)data, pe = p + size; p < pe; p += 3) {
|
||||
w = p[0] << 020;
|
||||
if (p + 1 < pe) w |= p[1] << 010;
|
||||
if (p + 2 < pe) w |= p[2] << 000;
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
#include "libc/mem/mem.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/thompike.h"
|
||||
#include "net/http/http.h"
|
||||
#include "net/http/escape.h"
|
||||
|
||||
/**
|
||||
* Encodes HTTP header value.
|
||||
|
|
72
net/http/encodelatin1.c
Normal file
72
net/http/encodelatin1.c
Normal file
|
@ -0,0 +1,72 @@
|
|||
/*-*- 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/errno.h"
|
||||
#include "libc/intrin/pcmpgtb.h"
|
||||
#include "libc/intrin/pmovmskb.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "net/http/escape.h"
|
||||
|
||||
/**
|
||||
* Encodes UTF-8 to ISO-8859-1.
|
||||
*
|
||||
* @param p is input value
|
||||
* @param n if -1 implies strlen
|
||||
* @param z if non-NULL receives output length
|
||||
* @param f can kControlC0, kControlC1 to forbid
|
||||
* @return allocated NUL-terminated buffer, or NULL w/ errno
|
||||
* @error EILSEQ means UTF-8 found we can't or won't re-encode
|
||||
* @error ENOMEM means malloc() failed
|
||||
*/
|
||||
char *EncodeLatin1(const char *p, size_t n, size_t *z, int f) {
|
||||
int c;
|
||||
size_t i;
|
||||
char *r, *q;
|
||||
if (z) *z = 0;
|
||||
if (n == -1) n = p ? strlen(p) : 0;
|
||||
if ((q = r = malloc(n + 1))) {
|
||||
for (i = 0; i < n;) {
|
||||
c = p[i++] & 0xff;
|
||||
if (c >= 0300) {
|
||||
if ((c <= 0303) && i < n && (p[i] & 0300) == 0200) {
|
||||
c = (c & 037) << 6 | p[i++] & 077;
|
||||
} else {
|
||||
goto Invalid;
|
||||
}
|
||||
}
|
||||
if (((f & kControlC1) && 0x80 <= c && c < 0xA0) ||
|
||||
((f & kControlC0) && (c < 32 || c == 0x7F) &&
|
||||
!(c == '\t' || c == '\r' || c == '\n' || c == '\v')) ||
|
||||
((f & kControlWs) &&
|
||||
(c == '\t' || c == '\r' || c == '\n' || c == '\v'))) {
|
||||
goto Invalid;
|
||||
}
|
||||
*q++ = c;
|
||||
}
|
||||
if (z) *z = q - r;
|
||||
*q++ = '\0';
|
||||
if ((q = realloc(r, q - r))) r = q;
|
||||
}
|
||||
return r;
|
||||
Invalid:
|
||||
free(r);
|
||||
errno = EILSEQ;
|
||||
return NULL;
|
||||
}
|
|
@ -1,13 +1,13 @@
|
|||
#ifndef COSMOPOLITAN_NET_HTTP_ESCAPE_H_
|
||||
#define COSMOPOLITAN_NET_HTTP_ESCAPE_H_
|
||||
|
||||
#define kControlWs 1
|
||||
#define kControlC0 2
|
||||
#define kControlC1 4
|
||||
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
struct EscapeResult {
|
||||
char *data;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
extern const signed char kHexToInt[256];
|
||||
extern const char kEscapeAuthority[256];
|
||||
extern const char kEscapeIp[256];
|
||||
|
@ -16,17 +16,27 @@ extern const char kEscapeSegment[256];
|
|||
extern const char kEscapeParam[256];
|
||||
extern const char kEscapeFragment[256];
|
||||
|
||||
struct EscapeResult EscapeHtml(const char *, size_t);
|
||||
struct EscapeResult EscapeUrl(const char *, size_t, const char[hasatleast 256]);
|
||||
struct EscapeResult EscapeUser(const char *, size_t);
|
||||
struct EscapeResult EscapePass(const char *, size_t);
|
||||
struct EscapeResult EscapeIp(const char *, size_t);
|
||||
struct EscapeResult EscapeHost(const char *, size_t);
|
||||
struct EscapeResult EscapePath(const char *, size_t);
|
||||
struct EscapeResult EscapeParam(const char *, size_t);
|
||||
struct EscapeResult EscapeFragment(const char *, size_t);
|
||||
struct EscapeResult EscapeSegment(const char *, size_t);
|
||||
struct EscapeResult EscapeJsStringLiteral(const char *, size_t);
|
||||
char *EscapeHtml(const char *, size_t, size_t *);
|
||||
char *EscapeUrl(const char *, size_t, size_t *, const char[256]);
|
||||
char *EscapeUser(const char *, size_t, size_t *);
|
||||
char *EscapePass(const char *, size_t, size_t *);
|
||||
char *EscapeIp(const char *, size_t, size_t *);
|
||||
char *EscapeHost(const char *, size_t, size_t *);
|
||||
char *EscapePath(const char *, size_t, size_t *);
|
||||
char *EscapeParam(const char *, size_t, size_t *);
|
||||
char *EscapeFragment(const char *, size_t, size_t *);
|
||||
char *EscapeSegment(const char *, size_t, size_t *);
|
||||
char *EscapeJsStringLiteral(const char *, size_t, size_t *);
|
||||
|
||||
bool HasControlCodes(const char *, size_t, int);
|
||||
char *Underlong(const char *, size_t, size_t *);
|
||||
char *DecodeLatin1(const char *, size_t, size_t *);
|
||||
char *EncodeLatin1(const char *, size_t, size_t *, int);
|
||||
char *EncodeHttpHeaderValue(const char *, size_t, size_t *);
|
||||
char *VisualizeControlCodes(const char *, size_t, size_t *);
|
||||
char *IndentLines(const char *, size_t, size_t *, size_t);
|
||||
char *EncodeBase64(const char *, size_t, size_t *);
|
||||
char *DecodeBase64(const char *, size_t, size_t *);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
|
|
@ -21,8 +21,11 @@
|
|||
/**
|
||||
* Escapes URL fragment.
|
||||
*
|
||||
* @param size if -1 implies strlen
|
||||
* @param p is input value
|
||||
* @param n if -1 implies strlen
|
||||
* @param z if non-NULL receives output length
|
||||
* @return allocated NUL-terminated buffer, or NULL w/ errno
|
||||
*/
|
||||
struct EscapeResult EscapeFragment(const char *data, size_t size) {
|
||||
return EscapeUrl(data, size, kEscapeFragment);
|
||||
char *EscapeFragment(const char *p, size_t n, size_t *z) {
|
||||
return EscapeUrl(p, n, z, kEscapeFragment);
|
||||
}
|
||||
|
|
|
@ -21,8 +21,11 @@
|
|||
/**
|
||||
* Escapes URL host or registry name.
|
||||
*
|
||||
* @param size if -1 implies strlen
|
||||
* @param p is input value
|
||||
* @param n if -1 implies strlen
|
||||
* @param z if non-NULL receives output length
|
||||
* @return allocated NUL-terminated buffer, or NULL w/ errno
|
||||
*/
|
||||
struct EscapeResult EscapeHost(const char *data, size_t size) {
|
||||
return EscapeUrl(data, size, kEscapeAuthority);
|
||||
char *EscapeHost(const char *p, size_t n, size_t *z) {
|
||||
return EscapeUrl(p, n, z, kEscapeAuthority);
|
||||
}
|
||||
|
|
|
@ -23,63 +23,67 @@
|
|||
/**
|
||||
* Escapes HTML entities.
|
||||
*
|
||||
* @param size if -1 implies strlen
|
||||
* @param p is input value
|
||||
* @param n if -1 implies strlen
|
||||
* @param z if non-NULL receives output length
|
||||
* @return allocated NUL-terminated buffer, or NULL w/ errno
|
||||
*/
|
||||
struct EscapeResult EscapeHtml(const char *data, size_t size) {
|
||||
char *EscapeHtml(const char *p, size_t n, size_t *z) {
|
||||
int c;
|
||||
char *p;
|
||||
size_t i;
|
||||
struct EscapeResult r;
|
||||
if (size == -1) size = data ? strlen(data) : 0;
|
||||
p = r.data = xmalloc(size * 6 + 1);
|
||||
for (i = 0; i < size; ++i) {
|
||||
switch ((c = data[i])) {
|
||||
case '&':
|
||||
p[0] = '&';
|
||||
p[1] = 'a';
|
||||
p[2] = 'm';
|
||||
p[3] = 'p';
|
||||
p[4] = ';';
|
||||
p += 5;
|
||||
break;
|
||||
case '<':
|
||||
p[0] = '&';
|
||||
p[1] = 'l';
|
||||
p[2] = 't';
|
||||
p[3] = ';';
|
||||
p += 4;
|
||||
break;
|
||||
case '>':
|
||||
p[0] = '&';
|
||||
p[1] = 'g';
|
||||
p[2] = 't';
|
||||
p[3] = ';';
|
||||
p += 4;
|
||||
break;
|
||||
case '"':
|
||||
p[0] = '&';
|
||||
p[1] = 'q';
|
||||
p[2] = 'u';
|
||||
p[3] = 'o';
|
||||
p[4] = 't';
|
||||
p[5] = ';';
|
||||
p += 6;
|
||||
break;
|
||||
case '\'':
|
||||
p[0] = '&';
|
||||
p[1] = '#';
|
||||
p[2] = '3';
|
||||
p[3] = '9';
|
||||
p[4] = ';';
|
||||
p += 5;
|
||||
break;
|
||||
default:
|
||||
*p++ = c;
|
||||
break;
|
||||
char *q, *r;
|
||||
if (z) *z = 0;
|
||||
if (n == -1) n = p ? strlen(p) : 0;
|
||||
if ((q = r = malloc(n * 6 + 1))) {
|
||||
for (i = 0; i < n; ++i) {
|
||||
switch ((c = p[i])) {
|
||||
case '&':
|
||||
q[0] = '&';
|
||||
q[1] = 'a';
|
||||
q[2] = 'm';
|
||||
q[3] = 'p';
|
||||
q[4] = ';';
|
||||
q += 5;
|
||||
break;
|
||||
case '<':
|
||||
q[0] = '&';
|
||||
q[1] = 'l';
|
||||
q[2] = 't';
|
||||
q[3] = ';';
|
||||
q += 4;
|
||||
break;
|
||||
case '>':
|
||||
q[0] = '&';
|
||||
q[1] = 'g';
|
||||
q[2] = 't';
|
||||
q[3] = ';';
|
||||
q += 4;
|
||||
break;
|
||||
case '"':
|
||||
q[0] = '&';
|
||||
q[1] = 'q';
|
||||
q[2] = 'u';
|
||||
q[3] = 'o';
|
||||
q[4] = 't';
|
||||
q[5] = ';';
|
||||
q += 6;
|
||||
break;
|
||||
case '\'':
|
||||
q[0] = '&';
|
||||
q[1] = '#';
|
||||
q[2] = '3';
|
||||
q[3] = '9';
|
||||
q[4] = ';';
|
||||
q += 5;
|
||||
break;
|
||||
default:
|
||||
*q++ = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (z) *z = q - r;
|
||||
*q++ = '\0';
|
||||
if ((q = realloc(r, q - r))) r = q;
|
||||
}
|
||||
r.size = p - r.data;
|
||||
r.data = xrealloc(r.data, r.size + 1);
|
||||
r.data[r.size] = '\0';
|
||||
return r;
|
||||
}
|
||||
|
|
|
@ -23,8 +23,11 @@
|
|||
*
|
||||
* This is the same as EscapeHost except colon is permitted.
|
||||
*
|
||||
* @param size if -1 implies strlen
|
||||
* @param p is input value
|
||||
* @param n if -1 implies strlen
|
||||
* @param z if non-NULL receives output length
|
||||
* @return allocated NUL-terminated buffer, or NULL w/ errno
|
||||
*/
|
||||
struct EscapeResult EscapeIp(const char *data, size_t size) {
|
||||
return EscapeUrl(data, size, kEscapeAuthority);
|
||||
char *EscapeIp(const char *p, size_t n, size_t *z) {
|
||||
return EscapeUrl(p, n, z, kEscapeAuthority);
|
||||
}
|
||||
|
|
|
@ -31,186 +31,192 @@
|
|||
* can't be encoded will use invalid codepoint markers. This function is
|
||||
* agnostic to numbers that have been used with malicious intent in the
|
||||
* past under buggy software. Noncanonical encodings such as overlong
|
||||
* NUL are canonicalized as NUL.
|
||||
* NUL are canonicalized as NUL. Therefore it isn't necessary to say
|
||||
* EscapeJsStringLiteral(Underlong(𝑥)) since EscapeJsStringLiteral(𝑥)
|
||||
* will do the same thing.
|
||||
*
|
||||
* @param p is input value
|
||||
* @param n if -1 implies strlen
|
||||
* @param out_size if non-NULL receives output length
|
||||
* @return allocated NUL-terminated buffer, or NULL w/ errno
|
||||
*/
|
||||
struct EscapeResult EscapeJsStringLiteral(const char *data, size_t size) {
|
||||
char *p;
|
||||
char *EscapeJsStringLiteral(const char *p, size_t n, size_t *z) {
|
||||
uint64_t w;
|
||||
unsigned i, n;
|
||||
char *q, *r;
|
||||
size_t i, j, m;
|
||||
wint_t x, a, b;
|
||||
const char *d, *e;
|
||||
struct EscapeResult r;
|
||||
d = data;
|
||||
e = data + size;
|
||||
p = r.data = xmalloc(size * 6 + 6 + 1);
|
||||
while (d < e) {
|
||||
x = *d++ & 0xff;
|
||||
if (x >= 0300) {
|
||||
a = ThomPikeByte(x);
|
||||
n = ThomPikeLen(x) - 1;
|
||||
if (d + n <= e) {
|
||||
for (i = 0;;) {
|
||||
b = d[i] & 0xff;
|
||||
if (!ThomPikeCont(b)) break;
|
||||
a = ThomPikeMerge(a, b);
|
||||
if (++i == n) {
|
||||
x = a;
|
||||
d += i;
|
||||
break;
|
||||
if (z) *z = 0;
|
||||
if (n == -1) n = p ? strlen(p) : 0;
|
||||
if ((q = r = malloc(n * 6 + 6 + 1))) {
|
||||
for (i = 0; i < n;) {
|
||||
x = p[i++] & 0xff;
|
||||
if (x >= 0300) {
|
||||
a = ThomPikeByte(x);
|
||||
m = ThomPikeLen(x) - 1;
|
||||
if (i + m <= n) {
|
||||
for (j = 0;;) {
|
||||
b = p[i + j] & 0xff;
|
||||
if (!ThomPikeCont(b)) break;
|
||||
a = ThomPikeMerge(a, b);
|
||||
if (++j == m) {
|
||||
x = a;
|
||||
i += j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
switch (x) {
|
||||
case ' ':
|
||||
case '!':
|
||||
case '#':
|
||||
case '$':
|
||||
case '%':
|
||||
case '(':
|
||||
case ')':
|
||||
case '*':
|
||||
case '+':
|
||||
case ',':
|
||||
case '-':
|
||||
case '.':
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
case ':':
|
||||
case ';':
|
||||
case '?':
|
||||
case '@':
|
||||
case 'A':
|
||||
case 'B':
|
||||
case 'C':
|
||||
case 'D':
|
||||
case 'E':
|
||||
case 'F':
|
||||
case 'G':
|
||||
case 'H':
|
||||
case 'I':
|
||||
case 'J':
|
||||
case 'K':
|
||||
case 'L':
|
||||
case 'M':
|
||||
case 'N':
|
||||
case 'O':
|
||||
case 'P':
|
||||
case 'Q':
|
||||
case 'R':
|
||||
case 'S':
|
||||
case 'T':
|
||||
case 'U':
|
||||
case 'V':
|
||||
case 'W':
|
||||
case 'X':
|
||||
case 'Y':
|
||||
case 'Z':
|
||||
case '[':
|
||||
case ']':
|
||||
case '^':
|
||||
case '_':
|
||||
case '`':
|
||||
case 'a':
|
||||
case 'b':
|
||||
case 'c':
|
||||
case 'd':
|
||||
case 'e':
|
||||
case 'f':
|
||||
case 'g':
|
||||
case 'h':
|
||||
case 'i':
|
||||
case 'j':
|
||||
case 'k':
|
||||
case 'l':
|
||||
case 'm':
|
||||
case 'n':
|
||||
case 'o':
|
||||
case 'p':
|
||||
case 'q':
|
||||
case 'r':
|
||||
case 's':
|
||||
case 't':
|
||||
case 'u':
|
||||
case 'v':
|
||||
case 'w':
|
||||
case 'x':
|
||||
case 'y':
|
||||
case 'z':
|
||||
case '{':
|
||||
case '|':
|
||||
case '}':
|
||||
case '~':
|
||||
*q++ = x;
|
||||
break;
|
||||
case '\t':
|
||||
q[0] = '\\';
|
||||
q[1] = 't';
|
||||
q += 2;
|
||||
break;
|
||||
case '\n':
|
||||
q[0] = '\\';
|
||||
q[1] = 'n';
|
||||
q += 2;
|
||||
break;
|
||||
case '\r':
|
||||
q[0] = '\\';
|
||||
q[1] = 'r';
|
||||
q += 2;
|
||||
break;
|
||||
case '\f':
|
||||
q[0] = '\\';
|
||||
q[1] = 'f';
|
||||
q += 2;
|
||||
break;
|
||||
case '\\':
|
||||
q[0] = '\\';
|
||||
q[1] = '\\';
|
||||
q += 2;
|
||||
break;
|
||||
case '/':
|
||||
q[0] = '\\';
|
||||
q[1] = '/';
|
||||
q += 2;
|
||||
break;
|
||||
case '"':
|
||||
q[0] = '\\';
|
||||
q[1] = '"';
|
||||
q += 2;
|
||||
break;
|
||||
case '\'':
|
||||
q[0] = '\\';
|
||||
q[1] = '\'';
|
||||
q += 2;
|
||||
break;
|
||||
case '<':
|
||||
case '>':
|
||||
case '&':
|
||||
case '=':
|
||||
default:
|
||||
w = EncodeUtf16(x);
|
||||
do {
|
||||
q[0] = '\\';
|
||||
q[1] = 'u';
|
||||
q[2] = "0123456789abcdef"[(w & 0xF000) >> 014];
|
||||
q[3] = "0123456789abcdef"[(w & 0x0F00) >> 010];
|
||||
q[4] = "0123456789abcdef"[(w & 0x00F0) >> 004];
|
||||
q[5] = "0123456789abcdef"[(w & 0x000F) >> 000];
|
||||
q += 6;
|
||||
} while ((w >>= 16));
|
||||
break;
|
||||
}
|
||||
}
|
||||
switch (x) {
|
||||
case ' ':
|
||||
case '!':
|
||||
case '#':
|
||||
case '$':
|
||||
case '%':
|
||||
case '(':
|
||||
case ')':
|
||||
case '*':
|
||||
case '+':
|
||||
case ',':
|
||||
case '-':
|
||||
case '.':
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
case ':':
|
||||
case ';':
|
||||
case '?':
|
||||
case '@':
|
||||
case 'A':
|
||||
case 'B':
|
||||
case 'C':
|
||||
case 'D':
|
||||
case 'E':
|
||||
case 'F':
|
||||
case 'G':
|
||||
case 'H':
|
||||
case 'I':
|
||||
case 'J':
|
||||
case 'K':
|
||||
case 'L':
|
||||
case 'M':
|
||||
case 'N':
|
||||
case 'O':
|
||||
case 'P':
|
||||
case 'Q':
|
||||
case 'R':
|
||||
case 'S':
|
||||
case 'T':
|
||||
case 'U':
|
||||
case 'V':
|
||||
case 'W':
|
||||
case 'X':
|
||||
case 'Y':
|
||||
case 'Z':
|
||||
case '[':
|
||||
case ']':
|
||||
case '^':
|
||||
case '_':
|
||||
case '`':
|
||||
case 'a':
|
||||
case 'b':
|
||||
case 'c':
|
||||
case 'd':
|
||||
case 'e':
|
||||
case 'f':
|
||||
case 'g':
|
||||
case 'h':
|
||||
case 'i':
|
||||
case 'j':
|
||||
case 'k':
|
||||
case 'l':
|
||||
case 'm':
|
||||
case 'n':
|
||||
case 'o':
|
||||
case 'p':
|
||||
case 'q':
|
||||
case 'r':
|
||||
case 's':
|
||||
case 't':
|
||||
case 'u':
|
||||
case 'v':
|
||||
case 'w':
|
||||
case 'x':
|
||||
case 'y':
|
||||
case 'z':
|
||||
case '{':
|
||||
case '|':
|
||||
case '}':
|
||||
case '~':
|
||||
*p++ = x;
|
||||
break;
|
||||
case '\t':
|
||||
p[0] = '\\';
|
||||
p[1] = 't';
|
||||
p += 2;
|
||||
break;
|
||||
case '\n':
|
||||
p[0] = '\\';
|
||||
p[1] = 'n';
|
||||
p += 2;
|
||||
break;
|
||||
case '\r':
|
||||
p[0] = '\\';
|
||||
p[1] = 'r';
|
||||
p += 2;
|
||||
break;
|
||||
case '\f':
|
||||
p[0] = '\\';
|
||||
p[1] = 'f';
|
||||
p += 2;
|
||||
break;
|
||||
case '\\':
|
||||
p[0] = '\\';
|
||||
p[1] = '\\';
|
||||
p += 2;
|
||||
break;
|
||||
case '/':
|
||||
p[0] = '\\';
|
||||
p[1] = '/';
|
||||
p += 2;
|
||||
break;
|
||||
case '"':
|
||||
p[0] = '\\';
|
||||
p[1] = '"';
|
||||
p += 2;
|
||||
break;
|
||||
case '\'':
|
||||
p[0] = '\\';
|
||||
p[1] = '\'';
|
||||
p += 2;
|
||||
break;
|
||||
case '<':
|
||||
case '>':
|
||||
case '&':
|
||||
case '=':
|
||||
default:
|
||||
w = EncodeUtf16(x);
|
||||
do {
|
||||
p[0] = '\\';
|
||||
p[1] = 'u';
|
||||
p[2] = "0123456789abcdef"[(w & 0xF000) >> 014];
|
||||
p[3] = "0123456789abcdef"[(w & 0x0F00) >> 010];
|
||||
p[4] = "0123456789abcdef"[(w & 0x00F0) >> 004];
|
||||
p[5] = "0123456789abcdef"[(w & 0x000F) >> 000];
|
||||
p += 6;
|
||||
} while ((w >>= 16));
|
||||
break;
|
||||
}
|
||||
if (z) *z = q - r;
|
||||
*q++ = '\0';
|
||||
if ((q = realloc(r, q - r))) r = q;
|
||||
}
|
||||
r.size = p - r.data;
|
||||
r.data = xrealloc(r.data, r.size + 1);
|
||||
r.data[r.size] = '\0';
|
||||
return r;
|
||||
}
|
||||
|
|
|
@ -21,8 +21,11 @@
|
|||
/**
|
||||
* Escapes query/form name/parameter.
|
||||
*
|
||||
* @param size if -1 implies strlen
|
||||
* @param p is input value
|
||||
* @param n if -1 implies strlen
|
||||
* @param z if non-NULL receives output length
|
||||
* @return allocated NUL-terminated buffer, or NULL w/ errno
|
||||
*/
|
||||
struct EscapeResult EscapeParam(const char *data, size_t size) {
|
||||
return EscapeUrl(data, size, kEscapeParam);
|
||||
char *EscapeParam(const char *p, size_t n, size_t *z) {
|
||||
return EscapeUrl(p, n, z, kEscapeParam);
|
||||
}
|
||||
|
|
|
@ -21,8 +21,11 @@
|
|||
/**
|
||||
* Escapes URL password.
|
||||
*
|
||||
* @param size if -1 implies strlen
|
||||
* @param p is input value
|
||||
* @param n if -1 implies strlen
|
||||
* @param z if non-NULL receives output length
|
||||
* @return allocated NUL-terminated buffer, or NULL w/ errno
|
||||
*/
|
||||
struct EscapeResult EscapePass(const char *data, size_t size) {
|
||||
return EscapeUrl(data, size, kEscapeAuthority);
|
||||
char *EscapePass(const char *p, size_t n, size_t *z) {
|
||||
return EscapeUrl(p, n, z, kEscapeAuthority);
|
||||
}
|
||||
|
|
|
@ -23,8 +23,11 @@
|
|||
*
|
||||
* This is the same as EscapePathSegment() except slash is allowed.
|
||||
*
|
||||
* @param size if -1 implies strlen
|
||||
* @param p is input value
|
||||
* @param n if -1 implies strlen
|
||||
* @param z if non-NULL receives output length
|
||||
* @return allocated NUL-terminated buffer, or NULL w/ errno
|
||||
*/
|
||||
struct EscapeResult EscapePath(const char *data, size_t size) {
|
||||
return EscapeUrl(data, size, kEscapePath);
|
||||
char *EscapePath(const char *p, size_t n, size_t *z) {
|
||||
return EscapeUrl(p, n, z, kEscapePath);
|
||||
}
|
||||
|
|
|
@ -24,8 +24,11 @@
|
|||
* Please note this will URI encode the slash character. That's because
|
||||
* segments are the labels between the slashes in a path.
|
||||
*
|
||||
* @param size if -1 implies strlen
|
||||
* @param p is input value
|
||||
* @param n if -1 implies strlen
|
||||
* @param z if non-NULL receives output length
|
||||
* @return allocated NUL-terminated buffer, or NULL w/ errno
|
||||
*/
|
||||
struct EscapeResult EscapeSegment(const char *data, size_t size) {
|
||||
return EscapeUrl(data, size, kEscapeSegment);
|
||||
char *EscapeSegment(const char *p, size_t n, size_t *z) {
|
||||
return EscapeUrl(p, n, z, kEscapeSegment);
|
||||
}
|
||||
|
|
|
@ -26,7 +26,10 @@
|
|||
* This function is agnostic to the underlying charset.
|
||||
* Always using UTF-8 is a good idea.
|
||||
*
|
||||
* @param size if -1 implies strlen
|
||||
* @param p is input value
|
||||
* @param n if -1 implies strlen
|
||||
* @param z if non-NULL receives output length
|
||||
* @return allocated NUL-terminated buffer, or NULL w/ errno
|
||||
* @see kEscapeAuthority
|
||||
* @see kEscapeIpLiteral
|
||||
* @see kEscapePath
|
||||
|
@ -34,16 +37,17 @@
|
|||
* @see kEscapeParam
|
||||
* @see kEscapeFragment
|
||||
*/
|
||||
struct EscapeResult EscapeUrl(const char *data, size_t size,
|
||||
const char xlat[hasatleast 256]) {
|
||||
char *EscapeUrl(const char *p, size_t n, size_t *z, const char T[256]) {
|
||||
char *r, *q;
|
||||
struct UrlView v;
|
||||
struct EscapeResult r;
|
||||
if (size == -1) size = data ? strlen(data) : 0;
|
||||
v.p = data;
|
||||
v.n = size;
|
||||
r.data = xmalloc(size * 6 + 1);
|
||||
r.size = EscapeUrlView(r.data, &v, xlat) - r.data;
|
||||
r.data = xrealloc(r.data, r.size + 1);
|
||||
r.data[r.size] = '\0';
|
||||
if (n == -1) n = p ? strlen(p) : 0;
|
||||
if (z) *z = 0;
|
||||
if ((q = r = malloc(n * 6 + 1))) {
|
||||
v.p = p, v.n = n;
|
||||
q = EscapeUrlView(r, &v, T);
|
||||
if (z) *z = q - r;
|
||||
*q++ = '\0';
|
||||
if ((q = realloc(r, q - r))) r = q;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
|
|
@ -21,8 +21,11 @@
|
|||
/**
|
||||
* Escapes URL user name.
|
||||
*
|
||||
* @param size if -1 implies strlen
|
||||
* @param p is input value
|
||||
* @param n if -1 implies strlen
|
||||
* @param z if non-NULL receives output length
|
||||
* @return allocated NUL-terminated buffer, or NULL w/ errno
|
||||
*/
|
||||
struct EscapeResult EscapeUser(const char *data, size_t size) {
|
||||
return EscapeUrl(data, size, kEscapeAuthority);
|
||||
char *EscapeUser(const char *p, size_t n, size_t *z) {
|
||||
return EscapeUrl(p, n, z, kEscapeAuthority);
|
||||
}
|
||||
|
|
|
@ -9,63 +9,70 @@
|
|||
%readonly-tables
|
||||
%struct-type
|
||||
%define lookup-function-name LookupHttpHeader
|
||||
struct HttpHeaderSlot { char *name; char code; };
|
||||
struct thatispacked HttpHeaderSlot { char *name; char code; };
|
||||
%%
|
||||
Accept, kHttpAccept
|
||||
Accept-Charset, kHttpAcceptCharset
|
||||
Accept-Encoding, kHttpAcceptEncoding
|
||||
Accept-Language, kHttpAcceptLanguage
|
||||
Age, kHttpAge
|
||||
Allow, kHttpAllow
|
||||
Authorization, kHttpAuthorization
|
||||
Cache-Control, kHttpCacheControl
|
||||
Chunked, kHttpChunked
|
||||
Link, kHttpLink
|
||||
Connection, kHttpConnection
|
||||
Content-Base, kHttpContentBase
|
||||
Content-Encoding, kHttpContentEncoding
|
||||
Content-Language, kHttpContentLanguage
|
||||
Content-Length, kHttpContentLength
|
||||
Content-Location, kHttpContentLocation
|
||||
Content-MD5, kHttpContentMd5
|
||||
Content-Range, kHttpContentRange
|
||||
Content-Type, kHttpContentType
|
||||
Date, kHttpDate
|
||||
ETag, kHttpEtag
|
||||
Expires, kHttpExpires
|
||||
From, kHttpFrom
|
||||
Host, kHttpHost
|
||||
If-Match, kHttpIfMatch
|
||||
If-Modified-Since, kHttpIfModifiedSince
|
||||
If-None-Match, kHttpIfNoneMatch
|
||||
If-Range, kHttpIfRange
|
||||
If-Unmodified-Since, kHttpIfUnmodifiedSince
|
||||
Keep-Alive, kHttpKeepAlive
|
||||
Max-Forwards, kHttpMaxForwards
|
||||
Pragma, kHttpPragma
|
||||
Proxy-Authenticate, kHttpProxyAuthenticate
|
||||
Proxy-Authorization, kHttpProxyAuthorization
|
||||
Proxy-Connection, kHttpProxyConnection
|
||||
Range, kHttpRange
|
||||
Referer, kHttpReferer
|
||||
Transfer-Encoding, kHttpTransferEncoding
|
||||
Upgrade, kHttpUpgrade
|
||||
User-Agent, kHttpUserAgent
|
||||
Via, kHttpVia
|
||||
Location, kHttpLocation
|
||||
Public, kHttpPublic
|
||||
Retry-After, kHttpRetryAfter
|
||||
Server, kHttpServer
|
||||
Vary, kHttpVary
|
||||
Warning, kHttpWarning
|
||||
WWW-Authenticate, kHttpWwwAuthenticate
|
||||
Last-Modified, kHttpLastModified
|
||||
Trailer, kHttpTrailer
|
||||
TE, kHttpTe
|
||||
DNT, kHttpDnt
|
||||
Expect, kHttpExpect
|
||||
Content-Disposition, kHttpContentDisposition
|
||||
Content-Description, kHttpContentDescription
|
||||
Origin, kHttpOrigin
|
||||
Upgrade-Insecure-Requests, kHttpUpgradeInsecureRequests
|
||||
URI, kHttpUri
|
||||
Accept, kHttpAccept
|
||||
Accept-Charset, kHttpAcceptCharset
|
||||
Accept-Encoding, kHttpAcceptEncoding
|
||||
Accept-Language, kHttpAcceptLanguage
|
||||
Age, kHttpAge
|
||||
Allow, kHttpAllow
|
||||
Authorization, kHttpAuthorization
|
||||
Cache-Control, kHttpCacheControl
|
||||
Chunked, kHttpChunked
|
||||
Link, kHttpLink
|
||||
Connection, kHttpConnection
|
||||
Content-Base, kHttpContentBase
|
||||
Content-Encoding, kHttpContentEncoding
|
||||
Content-Language, kHttpContentLanguage
|
||||
Content-Length, kHttpContentLength
|
||||
Content-Location, kHttpContentLocation
|
||||
Content-MD5, kHttpContentMd5
|
||||
Content-Range, kHttpContentRange
|
||||
Content-Type, kHttpContentType
|
||||
Date, kHttpDate
|
||||
ETag, kHttpEtag
|
||||
Expires, kHttpExpires
|
||||
From, kHttpFrom
|
||||
Host, kHttpHost
|
||||
If-Match, kHttpIfMatch
|
||||
If-Modified-Since, kHttpIfModifiedSince
|
||||
If-None-Match, kHttpIfNoneMatch
|
||||
If-Range, kHttpIfRange
|
||||
If-Unmodified-Since, kHttpIfUnmodifiedSince
|
||||
Keep-Alive, kHttpKeepAlive
|
||||
Max-Forwards, kHttpMaxForwards
|
||||
Pragma, kHttpPragma
|
||||
Proxy-Authenticate, kHttpProxyAuthenticate
|
||||
Proxy-Authorization, kHttpProxyAuthorization
|
||||
Proxy-Connection, kHttpProxyConnection
|
||||
Range, kHttpRange
|
||||
Referer, kHttpReferer
|
||||
Transfer-Encoding, kHttpTransferEncoding
|
||||
Upgrade, kHttpUpgrade
|
||||
User-Agent, kHttpUserAgent
|
||||
Via, kHttpVia
|
||||
Location, kHttpLocation
|
||||
Public, kHttpPublic
|
||||
Retry-After, kHttpRetryAfter
|
||||
Server, kHttpServer
|
||||
Vary, kHttpVary
|
||||
Warning, kHttpWarning
|
||||
WWW-Authenticate, kHttpWwwAuthenticate
|
||||
Last-Modified, kHttpLastModified
|
||||
Trailer, kHttpTrailer
|
||||
TE, kHttpTe
|
||||
DNT, kHttpDnt
|
||||
Expect, kHttpExpect
|
||||
Content-Disposition, kHttpContentDisposition
|
||||
Content-Description, kHttpContentDescription
|
||||
Origin, kHttpOrigin
|
||||
Upgrade-Insecure-Requests, kHttpUpgradeInsecureRequests
|
||||
URI, kHttpUri
|
||||
X-Csrf-Token, kHttpXCsrfToken
|
||||
X-Forwarded-For, kHttpXForwardedFor
|
||||
X-Forwarded-Host, kHttpXForwardedHost
|
||||
X-Forwarded-Proto, kHttpXForwardedProto
|
||||
X-Requested-With, kHttpXRequestedWith
|
||||
Access-Control-Request-Method, kHttpAccessControlRequestMethod
|
||||
Access-Control-Request-Headers, kHttpAccessControlRequestHeaders
|
||||
|
|
|
@ -35,14 +35,14 @@
|
|||
#include "net/http/http.h"
|
||||
#define GPERF_DOWNCASE
|
||||
#line 12 "gethttpheader.gperf"
|
||||
struct HttpHeaderSlot { char *name; char code; };
|
||||
struct thatispacked HttpHeaderSlot { char *name; char code; };
|
||||
|
||||
#define TOTAL_KEYWORDS 58
|
||||
#define TOTAL_KEYWORDS 65
|
||||
#define MIN_WORD_LENGTH 2
|
||||
#define MAX_WORD_LENGTH 25
|
||||
#define MAX_WORD_LENGTH 30
|
||||
#define MIN_HASH_VALUE 2
|
||||
#define MAX_HASH_VALUE 97
|
||||
/* maximum key range = 96, duplicates = 0 */
|
||||
#define MAX_HASH_VALUE 102
|
||||
/* maximum key range = 101, duplicates = 0 */
|
||||
|
||||
#ifndef GPERF_DOWNCASE
|
||||
#define GPERF_DOWNCASE 1
|
||||
|
@ -101,32 +101,32 @@ hash (register const char *str, register size_t len)
|
|||
{
|
||||
static const unsigned char asso_values[] =
|
||||
{
|
||||
98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
|
||||
98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
|
||||
98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
|
||||
98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
|
||||
98, 98, 98, 98, 98, 30, 98, 98, 98, 98,
|
||||
98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
|
||||
98, 98, 98, 98, 98, 5, 0, 30, 55, 0,
|
||||
0, 10, 5, 30, 98, 0, 0, 15, 0, 15,
|
||||
51, 98, 30, 55, 10, 5, 35, 20, 25, 10,
|
||||
98, 98, 98, 98, 98, 98, 98, 5, 0, 30,
|
||||
55, 0, 0, 10, 5, 30, 98, 0, 0, 15,
|
||||
0, 15, 51, 98, 30, 55, 10, 5, 35, 20,
|
||||
25, 10, 98, 98, 98, 98, 98, 98, 98, 98,
|
||||
98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
|
||||
98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
|
||||
98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
|
||||
98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
|
||||
98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
|
||||
98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
|
||||
98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
|
||||
98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
|
||||
98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
|
||||
98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
|
||||
98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
|
||||
98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
|
||||
98, 98, 98, 98, 98, 98
|
||||
103, 103, 103, 103, 103, 103, 103, 103, 103, 103,
|
||||
103, 103, 103, 103, 103, 103, 103, 103, 103, 103,
|
||||
103, 103, 103, 103, 103, 103, 103, 103, 103, 103,
|
||||
103, 103, 103, 103, 103, 103, 103, 103, 103, 103,
|
||||
103, 103, 103, 103, 103, 30, 103, 103, 103, 103,
|
||||
103, 103, 103, 103, 103, 103, 103, 103, 103, 103,
|
||||
103, 103, 103, 103, 103, 10, 0, 10, 0, 5,
|
||||
0, 15, 25, 30, 103, 0, 0, 5, 0, 45,
|
||||
65, 103, 20, 55, 0, 30, 15, 10, 10, 40,
|
||||
103, 103, 103, 103, 103, 103, 103, 10, 0, 10,
|
||||
0, 5, 0, 15, 25, 30, 103, 0, 0, 5,
|
||||
0, 45, 65, 103, 20, 55, 0, 30, 15, 10,
|
||||
10, 40, 103, 103, 103, 103, 103, 103, 103, 103,
|
||||
103, 103, 103, 103, 103, 103, 103, 103, 103, 103,
|
||||
103, 103, 103, 103, 103, 103, 103, 103, 103, 103,
|
||||
103, 103, 103, 103, 103, 103, 103, 103, 103, 103,
|
||||
103, 103, 103, 103, 103, 103, 103, 103, 103, 103,
|
||||
103, 103, 103, 103, 103, 103, 103, 103, 103, 103,
|
||||
103, 103, 103, 103, 103, 103, 103, 103, 103, 103,
|
||||
103, 103, 103, 103, 103, 103, 103, 103, 103, 103,
|
||||
103, 103, 103, 103, 103, 103, 103, 103, 103, 103,
|
||||
103, 103, 103, 103, 103, 103, 103, 103, 103, 103,
|
||||
103, 103, 103, 103, 103, 103, 103, 103, 103, 103,
|
||||
103, 103, 103, 103, 103, 103, 103, 103, 103, 103,
|
||||
103, 103, 103, 103, 103, 103, 103, 103, 103, 103,
|
||||
103, 103, 103, 103, 103, 103
|
||||
};
|
||||
register unsigned int hval = len;
|
||||
|
||||
|
@ -152,146 +152,157 @@ hash (register const char *str, register size_t len)
|
|||
return hval;
|
||||
}
|
||||
|
||||
const struct HttpHeaderSlot *
|
||||
const struct thatispacked HttpHeaderSlot *
|
||||
LookupHttpHeader (register const char *str, register size_t len)
|
||||
{
|
||||
static const struct HttpHeaderSlot wordlist[] =
|
||||
static const struct thatispacked HttpHeaderSlot wordlist[] =
|
||||
{
|
||||
{""}, {""},
|
||||
#line 64 "gethttpheader.gperf"
|
||||
{"TE", kHttpTe},
|
||||
#line 18 "gethttpheader.gperf"
|
||||
{"Age", kHttpAge},
|
||||
{"TE", kHttpTe},
|
||||
#line 65 "gethttpheader.gperf"
|
||||
{"DNT", kHttpDnt},
|
||||
#line 23 "gethttpheader.gperf"
|
||||
{"Link", kHttpLink},
|
||||
{"Link", kHttpLink},
|
||||
{""},
|
||||
#line 56 "gethttpheader.gperf"
|
||||
{"Public", kHttpPublic},
|
||||
#line 50 "gethttpheader.gperf"
|
||||
{"Referer", kHttpReferer},
|
||||
#line 54 "gethttpheader.gperf"
|
||||
{"Via", kHttpVia},
|
||||
{"Public", kHttpPublic},
|
||||
{""},
|
||||
#line 24 "gethttpheader.gperf"
|
||||
{"Connection", kHttpConnection},
|
||||
{""},
|
||||
#line 22 "gethttpheader.gperf"
|
||||
{"Chunked", kHttpChunked},
|
||||
#line 65 "gethttpheader.gperf"
|
||||
{"DNT", kHttpDnt},
|
||||
#line 18 "gethttpheader.gperf"
|
||||
{"Age", kHttpAge},
|
||||
#line 33 "gethttpheader.gperf"
|
||||
{"Date", kHttpDate},
|
||||
#line 49 "gethttpheader.gperf"
|
||||
{"Range", kHttpRange},
|
||||
{""}, {""}, {""},
|
||||
#line 34 "gethttpheader.gperf"
|
||||
{"ETag", kHttpEtag},
|
||||
#line 19 "gethttpheader.gperf"
|
||||
{"Allow", kHttpAllow},
|
||||
#line 45 "gethttpheader.gperf"
|
||||
{"Pragma", kHttpPragma},
|
||||
#line 51 "gethttpheader.gperf"
|
||||
{"Transfer-Encoding", kHttpTransferEncoding},
|
||||
{""},
|
||||
#line 28 "gethttpheader.gperf"
|
||||
{"Content-Length", kHttpContentLength},
|
||||
{""},
|
||||
{"Date", kHttpDate},
|
||||
#line 24 "gethttpheader.gperf"
|
||||
{"Connection", kHttpConnection},
|
||||
#line 30 "gethttpheader.gperf"
|
||||
{"Content-MD5", kHttpContentMd5},
|
||||
#line 50 "gethttpheader.gperf"
|
||||
{"Referer", kHttpReferer},
|
||||
#line 54 "gethttpheader.gperf"
|
||||
{"Via", kHttpVia},
|
||||
{""}, {""},
|
||||
#line 26 "gethttpheader.gperf"
|
||||
{"Content-Encoding", kHttpContentEncoding},
|
||||
{"Content-Encoding", kHttpContentEncoding},
|
||||
{""}, {""},
|
||||
#line 28 "gethttpheader.gperf"
|
||||
{"Content-Length", kHttpContentLength},
|
||||
#line 49 "gethttpheader.gperf"
|
||||
{"Range", kHttpRange},
|
||||
#line 14 "gethttpheader.gperf"
|
||||
{"Accept", kHttpAccept},
|
||||
#line 25 "gethttpheader.gperf"
|
||||
{"Content-Base", kHttpContentBase},
|
||||
{"Content-Base", kHttpContentBase},
|
||||
#line 31 "gethttpheader.gperf"
|
||||
{"Content-Range", kHttpContentRange},
|
||||
{"Content-Range", kHttpContentRange},
|
||||
#line 68 "gethttpheader.gperf"
|
||||
{"Content-Description", kHttpContentDescription},
|
||||
{"Content-Description", kHttpContentDescription},
|
||||
{""},
|
||||
#line 27 "gethttpheader.gperf"
|
||||
{"Content-Language", kHttpContentLanguage},
|
||||
#line 32 "gethttpheader.gperf"
|
||||
{"Content-Type", kHttpContentType},
|
||||
#line 71 "gethttpheader.gperf"
|
||||
{"URI", kHttpUri},
|
||||
#line 36 "gethttpheader.gperf"
|
||||
{"From", kHttpFrom},
|
||||
{""},
|
||||
#line 14 "gethttpheader.gperf"
|
||||
{"Accept", kHttpAccept},
|
||||
{"Content-Language", kHttpContentLanguage},
|
||||
#line 60 "gethttpheader.gperf"
|
||||
{"Warning", kHttpWarning},
|
||||
#line 20 "gethttpheader.gperf"
|
||||
{"Authorization", kHttpAuthorization},
|
||||
{""}, {""},
|
||||
#line 29 "gethttpheader.gperf"
|
||||
{"Content-Location", kHttpContentLocation},
|
||||
#line 63 "gethttpheader.gperf"
|
||||
{"Trailer", kHttpTrailer},
|
||||
{"Warning", kHttpWarning},
|
||||
#line 55 "gethttpheader.gperf"
|
||||
{"Location", kHttpLocation},
|
||||
#line 59 "gethttpheader.gperf"
|
||||
{"Vary", kHttpVary},
|
||||
{"Location", kHttpLocation},
|
||||
#line 34 "gethttpheader.gperf"
|
||||
{"ETag", kHttpEtag},
|
||||
#line 17 "gethttpheader.gperf"
|
||||
{"Accept-Language", kHttpAcceptLanguage},
|
||||
#line 69 "gethttpheader.gperf"
|
||||
{"Origin", kHttpOrigin},
|
||||
#line 52 "gethttpheader.gperf"
|
||||
{"Upgrade", kHttpUpgrade},
|
||||
#line 40 "gethttpheader.gperf"
|
||||
{"If-None-Match", kHttpIfNoneMatch},
|
||||
#line 15 "gethttpheader.gperf"
|
||||
{"Accept-Charset", kHttpAcceptCharset},
|
||||
{"Accept-Language", kHttpAcceptLanguage},
|
||||
#line 45 "gethttpheader.gperf"
|
||||
{"Pragma", kHttpPragma},
|
||||
#line 51 "gethttpheader.gperf"
|
||||
{"Transfer-Encoding", kHttpTransferEncoding},
|
||||
#line 71 "gethttpheader.gperf"
|
||||
{"URI", kHttpUri},
|
||||
{""},
|
||||
#line 53 "gethttpheader.gperf"
|
||||
{"User-Agent", kHttpUserAgent},
|
||||
{"User-Agent", kHttpUserAgent},
|
||||
#line 57 "gethttpheader.gperf"
|
||||
{"Retry-After", kHttpRetryAfter},
|
||||
{""},
|
||||
#line 38 "gethttpheader.gperf"
|
||||
{"If-Match", kHttpIfMatch},
|
||||
#line 42 "gethttpheader.gperf"
|
||||
{"If-Unmodified-Since", kHttpIfUnmodifiedSince},
|
||||
{""},
|
||||
#line 48 "gethttpheader.gperf"
|
||||
{"Proxy-Connection", kHttpProxyConnection},
|
||||
#line 66 "gethttpheader.gperf"
|
||||
{"Expect", kHttpExpect},
|
||||
#line 21 "gethttpheader.gperf"
|
||||
{"Cache-Control", kHttpCacheControl},
|
||||
#line 67 "gethttpheader.gperf"
|
||||
{"Content-Disposition", kHttpContentDisposition},
|
||||
{""},
|
||||
#line 43 "gethttpheader.gperf"
|
||||
{"Keep-Alive", kHttpKeepAlive},
|
||||
#line 39 "gethttpheader.gperf"
|
||||
{"If-Modified-Since", kHttpIfModifiedSince},
|
||||
#line 46 "gethttpheader.gperf"
|
||||
{"Proxy-Authenticate", kHttpProxyAuthenticate},
|
||||
#line 47 "gethttpheader.gperf"
|
||||
{"Proxy-Authorization", kHttpProxyAuthorization},
|
||||
#line 70 "gethttpheader.gperf"
|
||||
{"Upgrade-Insecure-Requests", kHttpUpgradeInsecureRequests},
|
||||
#line 61 "gethttpheader.gperf"
|
||||
{"WWW-Authenticate", kHttpWwwAuthenticate},
|
||||
{""},
|
||||
#line 41 "gethttpheader.gperf"
|
||||
{"If-Range", kHttpIfRange},
|
||||
#line 37 "gethttpheader.gperf"
|
||||
{"Host", kHttpHost},
|
||||
{""},
|
||||
#line 58 "gethttpheader.gperf"
|
||||
{"Server", kHttpServer},
|
||||
{""}, {""}, {""},
|
||||
{"Retry-After", kHttpRetryAfter},
|
||||
#line 22 "gethttpheader.gperf"
|
||||
{"Chunked", kHttpChunked},
|
||||
#line 20 "gethttpheader.gperf"
|
||||
{"Authorization", kHttpAuthorization},
|
||||
#line 15 "gethttpheader.gperf"
|
||||
{"Accept-Charset", kHttpAcceptCharset},
|
||||
#line 16 "gethttpheader.gperf"
|
||||
{"Accept-Encoding", kHttpAcceptEncoding},
|
||||
#line 30 "gethttpheader.gperf"
|
||||
{"Content-MD5", kHttpContentMd5},
|
||||
{"Accept-Encoding", kHttpAcceptEncoding},
|
||||
#line 58 "gethttpheader.gperf"
|
||||
{"Server", kHttpServer},
|
||||
#line 52 "gethttpheader.gperf"
|
||||
{"Upgrade", kHttpUpgrade},
|
||||
#line 38 "gethttpheader.gperf"
|
||||
{"If-Match", kHttpIfMatch},
|
||||
#line 77 "gethttpheader.gperf"
|
||||
{"Access-Control-Request-Method", kHttpAccessControlRequestMethod},
|
||||
#line 78 "gethttpheader.gperf"
|
||||
{"Access-Control-Request-Headers", kHttpAccessControlRequestHeaders},
|
||||
#line 76 "gethttpheader.gperf"
|
||||
{"X-Requested-With", kHttpXRequestedWith},
|
||||
#line 63 "gethttpheader.gperf"
|
||||
{"Trailer", kHttpTrailer},
|
||||
#line 21 "gethttpheader.gperf"
|
||||
{"Cache-Control", kHttpCacheControl},
|
||||
#line 67 "gethttpheader.gperf"
|
||||
{"Content-Disposition", kHttpContentDisposition},
|
||||
#line 19 "gethttpheader.gperf"
|
||||
{"Allow", kHttpAllow},
|
||||
#line 69 "gethttpheader.gperf"
|
||||
{"Origin", kHttpOrigin},
|
||||
#line 32 "gethttpheader.gperf"
|
||||
{"Content-Type", kHttpContentType},
|
||||
#line 40 "gethttpheader.gperf"
|
||||
{"If-None-Match", kHttpIfNoneMatch},
|
||||
#line 36 "gethttpheader.gperf"
|
||||
{"From", kHttpFrom},
|
||||
{""},
|
||||
#line 61 "gethttpheader.gperf"
|
||||
{"WWW-Authenticate", kHttpWwwAuthenticate},
|
||||
#line 39 "gethttpheader.gperf"
|
||||
{"If-Modified-Since", kHttpIfModifiedSince},
|
||||
#line 41 "gethttpheader.gperf"
|
||||
{"If-Range", kHttpIfRange},
|
||||
#line 37 "gethttpheader.gperf"
|
||||
{"Host", kHttpHost},
|
||||
#line 70 "gethttpheader.gperf"
|
||||
{"Upgrade-Insecure-Requests", kHttpUpgradeInsecureRequests},
|
||||
#line 29 "gethttpheader.gperf"
|
||||
{"Content-Location", kHttpContentLocation},
|
||||
{""}, {""},
|
||||
#line 59 "gethttpheader.gperf"
|
||||
{"Vary", kHttpVary},
|
||||
#line 73 "gethttpheader.gperf"
|
||||
{"X-Forwarded-For", kHttpXForwardedFor},
|
||||
#line 74 "gethttpheader.gperf"
|
||||
{"X-Forwarded-Host", kHttpXForwardedHost},
|
||||
#line 75 "gethttpheader.gperf"
|
||||
{"X-Forwarded-Proto", kHttpXForwardedProto},
|
||||
#line 62 "gethttpheader.gperf"
|
||||
{"Last-Modified", kHttpLastModified},
|
||||
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
|
||||
#line 35 "gethttpheader.gperf"
|
||||
{"Expires", kHttpExpires},
|
||||
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
|
||||
{"Last-Modified", kHttpLastModified},
|
||||
{""}, {""},
|
||||
#line 48 "gethttpheader.gperf"
|
||||
{"Proxy-Connection", kHttpProxyConnection},
|
||||
#line 44 "gethttpheader.gperf"
|
||||
{"Max-Forwards", kHttpMaxForwards}
|
||||
{"Max-Forwards", kHttpMaxForwards},
|
||||
{""}, {""}, {""},
|
||||
#line 66 "gethttpheader.gperf"
|
||||
{"Expect", kHttpExpect},
|
||||
#line 72 "gethttpheader.gperf"
|
||||
{"X-Csrf-Token", kHttpXCsrfToken},
|
||||
{""},
|
||||
#line 42 "gethttpheader.gperf"
|
||||
{"If-Unmodified-Since", kHttpIfUnmodifiedSince},
|
||||
{""}, {""}, {""}, {""}, {""},
|
||||
#line 43 "gethttpheader.gperf"
|
||||
{"Keep-Alive", kHttpKeepAlive},
|
||||
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
|
||||
{""}, {""}, {""},
|
||||
#line 46 "gethttpheader.gperf"
|
||||
{"Proxy-Authenticate", kHttpProxyAuthenticate},
|
||||
#line 47 "gethttpheader.gperf"
|
||||
{"Proxy-Authorization", kHttpProxyAuthorization},
|
||||
{""}, {""},
|
||||
#line 35 "gethttpheader.gperf"
|
||||
{"Expires", kHttpExpires}
|
||||
};
|
||||
|
||||
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
|
||||
|
|
|
@ -136,6 +136,20 @@ const char *GetHttpHeaderName(int h) {
|
|||
return "Upgrade-Insecure-Requests";
|
||||
case kHttpUri:
|
||||
return "URI";
|
||||
case kHttpXCsrfToken:
|
||||
return "X-Csrf-Token";
|
||||
case kHttpXForwardedFor:
|
||||
return "X-Forwarded-For";
|
||||
case kHttpXForwardedHost:
|
||||
return "X-Forwarded-Host";
|
||||
case kHttpXForwardedProto:
|
||||
return "X-Forwarded-Proto";
|
||||
case kHttpXRequestedWith:
|
||||
return "X-Requested-With";
|
||||
case kHttpAccessControlRequestMethod:
|
||||
return "Access-Control-Request-Method";
|
||||
case kHttpAccessControlRequestHeaders:
|
||||
return "Access-Control-Request-Headers";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
|
68
net/http/getipcategoryname.c
Normal file
68
net/http/getipcategoryname.c
Normal file
|
@ -0,0 +1,68 @@
|
|||
/*-*- 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 "net/http/ip.h"
|
||||
|
||||
/**
|
||||
* Describes IP address.
|
||||
* @see CategorizeIp()
|
||||
*/
|
||||
const char *GetIpCategoryName(int c) {
|
||||
switch (c) {
|
||||
case kIpMulticast:
|
||||
return "MULTICAST";
|
||||
case kIpLoopback:
|
||||
return "LOOPBACK";
|
||||
case kIpPrivate:
|
||||
return "PRIVATE";
|
||||
case kIpTestnet:
|
||||
return "TESTNET";
|
||||
case kIpAfrinic:
|
||||
return "AFRINIC";
|
||||
case kIpLacnic:
|
||||
return "LACNIC";
|
||||
case kIpApnic:
|
||||
return "APNIC";
|
||||
case kIpArin:
|
||||
return "ARIN";
|
||||
case kIpRipe:
|
||||
return "RIPE";
|
||||
case kIpDod:
|
||||
return "DOD";
|
||||
case kIpAtt:
|
||||
return "AT&T";
|
||||
case kIpApple:
|
||||
return "APPLE";
|
||||
case kIpFord:
|
||||
return "FORD";
|
||||
case kIpCogent:
|
||||
return "COGENT";
|
||||
case kIpPrudential:
|
||||
return "PRUDENTIAL";
|
||||
case kIpUsps:
|
||||
return "USPS";
|
||||
case kIpComcast:
|
||||
return "COMCAST";
|
||||
case kIpFuture:
|
||||
return "FUTURE";
|
||||
case kIpAnonymous:
|
||||
return "ANONYMOUS";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
69
net/http/hascontrolcodes.c
Normal file
69
net/http/hascontrolcodes.c
Normal file
|
@ -0,0 +1,69 @@
|
|||
/*-*- 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/errno.h"
|
||||
#include "libc/intrin/pcmpgtb.h"
|
||||
#include "libc/intrin/pmovmskb.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/thompike.h"
|
||||
#include "net/http/escape.h"
|
||||
|
||||
/**
|
||||
* Returns true if C0 or C1 control codes are present
|
||||
*
|
||||
* @param p is input value
|
||||
* @param n if -1 implies strlen
|
||||
* @param f can have kControlWs, kControlC0, kControlC1 to forbid
|
||||
* @return true if forbidden characters were found
|
||||
* @see VisualizeControlCodes()
|
||||
*/
|
||||
bool HasControlCodes(const char *p, size_t n, int f) {
|
||||
int c;
|
||||
wint_t x, a, b;
|
||||
size_t i, j, m;
|
||||
if (n == -1) n = p ? strlen(p) : 0;
|
||||
for (i = 0; i < n;) {
|
||||
x = p[i++] & 0xff;
|
||||
if (x >= 0300) {
|
||||
a = ThomPikeByte(x);
|
||||
m = ThomPikeLen(x) - 1;
|
||||
if (i + m <= n) {
|
||||
for (j = 0;;) {
|
||||
b = p[i + j] & 0xff;
|
||||
if (!ThomPikeCont(b)) break;
|
||||
a = ThomPikeMerge(a, b);
|
||||
if (++j == m) {
|
||||
x = a;
|
||||
i += j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (((f & kControlC1) && 0x80 <= x && x < 0xA0) ||
|
||||
((f & kControlC0) && (x < 32 || x == 0x7F) &&
|
||||
!(x == '\t' || x == '\r' || x == '\n' || x == '\v')) ||
|
||||
((f & kControlWs) &&
|
||||
(x == '\t' || x == '\r' || x == '\n' || x == '\v'))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
|
@ -30,8 +30,8 @@
|
|||
* @param n is byte length of s where -1 implies strlen
|
||||
* @return true if substring present
|
||||
*/
|
||||
bool HeaderHasSubstring(struct HttpRequest *m, const char *b, int h,
|
||||
const char *s, size_t n) {
|
||||
bool HeaderHas(struct HttpRequest *m, const char *b, int h, const char *s,
|
||||
size_t n) {
|
||||
size_t i;
|
||||
assert(0 <= h && h < kHttpHeadersMax);
|
||||
if (n == -1) n = s ? strlen(s) : 0;
|
||||
|
|
141
net/http/http.h
141
net/http/http.h
|
@ -1,6 +1,5 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_HTTP_HTTP_H_
|
||||
#define COSMOPOLITAN_LIBC_HTTP_HTTP_H_
|
||||
#include "libc/alg/alg.h"
|
||||
#include "libc/time/struct/tm.h"
|
||||
|
||||
#define kHttpGet 1
|
||||
|
@ -21,65 +20,72 @@
|
|||
#define kHttpReport 16
|
||||
#define kHttpUnlock 17
|
||||
|
||||
#define kHttpAccept 0
|
||||
#define kHttpAcceptCharset 1
|
||||
#define kHttpAcceptEncoding 2
|
||||
#define kHttpAcceptLanguage 3
|
||||
#define kHttpAge 4
|
||||
#define kHttpAllow 5
|
||||
#define kHttpAuthorization 6
|
||||
#define kHttpCacheControl 7
|
||||
#define kHttpChunked 8
|
||||
#define kHttpLink 9
|
||||
#define kHttpConnection 10
|
||||
#define kHttpContentBase 11
|
||||
#define kHttpContentEncoding 12
|
||||
#define kHttpContentLanguage 13
|
||||
#define kHttpContentLength 14
|
||||
#define kHttpContentLocation 15
|
||||
#define kHttpContentMd5 16
|
||||
#define kHttpContentRange 17
|
||||
#define kHttpContentType 18
|
||||
#define kHttpDate 19
|
||||
#define kHttpEtag 20
|
||||
#define kHttpExpires 21
|
||||
#define kHttpFrom 22
|
||||
#define kHttpHost 23
|
||||
#define kHttpIfMatch 24
|
||||
#define kHttpIfModifiedSince 25
|
||||
#define kHttpIfNoneMatch 26
|
||||
#define kHttpIfRange 27
|
||||
#define kHttpIfUnmodifiedSince 28
|
||||
#define kHttpKeepAlive 29
|
||||
#define kHttpMaxForwards 30
|
||||
#define kHttpPragma 31
|
||||
#define kHttpProxyAuthenticate 32
|
||||
#define kHttpProxyAuthorization 33
|
||||
#define kHttpProxyConnection 34
|
||||
#define kHttpRange 35
|
||||
#define kHttpReferer 36
|
||||
#define kHttpTransferEncoding 37
|
||||
#define kHttpUpgrade 38
|
||||
#define kHttpUserAgent 39
|
||||
#define kHttpVia 40
|
||||
#define kHttpLocation 41
|
||||
#define kHttpPublic 42
|
||||
#define kHttpRetryAfter 43
|
||||
#define kHttpServer 44
|
||||
#define kHttpVary 45
|
||||
#define kHttpWarning 46
|
||||
#define kHttpWwwAuthenticate 47
|
||||
#define kHttpLastModified 48
|
||||
#define kHttpTrailer 49
|
||||
#define kHttpTe 50
|
||||
#define kHttpDnt 51
|
||||
#define kHttpExpect 52
|
||||
#define kHttpContentDisposition 53
|
||||
#define kHttpContentDescription 54
|
||||
#define kHttpOrigin 55
|
||||
#define kHttpUpgradeInsecureRequests 56
|
||||
#define kHttpUri 57
|
||||
#define kHttpHeadersMax 58
|
||||
#define kHttpAccept 0
|
||||
#define kHttpAcceptCharset 1
|
||||
#define kHttpAcceptEncoding 2
|
||||
#define kHttpAcceptLanguage 3
|
||||
#define kHttpAge 4
|
||||
#define kHttpAllow 5
|
||||
#define kHttpAuthorization 6
|
||||
#define kHttpCacheControl 7
|
||||
#define kHttpChunked 8
|
||||
#define kHttpLink 9
|
||||
#define kHttpConnection 10
|
||||
#define kHttpContentBase 11
|
||||
#define kHttpContentEncoding 12
|
||||
#define kHttpContentLanguage 13
|
||||
#define kHttpContentLength 14
|
||||
#define kHttpContentLocation 15
|
||||
#define kHttpContentMd5 16
|
||||
#define kHttpContentRange 17
|
||||
#define kHttpContentType 18
|
||||
#define kHttpDate 19
|
||||
#define kHttpEtag 20
|
||||
#define kHttpExpires 21
|
||||
#define kHttpFrom 22
|
||||
#define kHttpHost 23
|
||||
#define kHttpIfMatch 24
|
||||
#define kHttpIfModifiedSince 25
|
||||
#define kHttpIfNoneMatch 26
|
||||
#define kHttpIfRange 27
|
||||
#define kHttpIfUnmodifiedSince 28
|
||||
#define kHttpKeepAlive 29
|
||||
#define kHttpMaxForwards 30
|
||||
#define kHttpPragma 31
|
||||
#define kHttpProxyAuthenticate 32
|
||||
#define kHttpProxyAuthorization 33
|
||||
#define kHttpProxyConnection 34
|
||||
#define kHttpRange 35
|
||||
#define kHttpReferer 36
|
||||
#define kHttpTransferEncoding 37
|
||||
#define kHttpUpgrade 38
|
||||
#define kHttpUserAgent 39
|
||||
#define kHttpVia 40
|
||||
#define kHttpLocation 41
|
||||
#define kHttpPublic 42
|
||||
#define kHttpRetryAfter 43
|
||||
#define kHttpServer 44
|
||||
#define kHttpVary 45
|
||||
#define kHttpWarning 46
|
||||
#define kHttpWwwAuthenticate 47
|
||||
#define kHttpLastModified 48
|
||||
#define kHttpTrailer 49
|
||||
#define kHttpTe 50
|
||||
#define kHttpDnt 51
|
||||
#define kHttpExpect 52
|
||||
#define kHttpContentDisposition 53
|
||||
#define kHttpContentDescription 54
|
||||
#define kHttpOrigin 55
|
||||
#define kHttpUpgradeInsecureRequests 56
|
||||
#define kHttpUri 57
|
||||
#define kHttpXCsrfToken 58
|
||||
#define kHttpXForwardedFor 59
|
||||
#define kHttpXForwardedHost 60
|
||||
#define kHttpXForwardedProto 61
|
||||
#define kHttpXRequestedWith 62
|
||||
#define kHttpAccessControlRequestMethod 63
|
||||
#define kHttpAccessControlRequestHeaders 64
|
||||
#define kHttpHeadersMax 65
|
||||
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
@ -111,30 +117,25 @@ extern const char kHttpToken[256];
|
|||
extern const char kHttpMethod[18][8];
|
||||
extern const bool kHttpRepeatable[kHttpHeadersMax];
|
||||
|
||||
const char *GetHttpReason(int);
|
||||
const char *GetHttpHeaderName(int);
|
||||
int GetHttpHeader(const char *, size_t);
|
||||
int GetHttpMethod(const char *, size_t);
|
||||
void InitHttpRequest(struct HttpRequest *);
|
||||
void DestroyHttpRequest(struct HttpRequest *);
|
||||
int ParseHttpRequest(struct HttpRequest *, const char *, size_t);
|
||||
bool HeaderHasSubstring(struct HttpRequest *, const char *, int, const char *,
|
||||
size_t);
|
||||
int NegotiateHttpRequest(int, const char *, uint32_t *, char *, uint32_t *,
|
||||
uint32_t *, bool, long double);
|
||||
bool HeaderHas(struct HttpRequest *, const char *, int, const char *, size_t);
|
||||
int64_t ParseContentLength(const char *, size_t);
|
||||
char *FormatHttpDateTime(char[hasatleast 30], struct tm *);
|
||||
bool ParseHttpRange(const char *, size_t, long, long *, long *);
|
||||
int64_t ParseHttpDateTime(const char *, size_t);
|
||||
const char *GetHttpReason(int);
|
||||
const char *GetHttpHeaderName(int);
|
||||
char *DecodeLatin1(const char *, size_t, size_t *);
|
||||
bool IsValidHttpToken(const char *, size_t);
|
||||
char *EncodeHttpHeaderValue(const char *, size_t, size_t *);
|
||||
char *VisualizeControlCodes(const char *, size_t, size_t *);
|
||||
char *IndentLines(const char *, size_t, size_t *, size_t);
|
||||
bool IsAcceptablePath(const char *, size_t);
|
||||
bool IsAcceptableHost(const char *, size_t);
|
||||
bool IsAcceptablePort(const char *, size_t);
|
||||
bool IsReasonablePath(const char *, size_t);
|
||||
int64_t ParseIp(const char *, size_t);
|
||||
int ParseForwarded(const char *, size_t, uint32_t *, uint16_t *);
|
||||
bool IsMimeType(const char *, size_t, const char *);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
|
|
|
@ -53,6 +53,21 @@ $(NET_HTTP_A).pkg: \
|
|||
$(NET_HTTP_A_OBJS) \
|
||||
$(foreach x,$(NET_HTTP_A_DIRECTDEPS),$($(x)_A).pkg)
|
||||
|
||||
o/$(MODE)/net/http/categorizeip.o \
|
||||
o/$(MODE)/net/http/getipcategoryname.o \
|
||||
o/$(MODE)/net/http/isafrinicip.o \
|
||||
o/$(MODE)/net/http/isanonymousip.o \
|
||||
o/$(MODE)/net/http/isapnicip.o \
|
||||
o/$(MODE)/net/http/isarinip.o \
|
||||
o/$(MODE)/net/http/isdodip.o \
|
||||
o/$(MODE)/net/http/islacnicip.o \
|
||||
o/$(MODE)/net/http/isloopbackip.o \
|
||||
o/$(MODE)/net/http/ismulticastip.o \
|
||||
o/$(MODE)/net/http/isripeip.o \
|
||||
o/$(MODE)/net/http/istestnetip.o: \
|
||||
OVERRIDE_CFLAGS += \
|
||||
-Os
|
||||
|
||||
o/$(MODE)/net/http/formathttpdatetime.o: \
|
||||
OVERRIDE_CFLAGS += \
|
||||
-O3
|
||||
|
|
|
@ -18,42 +18,46 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "net/http/http.h"
|
||||
#include "net/http/escape.h"
|
||||
|
||||
/**
|
||||
* Inserts spaces before lines.
|
||||
*
|
||||
* @param data is input value
|
||||
* @param size if -1 implies strlen
|
||||
* @param out_size if non-NULL receives output length
|
||||
* @param amt is number of spaces to use
|
||||
* @param p is input value
|
||||
* @param n if -1 implies strlen
|
||||
* @param z if non-NULL receives output length
|
||||
* @param j is number of spaces to use
|
||||
* @return allocated NUL-terminated buffer, or NULL w/ errno
|
||||
*/
|
||||
char *IndentLines(const char *data, size_t size, size_t *out_size, size_t amt) {
|
||||
char *r;
|
||||
const char *p;
|
||||
size_t i, n, m, a;
|
||||
if (size == -1) size = data ? strlen(data) : 0;
|
||||
char *IndentLines(const char *p, size_t n, size_t *z, size_t j) {
|
||||
char *r, *q;
|
||||
const char *l;
|
||||
size_t i, t, m, a;
|
||||
if (n == -1) n = p ? strlen(p) : 0;
|
||||
r = 0;
|
||||
n = 0;
|
||||
t = 0;
|
||||
do {
|
||||
if ((p = memchr(data, '\n', size))) {
|
||||
m = p + 1 - data;
|
||||
a = *data != '\r' && *data != '\n' ? amt : 0;
|
||||
if ((l = memchr(p, '\n', n))) {
|
||||
m = l + 1 - p;
|
||||
a = *p != '\r' && *p != '\n' ? j : 0;
|
||||
} else {
|
||||
m = size;
|
||||
a = size ? amt : 0;
|
||||
m = n;
|
||||
a = n ? j : 0;
|
||||
}
|
||||
r = xrealloc(r, n + a + m + 1);
|
||||
memset(r + n, ' ', a);
|
||||
memcpy(r + n + a, data, m);
|
||||
n += a + m;
|
||||
data += m;
|
||||
size -= m;
|
||||
} while (p);
|
||||
if (out_size) {
|
||||
*out_size = n;
|
||||
}
|
||||
r[n] = '\0';
|
||||
if ((q = realloc(r, t + a + m + 1))) {
|
||||
r = q;
|
||||
} else {
|
||||
free(r);
|
||||
if (z) *z = 0;
|
||||
return 0;
|
||||
}
|
||||
memset(r + t, ' ', a);
|
||||
memcpy(r + t + a, p, m);
|
||||
t += a + m;
|
||||
p += m;
|
||||
n -= m;
|
||||
} while (l);
|
||||
if (z) *z = t;
|
||||
r[t] = '\0';
|
||||
return r;
|
||||
}
|
||||
|
|
45
net/http/ip.h
Normal file
45
net/http/ip.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
#ifndef COSMOPOLITAN_NET_HTTP_IP_H_
|
||||
#define COSMOPOLITAN_NET_HTTP_IP_H_
|
||||
|
||||
#define kIpUnknown 0
|
||||
#define kIpMulticast 1
|
||||
#define kIpLoopback 2
|
||||
#define kIpPrivate 3
|
||||
#define kIpTestnet 4
|
||||
#define kIpAfrinic 5
|
||||
#define kIpLacnic 6
|
||||
#define kIpApnic 7
|
||||
#define kIpArin 8
|
||||
#define kIpRipe 9
|
||||
#define kIpDod 10
|
||||
#define kIpAtt 11
|
||||
#define kIpApple 12
|
||||
#define kIpFord 13
|
||||
#define kIpCogent 14
|
||||
#define kIpPrudential 15
|
||||
#define kIpUsps 16
|
||||
#define kIpComcast 17
|
||||
#define kIpFuture 18
|
||||
#define kIpAnonymous 19
|
||||
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
bool IsDodIp(uint32_t);
|
||||
bool IsArinIp(uint32_t);
|
||||
bool IsRipeIp(uint32_t);
|
||||
bool IsApnicIp(uint32_t);
|
||||
bool IsLacnicIp(uint32_t);
|
||||
bool IsPublicIp(uint32_t);
|
||||
bool IsPrivateIp(uint32_t);
|
||||
bool IsAfrinicIp(uint32_t);
|
||||
bool IsTestnetIp(uint32_t);
|
||||
bool IsLoopbackIp(uint32_t);
|
||||
bool IsMulticastIp(uint32_t);
|
||||
bool IsAnonymousIp(uint32_t);
|
||||
int CategorizeIp(uint32_t);
|
||||
const char *GetIpCategoryName(int);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_NET_HTTP_IP_H_ */
|
|
@ -29,9 +29,11 @@
|
|||
*
|
||||
* It is assumed that the URI parser already took care of percent
|
||||
* escape decoding as well as ISO-8859-1 decoding. The input needs
|
||||
* to be a UTF-8 string.
|
||||
* to be a UTF-8 string. This function takes overlong encodings into
|
||||
* consideration, so you don't need to call Underlong() beforehand.
|
||||
*
|
||||
* @param size if -1 implies strlen
|
||||
* @see IsReasonablePath()
|
||||
*/
|
||||
bool IsAcceptablePath(const char *data, size_t size) {
|
||||
const char *p, *e;
|
||||
|
|
28
net/http/isafrinicip.c
Normal file
28
net/http/isafrinicip.c
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*-*- 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 "net/http/ip.h"
|
||||
|
||||
/**
|
||||
* Returns true if IPv4 address is managed by AFRINIC.
|
||||
*/
|
||||
bool IsAfrinicIp(uint32_t x) {
|
||||
int a = (x & 0xff000000) >> 24;
|
||||
return a == 41 || a == 102 || a == 105 || a == 154 || a == 196 || a == 197 ||
|
||||
(x & 0xffffe000) == 0xca7b0000 /* 202.123.0.0/19 */;
|
||||
}
|
41
net/http/isanonymousip.c
Normal file
41
net/http/isanonymousip.c
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*-*- 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 "net/http/ip.h"
|
||||
|
||||
/**
|
||||
* Returns true if IPv4 address is anonymous proxy provider.
|
||||
*/
|
||||
bool IsAnonymousIp(uint32_t x) {
|
||||
return (x & 0xffffffff) == 0x1f0e8527 || (x & 0xffffff00) == 0x2e138900 ||
|
||||
(x & 0xffffff00) == 0x2e138f00 || (x & 0xfffffffe) == 0x32074e58 ||
|
||||
(x & 0xfffffe00) == 0x3e490800 || (x & 0xffffffff) == 0x3feb9bd2 ||
|
||||
(x & 0xffffffff) == 0x400c7617 || (x & 0xffffffff) == 0x400c7658 ||
|
||||
(x & 0xffffff00) == 0x432b9c00 || (x & 0xffffff00) == 0x450a8b00 ||
|
||||
(x & 0xffffff00) == 0x46e8f500 || (x & 0xffffffff) == 0x4a5209e0 ||
|
||||
(x & 0xfffffe00) == 0x50fe4a00 || (x & 0xfffffe00) == 0x5d735200 ||
|
||||
(x & 0xfffffe00) == 0x5d735400 || (x & 0xffffffff) == 0x602fe214 ||
|
||||
(x & 0xffffff00) == 0x93cb7800 || (x & 0xffffffff) == 0xb0094b2b ||
|
||||
(x & 0xffffffff) == 0xb9246491 || (x & 0xffffff00) == 0xc0ee1500 ||
|
||||
(x & 0xffffffff) == 0xc16b1147 || (x & 0xffffffff) == 0xc6906958 ||
|
||||
(x & 0xffffff00) == 0xc772df00 || (x & 0xffffff00) == 0xc7bcec00 ||
|
||||
(x & 0xffffffff) == 0xc8c8c8c8 || (x & 0xffffff00) == 0xce47a200 ||
|
||||
(x & 0xffffff00) == 0xcec46700 || (x & 0xffffffff) == 0xd02be134 ||
|
||||
(x & 0xffffff00) == 0xd1d8c600 || (x & 0xfffffffc) == 0xd43fa9e8 ||
|
||||
(x & 0xffffffff) == 0xd5eaf973 || (x & 0xffffff00) == 0xd897b400;
|
||||
}
|
35
net/http/isapnicip.c
Normal file
35
net/http/isapnicip.c
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*-*- 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 "net/http/ip.h"
|
||||
|
||||
/**
|
||||
* Returns true if IPv4 address is managed by APNIC.
|
||||
*/
|
||||
bool IsApnicIp(uint32_t x) {
|
||||
int a = (x & 0xff000000) >> 24;
|
||||
return a == 1 || a == 14 || a == 27 || a == 36 || a == 39 || a == 42 ||
|
||||
a == 43 || a == 49 || a == 58 || a == 59 || a == 60 || a == 61 ||
|
||||
a == 101 || a == 103 || a == 106 || a == 110 || a == 111 || a == 112 ||
|
||||
a == 113 || a == 114 || a == 115 || a == 116 || a == 117 || a == 118 ||
|
||||
a == 119 || a == 120 || a == 121 || a == 122 || a == 123 || a == 124 ||
|
||||
a == 125 || a == 126 || a == 133 || a == 150 || a == 153 || a == 163 ||
|
||||
a == 171 || a == 175 || a == 180 || a == 182 || a == 183 || a == 202 ||
|
||||
a == 203 || a == 210 || a == 211 || a == 218 || a == 219 || a == 220 ||
|
||||
a == 221 || a == 222 || a == 223;
|
||||
}
|
42
net/http/isarinip.c
Normal file
42
net/http/isarinip.c
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*-*- 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 "net/http/ip.h"
|
||||
|
||||
/**
|
||||
* Returns true if IPv4 address is managed by ARIN.
|
||||
*/
|
||||
bool IsArinIp(uint32_t x) {
|
||||
int a = (x & 0xff000000) >> 24;
|
||||
return a == 3 || a == 4 || a == 8 || a == 9 || a == 13 || a == 15 ||
|
||||
a == 16 || a == 18 || a == 20 || a == 23 || a == 24 || a == 32 ||
|
||||
a == 34 || a == 35 || a == 40 || a == 44 || a == 45 || a == 47 ||
|
||||
a == 50 || a == 52 || a == 54 || a == 63 || a == 64 || a == 65 ||
|
||||
a == 66 || a == 67 || a == 68 || a == 69 || a == 70 || a == 71 ||
|
||||
a == 72 || a == 74 || a == 75 || a == 76 || a == 96 || a == 97 ||
|
||||
a == 98 || a == 99 || a == 100 || a == 104 || a == 107 || a == 108 ||
|
||||
a == 128 || a == 129 || a == 130 || a == 131 || a == 132 || a == 134 ||
|
||||
a == 135 || a == 136 || a == 137 || a == 138 || a == 139 || a == 140 ||
|
||||
a == 142 || a == 143 || a == 144 || a == 146 || a == 147 || a == 148 ||
|
||||
a == 149 || a == 152 || a == 155 || a == 156 || a == 157 || a == 158 ||
|
||||
a == 159 || a == 160 || a == 161 || a == 162 || a == 164 || a == 165 ||
|
||||
a == 166 || a == 167 || a == 168 || a == 169 || a == 170 || a == 172 ||
|
||||
a == 173 || a == 174 || a == 184 || a == 192 || a == 198 || a == 199 ||
|
||||
a == 204 || a == 205 || a == 206 || a == 207 || a == 208 || a == 209 ||
|
||||
a == 216;
|
||||
}
|
29
net/http/isdodip.c
Normal file
29
net/http/isdodip.c
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*-*- 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 "net/http/ip.h"
|
||||
|
||||
/**
|
||||
* Returns true if IP is owned by the U.S. Department of Defense.
|
||||
*/
|
||||
bool IsDodIp(uint32_t x) {
|
||||
int a = (x & 0xff000000) >> 24;
|
||||
return a == 6 || a == 7 || a == 11 || a == 21 || a == 22 || a == 26 ||
|
||||
a == 28 || a == 29 || a == 30 || a == 33 || a == 55 || a == 214 ||
|
||||
a == 215;
|
||||
}
|
28
net/http/islacnicip.c
Normal file
28
net/http/islacnicip.c
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*-*- 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 "net/http/ip.h"
|
||||
|
||||
/**
|
||||
* Returns true if IPv4 address is managed by LACNIC.
|
||||
*/
|
||||
bool IsLacnicIp(uint32_t x) {
|
||||
int a = (x & 0xff000000) >> 24;
|
||||
return a == 177 || a == 179 || a == 181 || a == 186 || a == 187 || a == 189 ||
|
||||
a == 190 || a == 191 || a == 200 || a == 201;
|
||||
}
|
26
net/http/isloopbackip.c
Normal file
26
net/http/isloopbackip.c
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*-*- 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 "net/http/ip.h"
|
||||
|
||||
/**
|
||||
* Returns true if IPv4 address is used for localhost.
|
||||
*/
|
||||
bool IsLoopbackIp(uint32_t x) {
|
||||
return (x >> 24) == 127; /* 127.0.0.0/8 */
|
||||
}
|
26
net/http/ismulticastip.c
Normal file
26
net/http/ismulticastip.c
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*-*- 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 "net/http/ip.h"
|
||||
|
||||
/**
|
||||
* Returns true if IPv4 address is used for multicast.
|
||||
*/
|
||||
bool IsMulticastIp(uint32_t x) {
|
||||
return (x >> 28) == 0xE; /* 224.0.0.0/4 */
|
||||
}
|
28
net/http/isprivateip.c
Normal file
28
net/http/isprivateip.c
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*-*- 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 "net/http/ip.h"
|
||||
|
||||
/**
|
||||
* Returns true if IPv4 address is intended for private networks.
|
||||
*/
|
||||
bool IsPrivateIp(uint32_t x) {
|
||||
return (x >> 24) == 10 /* 10.0.0.0/8 */
|
||||
|| (x & 0xfff00000) == 0xac100000 /* 172.16.0.0/12 */
|
||||
|| (x & 0xffff0000) == 0xc0a80000 /* 192.168.0.0/16 */;
|
||||
}
|
26
net/http/ispublicip.c
Normal file
26
net/http/ispublicip.c
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*-*- 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 "net/http/ip.h"
|
||||
|
||||
/**
|
||||
* Returns true if IPv4 address can come from the Internet.
|
||||
*/
|
||||
bool IsPublicIp(uint32_t x) {
|
||||
return !IsLoopbackIp(x) && !IsPrivateIp(x) && !IsTestnetIp(x);
|
||||
}
|
67
net/http/isreasonablepath.c
Normal file
67
net/http/isreasonablepath.c
Normal file
|
@ -0,0 +1,67 @@
|
|||
/*-*- 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/str/str.h"
|
||||
#include "libc/str/thompike.h"
|
||||
#include "net/http/http.h"
|
||||
|
||||
/**
|
||||
* Returns true if path doesn't contain "." or ".." segments.
|
||||
*
|
||||
* @param size if -1 implies strlen
|
||||
* @see IsAcceptablePath()
|
||||
*/
|
||||
bool IsReasonablePath(const char *data, size_t size) {
|
||||
const char *p, *e;
|
||||
int x, y, z, a, b, i, n;
|
||||
if (size == -1) size = data ? strlen(data) : 0;
|
||||
z = '/';
|
||||
y = '/';
|
||||
x = '/';
|
||||
p = data;
|
||||
e = p + size;
|
||||
while (p < e) {
|
||||
x = *p++ & 0xff;
|
||||
if (x >= 0300) {
|
||||
a = ThomPikeByte(x);
|
||||
n = ThomPikeLen(x) - 1;
|
||||
if (p + n <= e) {
|
||||
for (i = 0;;) {
|
||||
b = p[i] & 0xff;
|
||||
if (!ThomPikeCont(b)) break;
|
||||
a = ThomPikeMerge(a, b);
|
||||
if (++i == n) {
|
||||
x = a;
|
||||
p += i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (x == '\\') {
|
||||
x = '/';
|
||||
}
|
||||
if (z == '/' && y == '.' && x == '/') return false;
|
||||
if (z == '/' && y == '.' && x == '.') return false;
|
||||
z = y;
|
||||
y = x;
|
||||
}
|
||||
if (y == '/' && x == '.') return false;
|
||||
if (z == '/' && y == '.' && x == '.') return false;
|
||||
return true;
|
||||
}
|
34
net/http/isripeip.c
Normal file
34
net/http/isripeip.c
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*-*- 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 "net/http/ip.h"
|
||||
|
||||
/**
|
||||
* Returns true if IPv4 address is managed by RIPE NCC.
|
||||
*/
|
||||
bool IsRipeIp(uint32_t x) {
|
||||
int a = (x & 0xff000000) >> 24;
|
||||
return a == 2 || a == 5 || a == 25 || a == 31 || a == 37 || a == 46 ||
|
||||
a == 51 || a == 53 || a == 57 || a == 62 || a == 77 || a == 78 ||
|
||||
a == 79 || a == 80 || a == 81 || a == 82 || a == 83 || a == 84 ||
|
||||
a == 85 || a == 86 || a == 87 || a == 88 || a == 89 || a == 90 ||
|
||||
a == 91 || a == 92 || a == 93 || a == 94 || a == 95 || a == 109 ||
|
||||
a == 141 || a == 145 || a == 151 || a == 176 || a == 178 || a == 185 ||
|
||||
a == 188 || a == 193 || a == 194 || a == 195 || a == 212 || a == 213 ||
|
||||
a == 217;
|
||||
}
|
29
net/http/istestnetip.c
Normal file
29
net/http/istestnetip.c
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*-*- 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 "net/http/ip.h"
|
||||
|
||||
/**
|
||||
* Returns true if IPv4 address is intended for documentation.
|
||||
* @see RFC5737
|
||||
*/
|
||||
bool IsTestnetIp(uint32_t x) {
|
||||
return (((x & 0xFFFFFF00u) == 0xC0000200u) /* 192.0.2.0/24 */ ||
|
||||
((x & 0xFFFFFF00u) == 0xC0000200u) /* 198.51.100.0/24 */ ||
|
||||
((x & 0xFFFFFF00u) == 0xCB007100u) /* 203.0.113.0/24 */);
|
||||
}
|
|
@ -1,106 +0,0 @@
|
|||
/*-*- 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 2020 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/calls/calls.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/math.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/poll.h"
|
||||
#include "libc/sysv/consts/shut.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
#include "libc/time/time.h"
|
||||
#include "net/http/http.h"
|
||||
|
||||
static pureconst long AsMilliseconds(long double ts) {
|
||||
return ts * 1e3 + .5;
|
||||
}
|
||||
|
||||
/**
|
||||
* Negotiates HTTP request.
|
||||
*
|
||||
* This function blocks until a response header is consumed. We assume
|
||||
* the response header is smaller than *inout_respsize. We're agnostic
|
||||
* to the various different i/o paradigms. Goal is really good latency.
|
||||
*
|
||||
* @param singleshot should be true w/ connection: close
|
||||
* @return 0 on success, or -1 w/ errno
|
||||
*/
|
||||
int NegotiateHttpRequest(int sock, const char *req, uint32_t *inout_reqsize,
|
||||
char *resp, uint32_t *inout_respsize,
|
||||
uint32_t *out_resphdrsize, bool singleshot,
|
||||
long double timeout) {
|
||||
ssize_t rc;
|
||||
struct pollfd fd;
|
||||
const char *body;
|
||||
long double start, now, deadline;
|
||||
uint32_t transmitted, received, exchanged, remaining;
|
||||
fd.fd = sock;
|
||||
received = 0;
|
||||
transmitted = 0;
|
||||
fd.events = POLLOUT | POLLIN;
|
||||
deadline = (start = now = nowl()) + timeout;
|
||||
do {
|
||||
if ((rc = poll(&fd, 1, MAX(0, AsMilliseconds(deadline - now)))) == 1) {
|
||||
if (fd.revents & POLLHUP) {
|
||||
econnreset();
|
||||
break;
|
||||
}
|
||||
if (fd.revents & (POLLIN | POLLERR)) {
|
||||
remaining = *inout_respsize - received - 1;
|
||||
if ((rc = recv(fd.fd, resp + received, remaining, 0)) != -1) {
|
||||
exchanged = rc;
|
||||
body = memmem(resp + (received >= 4 ? received - 4 : 0), exchanged,
|
||||
"\r\n\r\n", 4);
|
||||
received += exchanged;
|
||||
if (body) {
|
||||
resp[received] = '\0';
|
||||
*inout_respsize = received;
|
||||
*inout_reqsize = transmitted;
|
||||
*out_resphdrsize = body - resp;
|
||||
return 0;
|
||||
}
|
||||
if (exchanged == remaining) {
|
||||
emsgsize();
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (fd.revents & POLLOUT) {
|
||||
remaining = *inout_reqsize - transmitted;
|
||||
if ((rc = send(fd.fd, req + transmitted, remaining, 0)) != -1) {
|
||||
exchanged = rc;
|
||||
transmitted += exchanged;
|
||||
if (exchanged == remaining) {
|
||||
if (singleshot) shutdown(fd.fd, SHUT_WR);
|
||||
fd.events &= ~POLLOUT;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!rc) etimedout();
|
||||
break;
|
||||
}
|
||||
} while ((now = nowl()) < deadline);
|
||||
close(fd.fd);
|
||||
return -1;
|
||||
}
|
76
net/http/parseforwarded.c
Normal file
76
net/http/parseforwarded.c
Normal file
|
@ -0,0 +1,76 @@
|
|||
/*-*- 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/str/str.h"
|
||||
#include "net/http/http.h"
|
||||
|
||||
/**
|
||||
* Parses X-Forwarded-For.
|
||||
*
|
||||
* This header is used by reverse proxies. For example:
|
||||
*
|
||||
* X-Forwarded-For: 203.0.113.42:31337
|
||||
*
|
||||
* @param s is input data
|
||||
* @param n if -1 implies strlen
|
||||
* @param ip receives ip on success if not NULL
|
||||
* @param port receives port on success if not NULL
|
||||
* @return 0 on success or -1 on failure
|
||||
* @see RFC7239's poorly designed Forwarded header
|
||||
*/
|
||||
int ParseForwarded(const char *s, size_t n, uint32_t *ip, uint16_t *port) {
|
||||
size_t i;
|
||||
uint32_t x;
|
||||
int c, j, t;
|
||||
if (n == -1) n = s ? strlen(s) : 0;
|
||||
for (t = x = j = i = 0; i < n;) {
|
||||
c = s[i++] & 255;
|
||||
if (isdigit(c)) {
|
||||
t *= 10;
|
||||
t += c - '0';
|
||||
if (t > 255) return -1;
|
||||
} else if (c == '.') {
|
||||
x <<= 8;
|
||||
x |= t;
|
||||
t = 0;
|
||||
++j;
|
||||
} else if (c == ':') {
|
||||
x <<= 8;
|
||||
x |= t;
|
||||
t = 0;
|
||||
if (j != 3) return -1;
|
||||
while (i < n) {
|
||||
c = s[i++] & 255;
|
||||
if (isdigit(c)) {
|
||||
t *= 10;
|
||||
t += c - '0';
|
||||
if (t > 65535) return -1;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (!x || !t) return -1;
|
||||
if (ip) *ip = x;
|
||||
if (port) *port = t;
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
|
@ -60,14 +60,24 @@ void DestroyHttpRequest(struct HttpRequest *r) {
|
|||
* that fragmented messages can be handled efficiently. A limitation on
|
||||
* message size is imposed to make the header data structures smaller.
|
||||
*
|
||||
* This parser assumes ISO-8859-1 and guarantees no C0 or C1 control
|
||||
* codes are present in message fields, with the exception of tab.
|
||||
* Please note that fields like URI may use UTF-8 percent encoding. This
|
||||
* parser doesn't care if you choose ASA X3.4-1963 or MULTICS newlines.
|
||||
*
|
||||
* kHttpRepeatable defines which standard header fields are O(1) and
|
||||
* which ones may have comma entries spilled over into xheaders. For
|
||||
* most headers it's sufficient to simply check the static slice. If
|
||||
* r->headers[kHttpFoo].a is zero then the header is totally absent.
|
||||
*
|
||||
* This parser takes about 300 nanoseconds (900 cycles) to parse a 403
|
||||
* byte Chrome HTTP request under MODE=rel on a Core i9 which is about
|
||||
* gigabyte per second of throughput per core.
|
||||
* This parser has linear complexity. Each character only needs to be
|
||||
* considered a single time. That's the case even if messages are
|
||||
* fragmented. If a message is valid but incomplete, this function will
|
||||
* return zero so that it can be resumed as soon as more data arrives.
|
||||
*
|
||||
* This parser takes about 500 nanoseconds to parse a 403 byte Chrome
|
||||
* HTTP request under MODE=rel on a Core i9 which is about three cycles
|
||||
* per byte or a gigabyte per second of throughput per core.
|
||||
*
|
||||
* @note we assume p points to a buffer that has >=SHRT_MAX bytes
|
||||
* @see HTTP/1.1 RFC2616 RFC2068
|
||||
|
|
|
@ -127,25 +127,28 @@ static bool ParseScheme(struct UrlParser *u, struct Url *h) {
|
|||
}
|
||||
|
||||
static void ParseAuthority(struct UrlParser *u, struct Url *h) {
|
||||
bool b = false;
|
||||
int t = 0;
|
||||
const char *c = NULL;
|
||||
while (u->i < u->size) {
|
||||
u->c = u->data[u->i++] & 0xff;
|
||||
if (u->c == '/' || u->c == '#' || u->c == '?') {
|
||||
break;
|
||||
} else if (u->c == '[') {
|
||||
b = true;
|
||||
t = -1;
|
||||
} else if (u->c == ']') {
|
||||
b = false;
|
||||
} else if (u->c == ':' && !b) {
|
||||
t = 0;
|
||||
} else if (u->c == ':' && t >= 0) {
|
||||
*u->p++ = ':';
|
||||
c = u->p;
|
||||
++t;
|
||||
} else if (u->c == '@') {
|
||||
if (c) {
|
||||
h->user.p = u->q;
|
||||
h->user.n = c - u->q;
|
||||
h->user.n = c - 1 - u->q;
|
||||
h->pass.p = c;
|
||||
h->pass.n = u->p - c;
|
||||
c = NULL;
|
||||
t = 0;
|
||||
} else {
|
||||
h->user.p = u->q;
|
||||
h->user.n = u->p - u->q;
|
||||
|
@ -159,9 +162,9 @@ static void ParseAuthority(struct UrlParser *u, struct Url *h) {
|
|||
*u->p++ = u->c;
|
||||
}
|
||||
}
|
||||
if (c) {
|
||||
if (t == 1) {
|
||||
h->host.p = u->q;
|
||||
h->host.n = c - u->q;
|
||||
h->host.n = c - 1 - u->q;
|
||||
h->port.p = c;
|
||||
h->port.n = u->p - c;
|
||||
c = NULL;
|
||||
|
|
85
net/http/underlong.c
Normal file
85
net/http/underlong.c
Normal file
|
@ -0,0 +1,85 @@
|
|||
/*-*- 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/intrin/pcmpgtb.h"
|
||||
#include "libc/intrin/pmovmskb.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/thompike.h"
|
||||
#include "libc/str/tpenc.h"
|
||||
#include "net/http/escape.h"
|
||||
|
||||
/**
|
||||
* Canonicalizes overlong Thompson-Pike encodings.
|
||||
*
|
||||
* Please note that the IETF banned these numbers, so if you want to
|
||||
* enforce their ban you can simply strcmp() the result to check for
|
||||
* the existence of banned numbers.
|
||||
*
|
||||
* @param p is input value
|
||||
* @param n if -1 implies strlen
|
||||
* @param z if non-NULL receives output length
|
||||
* @return allocated NUL-terminated buffer, or NULL w/ errno
|
||||
*/
|
||||
char *Underlong(const char *p, size_t n, size_t *z) {
|
||||
uint64_t w;
|
||||
char *r, *q;
|
||||
size_t i, j, m;
|
||||
wint_t x, a, b;
|
||||
int8_t v1[16], v2[16], vz[16];
|
||||
if (z) *z = 0;
|
||||
if (n == -1) n = p ? strlen(p) : 0;
|
||||
if ((q = r = malloc(n + 1))) {
|
||||
for (i = 0; i < n;) {
|
||||
memset(vz, 0, 16); /* 50x speedup for ASCII */
|
||||
while (i + 16 < n) {
|
||||
memcpy(v1, p + i, 16);
|
||||
pcmpgtb(v2, v1, vz);
|
||||
if (pmovmskb((void *)v2) != 0xFFFF) break;
|
||||
memcpy(q, v1, 16);
|
||||
q += 16;
|
||||
i += 16;
|
||||
}
|
||||
x = p[i++] & 0xff;
|
||||
if (x >= 0300) {
|
||||
a = ThomPikeByte(x);
|
||||
m = ThomPikeLen(x) - 1;
|
||||
if (i + m <= n) {
|
||||
for (j = 0;;) {
|
||||
b = p[i + j] & 0xff;
|
||||
if (!ThomPikeCont(b)) break;
|
||||
a = ThomPikeMerge(a, b);
|
||||
if (++j == m) {
|
||||
x = a;
|
||||
i += j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
w = tpenc(x);
|
||||
do {
|
||||
*q++ = w;
|
||||
} while ((w >>= 8));
|
||||
}
|
||||
if (z) *z = q - r;
|
||||
*q++ = '\0';
|
||||
if ((q = realloc(r, q - r))) r = q;
|
||||
}
|
||||
return r;
|
||||
}
|
|
@ -20,7 +20,7 @@
|
|||
#include "libc/str/str.h"
|
||||
#include "libc/str/thompike.h"
|
||||
#include "libc/str/tpenc.h"
|
||||
#include "net/http/http.h"
|
||||
#include "net/http/escape.h"
|
||||
|
||||
/**
|
||||
* Filters out control codes from string.
|
||||
|
@ -29,6 +29,10 @@
|
|||
* want full blown C string literal escaping, but we don't want things
|
||||
* like raw ANSI control codes from untrusted devices in our terminals.
|
||||
*
|
||||
* This function also canonicalizes overlong encodings. Therefore it
|
||||
* isn't necessary to say VisualizeControlCodes(Underlong(𝑥))) since
|
||||
* VisualizeControlCodes(𝑥) will do the same thing.
|
||||
*
|
||||
* @param data is input value
|
||||
* @param size if -1 implies strlen
|
||||
* @param out_size if non-NULL receives output length
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue