mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-03-03 15:38:22 +00:00
parent
da36e7e256
commit
4d21cd315d
20 changed files with 1075 additions and 664 deletions
37
libc/str/memcasecmp.c
Normal file
37
libc/str/memcasecmp.c
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
/*-*- 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/str/str.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compares memory case-insensitively.
|
||||||
|
* @return is <0, 0, or >0 based on uint8_t comparison
|
||||||
|
*/
|
||||||
|
int memcasecmp(const void *p, const void *q, size_t n) {
|
||||||
|
int c;
|
||||||
|
size_t i;
|
||||||
|
const unsigned char *a, *b;
|
||||||
|
if ((a = p) != (b = q)) {
|
||||||
|
for (i = 0; i < n; ++i) {
|
||||||
|
if ((c = kToLower[a[i]] - kToLower[b[i]])) {
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -123,6 +123,7 @@ int wcscmp(const wchar_t *, const wchar_t *) strlenesque;
|
||||||
int wcsncmp(const wchar_t *, const wchar_t *, size_t) strlenesque;
|
int wcsncmp(const wchar_t *, const wchar_t *, size_t) strlenesque;
|
||||||
int wmemcmp(const wchar_t *, const wchar_t *, size_t) strlenesque;
|
int wmemcmp(const wchar_t *, const wchar_t *, size_t) strlenesque;
|
||||||
int strcasecmp(const char *, const char *) strlenesque;
|
int strcasecmp(const char *, const char *) strlenesque;
|
||||||
|
int memcasecmp(const void *, const void *, size_t) strlenesque;
|
||||||
int strcasecmp16(const char16_t *, const char16_t *) strlenesque;
|
int strcasecmp16(const char16_t *, const char16_t *) strlenesque;
|
||||||
int wcscasecmp(const wchar_t *, const wchar_t *) strlenesque;
|
int wcscasecmp(const wchar_t *, const wchar_t *) strlenesque;
|
||||||
int strncasecmp(const char *, const char *, size_t) strlenesque;
|
int strncasecmp(const char *, const char *, size_t) strlenesque;
|
||||||
|
|
|
@ -37,21 +37,13 @@ struct EscapeResult EscapeUrl(const char *data, size_t size,
|
||||||
struct EscapeResult r;
|
struct EscapeResult r;
|
||||||
p = r.data = xmalloc(size * 6 + 1);
|
p = r.data = xmalloc(size * 6 + 1);
|
||||||
for (i = 0; i < size; ++i) {
|
for (i = 0; i < size; ++i) {
|
||||||
switch (xlat[(c = data[i] & 0xff)]) {
|
if (!xlat[(c = data[i] & 0xff)]) {
|
||||||
case 0:
|
*p++ = c;
|
||||||
*p++ = c;
|
} else {
|
||||||
break;
|
p[0] = '%';
|
||||||
case 1:
|
p[1] = "0123456789ABCDEF"[(c & 0xF0) >> 4];
|
||||||
*p++ = '+';
|
p[2] = "0123456789ABCDEF"[(c & 0x0F) >> 0];
|
||||||
break;
|
p += 3;
|
||||||
case 2:
|
|
||||||
p[0] = '%';
|
|
||||||
p[1] = "0123456789ABCDEF"[(c & 0xF0) >> 4];
|
|
||||||
p[2] = "0123456789ABCDEF"[(c & 0x0F) >> 0];
|
|
||||||
p += 3;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
unreachable;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
r.size = p - r.data;
|
r.size = p - r.data;
|
||||||
|
|
|
@ -21,27 +21,27 @@
|
||||||
|
|
||||||
// url fragment dispatch
|
// url fragment dispatch
|
||||||
// - 0 is -/?.~_@:!$&'()*+,;=0-9A-Za-z
|
// - 0 is -/?.~_@:!$&'()*+,;=0-9A-Za-z
|
||||||
// - 2 is everything else which needs uppercase hex %XX
|
// - 1 is everything else which needs uppercase hex %XX
|
||||||
// note that '& can break html
|
// note that '& can break html
|
||||||
// note that '() can break css urls
|
// note that '() can break css urls
|
||||||
// note that unicode can still be wild
|
// note that unicode can still be wild
|
||||||
static const char kEscapeUrlFragment[256] = {
|
static const char kEscapeUrlFragment[256] = {
|
||||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0x00
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x00
|
||||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0x10
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x10
|
||||||
2, 0, 2, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x20
|
1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x20
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, // 0x30
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, // 0x30
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x40
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x40
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, // 0x50
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, // 0x50
|
||||||
2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x60
|
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x60
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, 2, // 0x70
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, // 0x70
|
||||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0x80
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x80
|
||||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0x90
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x90
|
||||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xa0
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xa0
|
||||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xb0
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xb0
|
||||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xc0
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xc0
|
||||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xd0
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xd0
|
||||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xe0
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xe0
|
||||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xf0
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xf0
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -21,26 +21,25 @@
|
||||||
|
|
||||||
// url query/form name/parameter dispatch
|
// url query/form name/parameter dispatch
|
||||||
// - 0 is -.*_0-9A-Za-z
|
// - 0 is -.*_0-9A-Za-z
|
||||||
// - 1 is ' ' which becomes '+'
|
// - 1 is everything else which needs uppercase hex %XX
|
||||||
// - 2 is everything else which needs uppercase hex %XX
|
|
||||||
// note that unicode can still be wild
|
// note that unicode can still be wild
|
||||||
static const char kEscapeUrlParam[256] = {
|
static const char kEscapeUrlParam[256] = {
|
||||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0x00
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x00
|
||||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0x10
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x10
|
||||||
1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 0, 0, 2, // 0x20
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, // 0x20
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, // 0x30
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, // 0x30
|
||||||
2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x40
|
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x40
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, // 0x50
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, // 0x50
|
||||||
2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x60
|
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x60
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, // 0x70
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, // 0x70
|
||||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0x80
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x80
|
||||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0x90
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x90
|
||||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xa0
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xa0
|
||||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xb0
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xb0
|
||||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xc0
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xc0
|
||||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xd0
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xd0
|
||||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xe0
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xe0
|
||||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xf0
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xf0
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -21,27 +21,27 @@
|
||||||
|
|
||||||
// url path dispatch
|
// url path dispatch
|
||||||
// - 0 is -.~_@:!$&'()*+,;=0-9A-Za-z/
|
// - 0 is -.~_@:!$&'()*+,;=0-9A-Za-z/
|
||||||
// - 2 is everything else which needs uppercase hex %XX
|
// - 1 is everything else which needs uppercase hex %XX
|
||||||
// note that '& can break html
|
// note that '& can break html
|
||||||
// note that '() can break css urls
|
// note that '() can break css urls
|
||||||
// note that unicode can still be wild
|
// note that unicode can still be wild
|
||||||
static const char kEscapeUrlPath[256] = {
|
static const char kEscapeUrlPath[256] = {
|
||||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0x00
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x00
|
||||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0x10
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x10
|
||||||
2, 0, 2, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x20
|
1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x20
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 2, // 0x30
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, // 0x30
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x40
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x40
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, // 0x50
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, // 0x50
|
||||||
2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x60
|
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x60
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, 2, // 0x70
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, // 0x70
|
||||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0x80
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x80
|
||||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0x90
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x90
|
||||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xa0
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xa0
|
||||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xb0
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xb0
|
||||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xc0
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xc0
|
||||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xd0
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xd0
|
||||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xe0
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xe0
|
||||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xf0
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xf0
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -21,27 +21,27 @@
|
||||||
|
|
||||||
// url path segment dispatch
|
// url path segment dispatch
|
||||||
// - 0 is -.~_@:!$&'()*+,;=0-9A-Za-z
|
// - 0 is -.~_@:!$&'()*+,;=0-9A-Za-z
|
||||||
// - 2 is everything else which needs uppercase hex %XX
|
// - 1 is everything else which needs uppercase hex %XX
|
||||||
// note that '& can break html
|
// note that '& can break html
|
||||||
// note that '() can break css urls
|
// note that '() can break css urls
|
||||||
// note that unicode can still be wild
|
// note that unicode can still be wild
|
||||||
static const char kEscapeUrlPathSegment[256] = {
|
static const char kEscapeUrlPathSegment[256] = {
|
||||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0x00
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x00
|
||||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0x10
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x10
|
||||||
2, 0, 2, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, // 0x20
|
1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, // 0x20
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 2, // 0x30
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, // 0x30
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x40
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x40
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 0, // 0x50
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, // 0x50
|
||||||
2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x60
|
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x60
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 0, 2, // 0x70
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, // 0x70
|
||||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0x80
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x80
|
||||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0x90
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x90
|
||||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xa0
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xa0
|
||||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xb0
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xb0
|
||||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xc0
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xc0
|
||||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xd0
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xd0
|
||||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xe0
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xe0
|
||||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xf0
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xf0
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -11,57 +11,61 @@
|
||||||
%define lookup-function-name LookupHttpHeader
|
%define lookup-function-name LookupHttpHeader
|
||||||
struct HttpHeaderSlot { char *name; char code; };
|
struct HttpHeaderSlot { char *name; char code; };
|
||||||
%%
|
%%
|
||||||
Accept, kHttpAccept
|
Accept, kHttpAccept
|
||||||
Accept-Charset, kHttpAcceptCharset
|
Accept-Charset, kHttpAcceptCharset
|
||||||
Accept-Encoding, kHttpAcceptEncoding
|
Accept-Encoding, kHttpAcceptEncoding
|
||||||
Accept-Language, kHttpAcceptLanguage
|
Accept-Language, kHttpAcceptLanguage
|
||||||
Age, kHttpAge
|
Age, kHttpAge
|
||||||
Allow, kHttpAllow
|
Allow, kHttpAllow
|
||||||
Authorization, kHttpAuthorization
|
Authorization, kHttpAuthorization
|
||||||
Cache-Control, kHttpCacheControl
|
Cache-Control, kHttpCacheControl
|
||||||
Chunked, kHttpChunked
|
Chunked, kHttpChunked
|
||||||
Close, kHttpClose
|
Close, kHttpClose
|
||||||
Connection, kHttpConnection
|
Connection, kHttpConnection
|
||||||
Content-Base, kHttpContentBase
|
Content-Base, kHttpContentBase
|
||||||
Content-Encoding, kHttpContentEncoding
|
Content-Encoding, kHttpContentEncoding
|
||||||
Content-Language, kHttpContentLanguage
|
Content-Language, kHttpContentLanguage
|
||||||
Content-Length, kHttpContentLength
|
Content-Length, kHttpContentLength
|
||||||
Content-Location, kHttpContentLocation
|
Content-Location, kHttpContentLocation
|
||||||
Content-Md5, kHttpContentMd5
|
Content-Md5, kHttpContentMd5
|
||||||
Content-Range, kHttpContentRange
|
Content-Range, kHttpContentRange
|
||||||
Content-Type, kHttpContentType
|
Content-Type, kHttpContentType
|
||||||
Date, kHttpDate
|
Date, kHttpDate
|
||||||
ETag, kHttpEtag
|
ETag, kHttpEtag
|
||||||
Expires, kHttpExpires
|
Expires, kHttpExpires
|
||||||
From, kHttpFrom
|
From, kHttpFrom
|
||||||
Host, kHttpHost
|
Host, kHttpHost
|
||||||
If-Match, kHttpIfMatch
|
If-Match, kHttpIfMatch
|
||||||
If-Modified-Since, kHttpIfModifiedSince
|
If-Modified-Since, kHttpIfModifiedSince
|
||||||
If-None-Match, kHttpIfNoneMatch
|
If-None-Match, kHttpIfNoneMatch
|
||||||
If-Range, kHttpIfRange
|
If-Range, kHttpIfRange
|
||||||
If-Unmodified-Since, kHttpIfUnmodifiedSince
|
If-Unmodified-Since, kHttpIfUnmodifiedSince
|
||||||
Keep-Alive, kHttpKeepAlive
|
Keep-Alive, kHttpKeepAlive
|
||||||
Max-Forwards, kHttpMaxForwards
|
Max-Forwards, kHttpMaxForwards
|
||||||
Pragma, kHttpPragma
|
Pragma, kHttpPragma
|
||||||
Proxy-Authenticate, kHttpProxyAuthenticate
|
Proxy-Authenticate, kHttpProxyAuthenticate
|
||||||
Proxy-Authorization, kHttpProxyAuthorization
|
Proxy-Authorization, kHttpProxyAuthorization
|
||||||
Proxy-Connection, kHttpProxyConnection
|
Proxy-Connection, kHttpProxyConnection
|
||||||
Range, kHttpRange
|
Range, kHttpRange
|
||||||
Referer, kHttpReferer
|
Referer, kHttpReferer
|
||||||
Transfer-Encoding, kHttpTransferEncoding
|
Transfer-Encoding, kHttpTransferEncoding
|
||||||
Upgrade, kHttpUpgrade
|
Upgrade, kHttpUpgrade
|
||||||
User-Agent, kHttpUserAgent
|
User-Agent, kHttpUserAgent
|
||||||
Via, kHttpVia
|
Via, kHttpVia
|
||||||
Location, kHttpLocation
|
Location, kHttpLocation
|
||||||
Public, kHttpPublic
|
Public, kHttpPublic
|
||||||
Retry-After, kHttpRetryAfter
|
Retry-After, kHttpRetryAfter
|
||||||
Server, kHttpServer
|
Server, kHttpServer
|
||||||
Vary, kHttpVary
|
Vary, kHttpVary
|
||||||
Warning, kHttpWarning
|
Warning, kHttpWarning
|
||||||
WWW-Authenticate, kHttpWwwAuthenticate
|
WWW-Authenticate, kHttpWwwAuthenticate
|
||||||
Last-Modified, kHttpLastModified
|
Last-Modified, kHttpLastModified
|
||||||
Cookie, kHttpCookie
|
Cookie, kHttpCookie
|
||||||
Trailer, kHttpTrailer
|
Trailer, kHttpTrailer
|
||||||
TE, kHttpTe
|
TE, kHttpTe
|
||||||
DNT, kHttpDnt
|
DNT, kHttpDnt
|
||||||
Expect, kHttpExpect
|
Expect, kHttpExpect
|
||||||
|
Content-Disposition, kHttpContentDisposition
|
||||||
|
Content-Description, kHttpContentDescription
|
||||||
|
Origin, kHttpOrigin
|
||||||
|
Upgrade-Insecure-Requests, kHttpUpgradeInsecureRequests
|
||||||
|
|
|
@ -37,12 +37,12 @@
|
||||||
#line 12 "gethttpheader.gperf"
|
#line 12 "gethttpheader.gperf"
|
||||||
struct HttpHeaderSlot { char *name; char code; };
|
struct HttpHeaderSlot { char *name; char code; };
|
||||||
|
|
||||||
#define TOTAL_KEYWORDS 54
|
#define TOTAL_KEYWORDS 58
|
||||||
#define MIN_WORD_LENGTH 2
|
#define MIN_WORD_LENGTH 2
|
||||||
#define MAX_WORD_LENGTH 19
|
#define MAX_WORD_LENGTH 25
|
||||||
#define MIN_HASH_VALUE 2
|
#define MIN_HASH_VALUE 2
|
||||||
#define MAX_HASH_VALUE 89
|
#define MAX_HASH_VALUE 97
|
||||||
/* maximum key range = 88, duplicates = 0 */
|
/* maximum key range = 96, duplicates = 0 */
|
||||||
|
|
||||||
#ifndef GPERF_DOWNCASE
|
#ifndef GPERF_DOWNCASE
|
||||||
#define GPERF_DOWNCASE 1
|
#define GPERF_DOWNCASE 1
|
||||||
|
@ -101,32 +101,32 @@ hash (register const char *str, register size_t len)
|
||||||
{
|
{
|
||||||
static const unsigned char asso_values[] =
|
static const unsigned char asso_values[] =
|
||||||
{
|
{
|
||||||
90, 90, 90, 90, 90, 90, 90, 90, 90, 90,
|
98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
|
||||||
90, 90, 90, 90, 90, 90, 90, 90, 90, 90,
|
98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
|
||||||
90, 90, 90, 90, 90, 90, 90, 90, 90, 90,
|
98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
|
||||||
90, 90, 90, 90, 90, 90, 90, 90, 90, 90,
|
98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
|
||||||
90, 90, 90, 90, 90, 30, 90, 90, 90, 90,
|
98, 98, 98, 98, 98, 30, 98, 98, 98, 98,
|
||||||
90, 90, 90, 90, 90, 90, 90, 90, 90, 90,
|
98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
|
||||||
90, 90, 90, 90, 90, 5, 5, 30, 50, 0,
|
98, 98, 98, 98, 98, 5, 5, 30, 55, 0,
|
||||||
35, 30, 0, 5, 90, 40, 0, 30, 0, 20,
|
35, 30, 0, 35, 98, 40, 0, 30, 0, 20,
|
||||||
45, 90, 0, 5, 10, 5, 0, 15, 20, 25,
|
55, 98, 0, 5, 10, 5, 0, 5, 20, 30,
|
||||||
90, 90, 90, 90, 90, 90, 90, 5, 5, 30,
|
98, 98, 98, 98, 98, 98, 98, 5, 5, 30,
|
||||||
50, 0, 35, 30, 0, 5, 90, 40, 0, 30,
|
55, 0, 35, 30, 0, 35, 98, 40, 0, 30,
|
||||||
0, 20, 45, 90, 0, 5, 10, 5, 0, 15,
|
0, 20, 55, 98, 0, 5, 10, 5, 0, 5,
|
||||||
20, 25, 90, 90, 90, 90, 90, 90, 90, 90,
|
20, 30, 98, 98, 98, 98, 98, 98, 98, 98,
|
||||||
90, 90, 90, 90, 90, 90, 90, 90, 90, 90,
|
98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
|
||||||
90, 90, 90, 90, 90, 90, 90, 90, 90, 90,
|
98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
|
||||||
90, 90, 90, 90, 90, 90, 90, 90, 90, 90,
|
98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
|
||||||
90, 90, 90, 90, 90, 90, 90, 90, 90, 90,
|
98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
|
||||||
90, 90, 90, 90, 90, 90, 90, 90, 90, 90,
|
98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
|
||||||
90, 90, 90, 90, 90, 90, 90, 90, 90, 90,
|
98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
|
||||||
90, 90, 90, 90, 90, 90, 90, 90, 90, 90,
|
98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
|
||||||
90, 90, 90, 90, 90, 90, 90, 90, 90, 90,
|
98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
|
||||||
90, 90, 90, 90, 90, 90, 90, 90, 90, 90,
|
98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
|
||||||
90, 90, 90, 90, 90, 90, 90, 90, 90, 90,
|
98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
|
||||||
90, 90, 90, 90, 90, 90, 90, 90, 90, 90,
|
98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
|
||||||
90, 90, 90, 90, 90, 90, 90, 90, 90, 90,
|
98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
|
||||||
90, 90, 90, 90, 90, 90
|
98, 98, 98, 98, 98, 98
|
||||||
};
|
};
|
||||||
register unsigned int hval = len;
|
register unsigned int hval = len;
|
||||||
|
|
||||||
|
@ -159,132 +159,137 @@ LookupHttpHeader (register const char *str, register size_t len)
|
||||||
{
|
{
|
||||||
{""}, {""},
|
{""}, {""},
|
||||||
#line 65 "gethttpheader.gperf"
|
#line 65 "gethttpheader.gperf"
|
||||||
{"TE", kHttpTe},
|
{"TE", kHttpTe},
|
||||||
#line 18 "gethttpheader.gperf"
|
#line 18 "gethttpheader.gperf"
|
||||||
{"Age", kHttpAge},
|
{"Age", kHttpAge},
|
||||||
{""}, {""},
|
{""}, {""},
|
||||||
#line 58 "gethttpheader.gperf"
|
#line 58 "gethttpheader.gperf"
|
||||||
{"Server", kHttpServer},
|
{"Server", kHttpServer},
|
||||||
#line 60 "gethttpheader.gperf"
|
#line 60 "gethttpheader.gperf"
|
||||||
{"Warning", kHttpWarning},
|
{"Warning", kHttpWarning},
|
||||||
#line 54 "gethttpheader.gperf"
|
#line 54 "gethttpheader.gperf"
|
||||||
{"Via", kHttpVia},
|
{"Via", kHttpVia},
|
||||||
{""},
|
{""},
|
||||||
#line 24 "gethttpheader.gperf"
|
#line 24 "gethttpheader.gperf"
|
||||||
{"Connection", kHttpConnection},
|
{"Connection", kHttpConnection},
|
||||||
#line 56 "gethttpheader.gperf"
|
#line 56 "gethttpheader.gperf"
|
||||||
{"Public", kHttpPublic},
|
{"Public", kHttpPublic},
|
||||||
#line 22 "gethttpheader.gperf"
|
#line 22 "gethttpheader.gperf"
|
||||||
{"Chunked", kHttpChunked},
|
{"Chunked", kHttpChunked},
|
||||||
#line 66 "gethttpheader.gperf"
|
#line 66 "gethttpheader.gperf"
|
||||||
{"DNT", kHttpDnt},
|
{"DNT", kHttpDnt},
|
||||||
#line 33 "gethttpheader.gperf"
|
#line 33 "gethttpheader.gperf"
|
||||||
{"Date", kHttpDate},
|
{"Date", kHttpDate},
|
||||||
{""}, {""},
|
{""}, {""}, {""}, {""},
|
||||||
#line 64 "gethttpheader.gperf"
|
|
||||||
{"Trailer", kHttpTrailer},
|
|
||||||
{""},
|
|
||||||
#line 37 "gethttpheader.gperf"
|
#line 37 "gethttpheader.gperf"
|
||||||
{"Host", kHttpHost},
|
{"Host", kHttpHost},
|
||||||
#line 53 "gethttpheader.gperf"
|
#line 53 "gethttpheader.gperf"
|
||||||
{"User-Agent", kHttpUserAgent},
|
{"User-Agent", kHttpUserAgent},
|
||||||
#line 57 "gethttpheader.gperf"
|
#line 57 "gethttpheader.gperf"
|
||||||
{"Retry-After", kHttpRetryAfter},
|
{"Retry-After", kHttpRetryAfter},
|
||||||
#line 51 "gethttpheader.gperf"
|
#line 51 "gethttpheader.gperf"
|
||||||
{"Transfer-Encoding", kHttpTransferEncoding},
|
{"Transfer-Encoding", kHttpTransferEncoding},
|
||||||
{""},
|
{""},
|
||||||
#line 28 "gethttpheader.gperf"
|
#line 28 "gethttpheader.gperf"
|
||||||
{"Content-Length", kHttpContentLength},
|
{"Content-Length", kHttpContentLength},
|
||||||
#line 19 "gethttpheader.gperf"
|
#line 19 "gethttpheader.gperf"
|
||||||
{"Allow", kHttpAllow},
|
{"Allow", kHttpAllow},
|
||||||
#line 26 "gethttpheader.gperf"
|
#line 26 "gethttpheader.gperf"
|
||||||
{"Content-Encoding", kHttpContentEncoding},
|
{"Content-Encoding", kHttpContentEncoding},
|
||||||
#line 25 "gethttpheader.gperf"
|
#line 25 "gethttpheader.gperf"
|
||||||
{"Content-Base", kHttpContentBase},
|
{"Content-Base", kHttpContentBase},
|
||||||
#line 31 "gethttpheader.gperf"
|
#line 31 "gethttpheader.gperf"
|
||||||
{"Content-Range", kHttpContentRange},
|
{"Content-Range", kHttpContentRange},
|
||||||
#line 59 "gethttpheader.gperf"
|
#line 69 "gethttpheader.gperf"
|
||||||
{"Vary", kHttpVary},
|
{"Content-Description", kHttpContentDescription},
|
||||||
#line 23 "gethttpheader.gperf"
|
#line 23 "gethttpheader.gperf"
|
||||||
{"Close", kHttpClose},
|
{"Close", kHttpClose},
|
||||||
#line 27 "gethttpheader.gperf"
|
#line 27 "gethttpheader.gperf"
|
||||||
{"Content-Language", kHttpContentLanguage},
|
{"Content-Language", kHttpContentLanguage},
|
||||||
{""},
|
{""},
|
||||||
#line 20 "gethttpheader.gperf"
|
#line 20 "gethttpheader.gperf"
|
||||||
{"Authorization", kHttpAuthorization},
|
{"Authorization", kHttpAuthorization},
|
||||||
{""},
|
#line 59 "gethttpheader.gperf"
|
||||||
|
{"Vary", kHttpVary},
|
||||||
#line 49 "gethttpheader.gperf"
|
#line 49 "gethttpheader.gperf"
|
||||||
{"Range", kHttpRange},
|
{"Range", kHttpRange},
|
||||||
#line 14 "gethttpheader.gperf"
|
#line 14 "gethttpheader.gperf"
|
||||||
{"Accept", kHttpAccept},
|
{"Accept", kHttpAccept},
|
||||||
#line 52 "gethttpheader.gperf"
|
#line 52 "gethttpheader.gperf"
|
||||||
{"Upgrade", kHttpUpgrade},
|
{"Upgrade", kHttpUpgrade},
|
||||||
#line 41 "gethttpheader.gperf"
|
#line 41 "gethttpheader.gperf"
|
||||||
{"If-Range", kHttpIfRange},
|
{"If-Range", kHttpIfRange},
|
||||||
#line 34 "gethttpheader.gperf"
|
#line 34 "gethttpheader.gperf"
|
||||||
{"ETag", kHttpEtag},
|
{"ETag", kHttpEtag},
|
||||||
{""},
|
{""},
|
||||||
#line 45 "gethttpheader.gperf"
|
#line 45 "gethttpheader.gperf"
|
||||||
{"Pragma", kHttpPragma},
|
{"Pragma", kHttpPragma},
|
||||||
#line 50 "gethttpheader.gperf"
|
#line 50 "gethttpheader.gperf"
|
||||||
{"Referer", kHttpReferer},
|
{"Referer", kHttpReferer},
|
||||||
#line 55 "gethttpheader.gperf"
|
#line 55 "gethttpheader.gperf"
|
||||||
{"Location", kHttpLocation},
|
{"Location", kHttpLocation},
|
||||||
{""},
|
{""},
|
||||||
#line 17 "gethttpheader.gperf"
|
#line 17 "gethttpheader.gperf"
|
||||||
{"Accept-Language", kHttpAcceptLanguage},
|
{"Accept-Language", kHttpAcceptLanguage},
|
||||||
#line 29 "gethttpheader.gperf"
|
#line 29 "gethttpheader.gperf"
|
||||||
{"Content-Location", kHttpContentLocation},
|
{"Content-Location", kHttpContentLocation},
|
||||||
#line 32 "gethttpheader.gperf"
|
#line 64 "gethttpheader.gperf"
|
||||||
{"Content-Type", kHttpContentType},
|
{"Trailer", kHttpTrailer},
|
||||||
#line 40 "gethttpheader.gperf"
|
#line 40 "gethttpheader.gperf"
|
||||||
{"If-None-Match", kHttpIfNoneMatch},
|
{"If-None-Match", kHttpIfNoneMatch},
|
||||||
#line 15 "gethttpheader.gperf"
|
#line 15 "gethttpheader.gperf"
|
||||||
{"Accept-Charset", kHttpAcceptCharset},
|
{"Accept-Charset", kHttpAcceptCharset},
|
||||||
{""},
|
|
||||||
#line 67 "gethttpheader.gperf"
|
|
||||||
{"Expect", kHttpExpect},
|
|
||||||
{""},
|
|
||||||
#line 21 "gethttpheader.gperf"
|
|
||||||
{"Cache-Control", kHttpCacheControl},
|
|
||||||
#line 36 "gethttpheader.gperf"
|
|
||||||
{"From", kHttpFrom},
|
|
||||||
#line 43 "gethttpheader.gperf"
|
|
||||||
{"Keep-Alive", kHttpKeepAlive},
|
|
||||||
#line 48 "gethttpheader.gperf"
|
|
||||||
{"Proxy-Connection", kHttpProxyConnection},
|
|
||||||
#line 35 "gethttpheader.gperf"
|
|
||||||
{"Expires", kHttpExpires},
|
|
||||||
#line 46 "gethttpheader.gperf"
|
|
||||||
{"Proxy-Authenticate", kHttpProxyAuthenticate},
|
|
||||||
#line 47 "gethttpheader.gperf"
|
|
||||||
{"Proxy-Authorization", kHttpProxyAuthorization},
|
|
||||||
{""},
|
{""},
|
||||||
#line 61 "gethttpheader.gperf"
|
#line 61 "gethttpheader.gperf"
|
||||||
{"WWW-Authenticate", kHttpWwwAuthenticate},
|
{"WWW-Authenticate", kHttpWwwAuthenticate},
|
||||||
|
#line 32 "gethttpheader.gperf"
|
||||||
|
{"Content-Type", kHttpContentType},
|
||||||
|
#line 21 "gethttpheader.gperf"
|
||||||
|
{"Cache-Control", kHttpCacheControl},
|
||||||
|
#line 36 "gethttpheader.gperf"
|
||||||
|
{"From", kHttpFrom},
|
||||||
|
#line 71 "gethttpheader.gperf"
|
||||||
|
{"Upgrade-Insecure-Requests", kHttpUpgradeInsecureRequests},
|
||||||
|
#line 48 "gethttpheader.gperf"
|
||||||
|
{"Proxy-Connection", kHttpProxyConnection},
|
||||||
|
{""},
|
||||||
|
#line 46 "gethttpheader.gperf"
|
||||||
|
{"Proxy-Authenticate", kHttpProxyAuthenticate},
|
||||||
|
#line 47 "gethttpheader.gperf"
|
||||||
|
{"Proxy-Authorization", kHttpProxyAuthorization},
|
||||||
|
{""},
|
||||||
|
#line 67 "gethttpheader.gperf"
|
||||||
|
{"Expect", kHttpExpect},
|
||||||
#line 44 "gethttpheader.gperf"
|
#line 44 "gethttpheader.gperf"
|
||||||
{"Max-Forwards", kHttpMaxForwards},
|
{"Max-Forwards", kHttpMaxForwards},
|
||||||
#line 62 "gethttpheader.gperf"
|
#line 62 "gethttpheader.gperf"
|
||||||
{"Last-Modified", kHttpLastModified},
|
{"Last-Modified", kHttpLastModified},
|
||||||
{""}, {""},
|
#line 68 "gethttpheader.gperf"
|
||||||
|
{"Content-Disposition", kHttpContentDisposition},
|
||||||
|
#line 43 "gethttpheader.gperf"
|
||||||
|
{"Keep-Alive", kHttpKeepAlive},
|
||||||
#line 63 "gethttpheader.gperf"
|
#line 63 "gethttpheader.gperf"
|
||||||
{"Cookie", kHttpCookie},
|
{"Cookie", kHttpCookie},
|
||||||
{""},
|
{""},
|
||||||
#line 38 "gethttpheader.gperf"
|
#line 38 "gethttpheader.gperf"
|
||||||
{"If-Match", kHttpIfMatch},
|
{"If-Match", kHttpIfMatch},
|
||||||
{""}, {""},
|
{""}, {""},
|
||||||
#line 30 "gethttpheader.gperf"
|
#line 70 "gethttpheader.gperf"
|
||||||
{"Content-Md5", kHttpContentMd5},
|
{"Origin", kHttpOrigin},
|
||||||
{""}, {""}, {""},
|
{""}, {""}, {""},
|
||||||
#line 16 "gethttpheader.gperf"
|
#line 16 "gethttpheader.gperf"
|
||||||
{"Accept-Encoding", kHttpAcceptEncoding},
|
{"Accept-Encoding", kHttpAcceptEncoding},
|
||||||
{""},
|
#line 30 "gethttpheader.gperf"
|
||||||
|
{"Content-Md5", kHttpContentMd5},
|
||||||
#line 39 "gethttpheader.gperf"
|
#line 39 "gethttpheader.gperf"
|
||||||
{"If-Modified-Since", kHttpIfModifiedSince},
|
{"If-Modified-Since", kHttpIfModifiedSince},
|
||||||
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
|
{""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
|
||||||
{""}, {""},
|
{""}, {""},
|
||||||
#line 42 "gethttpheader.gperf"
|
#line 42 "gethttpheader.gperf"
|
||||||
{"If-Unmodified-Since", kHttpIfUnmodifiedSince}
|
{"If-Unmodified-Since", kHttpIfUnmodifiedSince},
|
||||||
|
{""}, {""}, {""}, {""}, {""}, {""}, {""},
|
||||||
|
#line 35 "gethttpheader.gperf"
|
||||||
|
{"Expires", kHttpExpires}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
|
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
|
||||||
|
|
142
net/http/gethttpheadername.c
Normal file
142
net/http/gethttpheadername.c
Normal file
|
@ -0,0 +1,142 @@
|
||||||
|
/*-*- 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/http.h"
|
||||||
|
|
||||||
|
const char *GetHttpHeaderName(int h) {
|
||||||
|
switch (h) {
|
||||||
|
case kHttpAccept:
|
||||||
|
return "Accept";
|
||||||
|
case kHttpAcceptCharset:
|
||||||
|
return "Accept-Charset";
|
||||||
|
case kHttpAcceptEncoding:
|
||||||
|
return "Accept-Encoding";
|
||||||
|
case kHttpAcceptLanguage:
|
||||||
|
return "Accept-Language";
|
||||||
|
case kHttpAge:
|
||||||
|
return "Age";
|
||||||
|
case kHttpAllow:
|
||||||
|
return "Allow";
|
||||||
|
case kHttpAuthorization:
|
||||||
|
return "Authorization";
|
||||||
|
case kHttpCacheControl:
|
||||||
|
return "Cache-Control";
|
||||||
|
case kHttpChunked:
|
||||||
|
return "Chunked";
|
||||||
|
case kHttpClose:
|
||||||
|
return "Close";
|
||||||
|
case kHttpConnection:
|
||||||
|
return "Connection";
|
||||||
|
case kHttpContentBase:
|
||||||
|
return "Content-Base";
|
||||||
|
case kHttpContentEncoding:
|
||||||
|
return "Content-Encoding";
|
||||||
|
case kHttpContentLanguage:
|
||||||
|
return "Content-Language";
|
||||||
|
case kHttpContentLength:
|
||||||
|
return "Content-Length";
|
||||||
|
case kHttpContentLocation:
|
||||||
|
return "Content-Location";
|
||||||
|
case kHttpContentMd5:
|
||||||
|
return "Content-Md5";
|
||||||
|
case kHttpContentRange:
|
||||||
|
return "Content-Range";
|
||||||
|
case kHttpContentType:
|
||||||
|
return "Content-Type";
|
||||||
|
case kHttpDate:
|
||||||
|
return "Date";
|
||||||
|
case kHttpEtag:
|
||||||
|
return "ETag";
|
||||||
|
case kHttpExpires:
|
||||||
|
return "Expires";
|
||||||
|
case kHttpFrom:
|
||||||
|
return "From";
|
||||||
|
case kHttpHost:
|
||||||
|
return "Host";
|
||||||
|
case kHttpIfMatch:
|
||||||
|
return "If-Match";
|
||||||
|
case kHttpIfModifiedSince:
|
||||||
|
return "If-Modified-Since";
|
||||||
|
case kHttpIfNoneMatch:
|
||||||
|
return "If-None-Match";
|
||||||
|
case kHttpIfRange:
|
||||||
|
return "If-Range";
|
||||||
|
case kHttpIfUnmodifiedSince:
|
||||||
|
return "If-Unmodified-Since";
|
||||||
|
case kHttpKeepAlive:
|
||||||
|
return "Keep-Alive";
|
||||||
|
case kHttpMaxForwards:
|
||||||
|
return "Max-Forwards";
|
||||||
|
case kHttpPragma:
|
||||||
|
return "Pragma";
|
||||||
|
case kHttpProxyAuthenticate:
|
||||||
|
return "Proxy-Authenticate";
|
||||||
|
case kHttpProxyAuthorization:
|
||||||
|
return "Proxy-Authorization";
|
||||||
|
case kHttpProxyConnection:
|
||||||
|
return "Proxy-Connection";
|
||||||
|
case kHttpRange:
|
||||||
|
return "Range";
|
||||||
|
case kHttpReferer:
|
||||||
|
return "Referer";
|
||||||
|
case kHttpTransferEncoding:
|
||||||
|
return "Transfer-Encoding";
|
||||||
|
case kHttpUpgrade:
|
||||||
|
return "Upgrade";
|
||||||
|
case kHttpUserAgent:
|
||||||
|
return "User-Agent";
|
||||||
|
case kHttpVia:
|
||||||
|
return "Via";
|
||||||
|
case kHttpLocation:
|
||||||
|
return "Location";
|
||||||
|
case kHttpPublic:
|
||||||
|
return "Public";
|
||||||
|
case kHttpRetryAfter:
|
||||||
|
return "Retry-After";
|
||||||
|
case kHttpServer:
|
||||||
|
return "Server";
|
||||||
|
case kHttpVary:
|
||||||
|
return "Vary";
|
||||||
|
case kHttpWarning:
|
||||||
|
return "Warning";
|
||||||
|
case kHttpWwwAuthenticate:
|
||||||
|
return "WWW-Authenticate";
|
||||||
|
case kHttpLastModified:
|
||||||
|
return "Last-Modified";
|
||||||
|
case kHttpCookie:
|
||||||
|
return "Cookie";
|
||||||
|
case kHttpTrailer:
|
||||||
|
return "Trailer";
|
||||||
|
case kHttpTe:
|
||||||
|
return "TE";
|
||||||
|
case kHttpDnt:
|
||||||
|
return "DNT";
|
||||||
|
case kHttpExpect:
|
||||||
|
return "Expect";
|
||||||
|
case kHttpContentDisposition:
|
||||||
|
return "Content-Disposition";
|
||||||
|
case kHttpContentDescription:
|
||||||
|
return "Content-Description";
|
||||||
|
case kHttpOrigin:
|
||||||
|
return "Origin";
|
||||||
|
case kHttpUpgradeInsecureRequests:
|
||||||
|
return "Upgrade-Insecure-Requests";
|
||||||
|
default:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
126
net/http/http.h
126
net/http/http.h
|
@ -21,61 +21,65 @@
|
||||||
#define kHttpReport 15
|
#define kHttpReport 15
|
||||||
#define kHttpUnlock 16
|
#define kHttpUnlock 16
|
||||||
|
|
||||||
#define kHttpAccept 0
|
#define kHttpAccept 0
|
||||||
#define kHttpAcceptCharset 1
|
#define kHttpAcceptCharset 1
|
||||||
#define kHttpAcceptEncoding 2
|
#define kHttpAcceptEncoding 2
|
||||||
#define kHttpAcceptLanguage 3
|
#define kHttpAcceptLanguage 3
|
||||||
#define kHttpAge 4
|
#define kHttpAge 4
|
||||||
#define kHttpAllow 5
|
#define kHttpAllow 5
|
||||||
#define kHttpAuthorization 6
|
#define kHttpAuthorization 6
|
||||||
#define kHttpCacheControl 7
|
#define kHttpCacheControl 7
|
||||||
#define kHttpChunked 8
|
#define kHttpChunked 8
|
||||||
#define kHttpClose 9
|
#define kHttpClose 9
|
||||||
#define kHttpConnection 10
|
#define kHttpConnection 10
|
||||||
#define kHttpContentBase 11
|
#define kHttpContentBase 11
|
||||||
#define kHttpContentEncoding 12
|
#define kHttpContentEncoding 12
|
||||||
#define kHttpContentLanguage 13
|
#define kHttpContentLanguage 13
|
||||||
#define kHttpContentLength 14
|
#define kHttpContentLength 14
|
||||||
#define kHttpContentLocation 15
|
#define kHttpContentLocation 15
|
||||||
#define kHttpContentMd5 16
|
#define kHttpContentMd5 16
|
||||||
#define kHttpContentRange 17
|
#define kHttpContentRange 17
|
||||||
#define kHttpContentType 18
|
#define kHttpContentType 18
|
||||||
#define kHttpDate 19
|
#define kHttpDate 19
|
||||||
#define kHttpEtag 20
|
#define kHttpEtag 20
|
||||||
#define kHttpExpires 21
|
#define kHttpExpires 21
|
||||||
#define kHttpFrom 22
|
#define kHttpFrom 22
|
||||||
#define kHttpHost 23
|
#define kHttpHost 23
|
||||||
#define kHttpIfMatch 24
|
#define kHttpIfMatch 24
|
||||||
#define kHttpIfModifiedSince 25
|
#define kHttpIfModifiedSince 25
|
||||||
#define kHttpIfNoneMatch 26
|
#define kHttpIfNoneMatch 26
|
||||||
#define kHttpIfRange 27
|
#define kHttpIfRange 27
|
||||||
#define kHttpIfUnmodifiedSince 28
|
#define kHttpIfUnmodifiedSince 28
|
||||||
#define kHttpKeepAlive 29
|
#define kHttpKeepAlive 29
|
||||||
#define kHttpMaxForwards 30
|
#define kHttpMaxForwards 30
|
||||||
#define kHttpPragma 31
|
#define kHttpPragma 31
|
||||||
#define kHttpProxyAuthenticate 32
|
#define kHttpProxyAuthenticate 32
|
||||||
#define kHttpProxyAuthorization 33
|
#define kHttpProxyAuthorization 33
|
||||||
#define kHttpProxyConnection 34
|
#define kHttpProxyConnection 34
|
||||||
#define kHttpRange 35
|
#define kHttpRange 35
|
||||||
#define kHttpReferer 36
|
#define kHttpReferer 36
|
||||||
#define kHttpTransferEncoding 37
|
#define kHttpTransferEncoding 37
|
||||||
#define kHttpUpgrade 38
|
#define kHttpUpgrade 38
|
||||||
#define kHttpUserAgent 39
|
#define kHttpUserAgent 39
|
||||||
#define kHttpVia 40
|
#define kHttpVia 40
|
||||||
#define kHttpLocation 41
|
#define kHttpLocation 41
|
||||||
#define kHttpPublic 42
|
#define kHttpPublic 42
|
||||||
#define kHttpRetryAfter 43
|
#define kHttpRetryAfter 43
|
||||||
#define kHttpServer 44
|
#define kHttpServer 44
|
||||||
#define kHttpVary 45
|
#define kHttpVary 45
|
||||||
#define kHttpWarning 46
|
#define kHttpWarning 46
|
||||||
#define kHttpWwwAuthenticate 47
|
#define kHttpWwwAuthenticate 47
|
||||||
#define kHttpLastModified 48
|
#define kHttpLastModified 48
|
||||||
#define kHttpCookie 49
|
#define kHttpCookie 49
|
||||||
#define kHttpTrailer 50
|
#define kHttpTrailer 50
|
||||||
#define kHttpTe 51
|
#define kHttpTe 51
|
||||||
#define kHttpDnt 52
|
#define kHttpDnt 52
|
||||||
#define kHttpExpect 53
|
#define kHttpExpect 53
|
||||||
#define kHttpHeadersMax 54
|
#define kHttpContentDisposition 54
|
||||||
|
#define kHttpContentDescription 55
|
||||||
|
#define kHttpOrigin 56
|
||||||
|
#define kHttpUpgradeInsecureRequests 57
|
||||||
|
#define kHttpHeadersMax 58
|
||||||
|
|
||||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
COSMOPOLITAN_C_START_
|
COSMOPOLITAN_C_START_
|
||||||
|
@ -85,12 +89,20 @@ struct HttpRequestSlice {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct HttpRequest {
|
struct HttpRequest {
|
||||||
int i, t, a, h;
|
int i, t, a;
|
||||||
int method;
|
int method;
|
||||||
|
struct HttpRequestSlice k;
|
||||||
struct HttpRequestSlice uri;
|
struct HttpRequestSlice uri;
|
||||||
struct HttpRequestSlice version;
|
struct HttpRequestSlice version;
|
||||||
struct HttpRequestSlice scratch;
|
struct HttpRequestSlice scratch;
|
||||||
struct HttpRequestSlice headers[kHttpHeadersMax];
|
struct HttpRequestSlice headers[kHttpHeadersMax];
|
||||||
|
struct HttpRequestHeaders {
|
||||||
|
size_t n;
|
||||||
|
struct HttpRequestHeader {
|
||||||
|
struct HttpRequestSlice k;
|
||||||
|
struct HttpRequestSlice v;
|
||||||
|
} * p;
|
||||||
|
} xheaders;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern const char kHttpMethod[17][8];
|
extern const char kHttpMethod[17][8];
|
||||||
|
@ -98,6 +110,7 @@ extern const char kHttpMethod[17][8];
|
||||||
int GetHttpHeader(const char *, size_t);
|
int GetHttpHeader(const char *, size_t);
|
||||||
int GetHttpMethod(const char *, size_t);
|
int GetHttpMethod(const char *, size_t);
|
||||||
void InitHttpRequest(struct HttpRequest *);
|
void InitHttpRequest(struct HttpRequest *);
|
||||||
|
void DestroyHttpRequest(struct HttpRequest *);
|
||||||
int ParseHttpRequest(struct HttpRequest *, const char *, size_t);
|
int ParseHttpRequest(struct HttpRequest *, const char *, size_t);
|
||||||
int NegotiateHttpRequest(int, const char *, uint32_t *, char *, uint32_t *,
|
int NegotiateHttpRequest(int, const char *, uint32_t *, char *, uint32_t *,
|
||||||
uint32_t *, bool, long double);
|
uint32_t *, bool, long double);
|
||||||
|
@ -107,6 +120,7 @@ bool ParseHttpRange(const char *, size_t, long, long *, long *);
|
||||||
unsigned ParseHttpVersion(const char *, size_t);
|
unsigned ParseHttpVersion(const char *, size_t);
|
||||||
int64_t ParseHttpDateTime(const char *, size_t);
|
int64_t ParseHttpDateTime(const char *, size_t);
|
||||||
const char *GetHttpReason(int);
|
const char *GetHttpReason(int);
|
||||||
|
const char *GetHttpHeaderName(int);
|
||||||
|
|
||||||
COSMOPOLITAN_C_END_
|
COSMOPOLITAN_C_END_
|
||||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
|
|
|
@ -31,6 +31,7 @@ NET_HTTP_A_DIRECTDEPS = \
|
||||||
LIBC_FMT \
|
LIBC_FMT \
|
||||||
LIBC_INTRIN \
|
LIBC_INTRIN \
|
||||||
LIBC_LOG \
|
LIBC_LOG \
|
||||||
|
LIBC_MEM \
|
||||||
LIBC_NEXGEN32E \
|
LIBC_NEXGEN32E \
|
||||||
LIBC_RUNTIME \
|
LIBC_RUNTIME \
|
||||||
LIBC_SOCK \
|
LIBC_SOCK \
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "libc/alg/arraylist.internal.h"
|
#include "libc/alg/arraylist.internal.h"
|
||||||
#include "libc/limits.h"
|
#include "libc/limits.h"
|
||||||
#include "libc/macros.internal.h"
|
#include "libc/macros.internal.h"
|
||||||
|
#include "libc/mem/mem.h"
|
||||||
#include "libc/stdio/stdio.h"
|
#include "libc/stdio/stdio.h"
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
|
@ -37,11 +38,19 @@ void InitHttpRequest(struct HttpRequest *r) {
|
||||||
memset(r, 0, sizeof(*r));
|
memset(r, 0, sizeof(*r));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroys HTTP request parser.
|
||||||
|
*/
|
||||||
|
void DestroyHttpRequest(struct HttpRequest *r) {
|
||||||
|
free(r->xheaders.p);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses HTTP request.
|
* Parses HTTP request.
|
||||||
*/
|
*/
|
||||||
int ParseHttpRequest(struct HttpRequest *r, const char *p, size_t n) {
|
int ParseHttpRequest(struct HttpRequest *r, const char *p, size_t n) {
|
||||||
int c;
|
int c, h;
|
||||||
|
struct HttpRequestHeader *x;
|
||||||
for (n = MIN(n, LIMIT); r->i < n; ++r->i) {
|
for (n = MIN(n, LIMIT); r->i < n; ++r->i) {
|
||||||
c = p[r->i] & 0xff;
|
c = p[r->i] & 0xff;
|
||||||
switch (r->t) {
|
switch (r->t) {
|
||||||
|
@ -97,12 +106,12 @@ int ParseHttpRequest(struct HttpRequest *r, const char *p, size_t n) {
|
||||||
} else if (c == ' ' || c == '\t') {
|
} else if (c == ' ' || c == '\t') {
|
||||||
return ebadmsg(); /* RFC7230 § 3.2.4 */
|
return ebadmsg(); /* RFC7230 § 3.2.4 */
|
||||||
}
|
}
|
||||||
r->a = r->i;
|
r->k.a = r->i;
|
||||||
r->t = HKEY;
|
r->t = HKEY;
|
||||||
break;
|
break;
|
||||||
case HKEY:
|
case HKEY:
|
||||||
if (c == ':') {
|
if (c == ':') {
|
||||||
r->h = GetHttpHeader(p + r->a, r->i - r->a);
|
r->k.b = r->i;
|
||||||
r->t = HSEP;
|
r->t = HSEP;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -113,9 +122,16 @@ int ParseHttpRequest(struct HttpRequest *r, const char *p, size_t n) {
|
||||||
/* fallthrough */
|
/* fallthrough */
|
||||||
case HVAL:
|
case HVAL:
|
||||||
if (c == '\r' || c == '\n') {
|
if (c == '\r' || c == '\n') {
|
||||||
if (r->h != -1) {
|
if ((h = GetHttpHeader(p + r->k.a, r->k.b - r->k.a)) != -1) {
|
||||||
r->headers[r->h].a = r->a;
|
r->headers[h].a = r->a;
|
||||||
r->headers[r->h].b = r->i;
|
r->headers[h].b = r->i;
|
||||||
|
} else if ((x = realloc(r->xheaders.p, (r->xheaders.n + 1) *
|
||||||
|
sizeof(*r->xheaders.p)))) {
|
||||||
|
x[r->xheaders.n].k = r->k;
|
||||||
|
x[r->xheaders.n].v.a = r->a;
|
||||||
|
x[r->xheaders.n].v.b = r->i;
|
||||||
|
r->xheaders.p = x;
|
||||||
|
++r->xheaders.n;
|
||||||
}
|
}
|
||||||
r->t = c == '\r' ? CR1 : LF1;
|
r->t = c == '\r' ? CR1 : LF1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,8 @@ char *escapeparam(const char *s) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(escapeparam, test) {
|
TEST(escapeparam, test) {
|
||||||
EXPECT_STREQ("abc+%26%3C%3E%22%27%01%02", gc(escapeparam("abc &<>\"'\1\2")));
|
EXPECT_STREQ("abc%20%26%3C%3E%22%27%01%02",
|
||||||
|
gc(escapeparam("abc &<>\"'\1\2")));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(escapeparam, testLargeGrowth) {
|
TEST(escapeparam, testLargeGrowth) {
|
||||||
|
|
|
@ -41,19 +41,24 @@ static unsigned version(const char *m) {
|
||||||
return ParseHttpVersion(m + req->version.a, req->version.b - req->version.a);
|
return ParseHttpVersion(m + req->version.a, req->version.b - req->version.a);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ParseHttpRequest, testEmpty_tooShort) {
|
void SetUp(void) {
|
||||||
InitHttpRequest(req);
|
InitHttpRequest(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TearDown(void) {
|
||||||
|
DestroyHttpRequest(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ParseHttpRequest, testEmpty_tooShort) {
|
||||||
EXPECT_EQ(0, ParseHttpRequest(req, "", 0));
|
EXPECT_EQ(0, ParseHttpRequest(req, "", 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ParseHttpRequest, testTooShort) {
|
TEST(ParseHttpRequest, testTooShort) {
|
||||||
InitHttpRequest(req);
|
|
||||||
EXPECT_EQ(0, ParseHttpRequest(req, "\r\n", 2));
|
EXPECT_EQ(0, ParseHttpRequest(req, "\r\n", 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ParseHttpRequest, testNoHeaders) {
|
TEST(ParseHttpRequest, testNoHeaders) {
|
||||||
static const char m[] = "GET /foo HTTP/1.0\r\n\r\n";
|
static const char m[] = "GET /foo HTTP/1.0\r\n\r\n";
|
||||||
InitHttpRequest(req);
|
|
||||||
EXPECT_EQ(strlen(m), ParseHttpRequest(req, m, strlen(m)));
|
EXPECT_EQ(strlen(m), ParseHttpRequest(req, m, strlen(m)));
|
||||||
EXPECT_EQ(kHttpGet, req->method);
|
EXPECT_EQ(kHttpGet, req->method);
|
||||||
EXPECT_STREQ("/foo", gc(slice(m, req->uri)));
|
EXPECT_STREQ("/foo", gc(slice(m, req->uri)));
|
||||||
|
@ -66,7 +71,6 @@ POST /foo?bar%20hi HTTP/1.0\r\n\
|
||||||
Host: foo.example\r\n\
|
Host: foo.example\r\n\
|
||||||
Content-Length: 0\r\n\
|
Content-Length: 0\r\n\
|
||||||
\r\n";
|
\r\n";
|
||||||
InitHttpRequest(req);
|
|
||||||
EXPECT_EQ(strlen(m), ParseHttpRequest(req, m, strlen(m)));
|
EXPECT_EQ(strlen(m), ParseHttpRequest(req, m, strlen(m)));
|
||||||
EXPECT_EQ(kHttpPost, req->method);
|
EXPECT_EQ(kHttpPost, req->method);
|
||||||
EXPECT_STREQ("/foo?bar%20hi", gc(slice(m, req->uri)));
|
EXPECT_STREQ("/foo?bar%20hi", gc(slice(m, req->uri)));
|
||||||
|
@ -78,7 +82,6 @@ Content-Length: 0\r\n\
|
||||||
|
|
||||||
TEST(ParseHttpRequest, testHttp101) {
|
TEST(ParseHttpRequest, testHttp101) {
|
||||||
static const char m[] = "GET / HTTP/1.1\r\n\r\n";
|
static const char m[] = "GET / HTTP/1.1\r\n\r\n";
|
||||||
InitHttpRequest(req);
|
|
||||||
EXPECT_EQ(strlen(m), ParseHttpRequest(req, m, strlen(m)));
|
EXPECT_EQ(strlen(m), ParseHttpRequest(req, m, strlen(m)));
|
||||||
EXPECT_EQ(kHttpGet, req->method);
|
EXPECT_EQ(kHttpGet, req->method);
|
||||||
EXPECT_STREQ("/", gc(slice(m, req->uri)));
|
EXPECT_STREQ("/", gc(slice(m, req->uri)));
|
||||||
|
@ -88,7 +91,6 @@ TEST(ParseHttpRequest, testHttp101) {
|
||||||
|
|
||||||
TEST(ParseHttpRequest, testHttp100) {
|
TEST(ParseHttpRequest, testHttp100) {
|
||||||
static const char m[] = "GET / HTTP/1.0\r\n\r\n";
|
static const char m[] = "GET / HTTP/1.0\r\n\r\n";
|
||||||
InitHttpRequest(req);
|
|
||||||
EXPECT_EQ(strlen(m), ParseHttpRequest(req, m, strlen(m)));
|
EXPECT_EQ(strlen(m), ParseHttpRequest(req, m, strlen(m)));
|
||||||
EXPECT_EQ(kHttpGet, req->method);
|
EXPECT_EQ(kHttpGet, req->method);
|
||||||
EXPECT_STREQ("/", gc(slice(m, req->uri)));
|
EXPECT_STREQ("/", gc(slice(m, req->uri)));
|
||||||
|
@ -98,7 +100,6 @@ TEST(ParseHttpRequest, testHttp100) {
|
||||||
|
|
||||||
TEST(ParseHttpRequest, testHttp009) {
|
TEST(ParseHttpRequest, testHttp009) {
|
||||||
static const char m[] = "GET /\r\n\r\n";
|
static const char m[] = "GET /\r\n\r\n";
|
||||||
InitHttpRequest(req);
|
|
||||||
EXPECT_EQ(strlen(m), ParseHttpRequest(req, m, strlen(m)));
|
EXPECT_EQ(strlen(m), ParseHttpRequest(req, m, strlen(m)));
|
||||||
EXPECT_EQ(kHttpGet, req->method);
|
EXPECT_EQ(kHttpGet, req->method);
|
||||||
EXPECT_STREQ("/", gc(slice(m, req->uri)));
|
EXPECT_STREQ("/", gc(slice(m, req->uri)));
|
||||||
|
@ -112,7 +113,6 @@ TEST(ParseHttpRequest, testLeadingLineFeeds_areIgnored) {
|
||||||
GET /foo?bar%20hi HTTP/1.0\r\n\
|
GET /foo?bar%20hi HTTP/1.0\r\n\
|
||||||
User-Agent: hi\r\n\
|
User-Agent: hi\r\n\
|
||||||
\r\n";
|
\r\n";
|
||||||
InitHttpRequest(req);
|
|
||||||
EXPECT_EQ(strlen(m), ParseHttpRequest(req, m, strlen(m)));
|
EXPECT_EQ(strlen(m), ParseHttpRequest(req, m, strlen(m)));
|
||||||
EXPECT_STREQ("/foo?bar%20hi", gc(slice(m, req->uri)));
|
EXPECT_STREQ("/foo?bar%20hi", gc(slice(m, req->uri)));
|
||||||
}
|
}
|
||||||
|
@ -123,7 +123,6 @@ GET /foo?bar%20hi HTTP/1.0\r\n\
|
||||||
User-Agent: hi\r\n\
|
User-Agent: hi\r\n\
|
||||||
there\r\n\
|
there\r\n\
|
||||||
\r\n";
|
\r\n";
|
||||||
InitHttpRequest(req);
|
|
||||||
EXPECT_EQ(-1, ParseHttpRequest(req, m, strlen(m)));
|
EXPECT_EQ(-1, ParseHttpRequest(req, m, strlen(m)));
|
||||||
EXPECT_EQ(EBADMSG, errno);
|
EXPECT_EQ(EBADMSG, errno);
|
||||||
}
|
}
|
||||||
|
@ -134,7 +133,6 @@ GET /foo?bar%20hi HTTP/1.0\r\n\
|
||||||
User-Agent: hi\r\n\
|
User-Agent: hi\r\n\
|
||||||
: hi\r\n\
|
: hi\r\n\
|
||||||
\r\n";
|
\r\n";
|
||||||
InitHttpRequest(req);
|
|
||||||
EXPECT_EQ(-1, ParseHttpRequest(req, m, strlen(m)));
|
EXPECT_EQ(-1, ParseHttpRequest(req, m, strlen(m)));
|
||||||
EXPECT_EQ(EBADMSG, errno);
|
EXPECT_EQ(EBADMSG, errno);
|
||||||
}
|
}
|
||||||
|
@ -146,7 +144,6 @@ Host: foo.example\n\
|
||||||
Content-Length: 0\n\
|
Content-Length: 0\n\
|
||||||
\n\
|
\n\
|
||||||
\n";
|
\n";
|
||||||
InitHttpRequest(req);
|
|
||||||
EXPECT_EQ(strlen(m) - 1, ParseHttpRequest(req, m, strlen(m)));
|
EXPECT_EQ(strlen(m) - 1, ParseHttpRequest(req, m, strlen(m)));
|
||||||
EXPECT_EQ(kHttpPost, req->method);
|
EXPECT_EQ(kHttpPost, req->method);
|
||||||
EXPECT_STREQ("/foo?bar%20hi", gc(slice(m, req->uri)));
|
EXPECT_STREQ("/foo?bar%20hi", gc(slice(m, req->uri)));
|
||||||
|
@ -155,3 +152,37 @@ Content-Length: 0\n\
|
||||||
EXPECT_STREQ("0", gc(slice(m, req->headers[kHttpContentLength])));
|
EXPECT_STREQ("0", gc(slice(m, req->headers[kHttpContentLength])));
|
||||||
EXPECT_STREQ("", gc(slice(m, req->headers[kHttpEtag])));
|
EXPECT_STREQ("", gc(slice(m, req->headers[kHttpEtag])));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(ParseHttpRequest, testChromeMessage) {
|
||||||
|
static const char m[] = "\
|
||||||
|
GET /tool/net/redbean.png HTTP/1.1\r\n\
|
||||||
|
Host: 10.10.10.124:8080\r\n\
|
||||||
|
Connection: keep-alive\r\n\
|
||||||
|
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36\r\n\
|
||||||
|
DNT: \t1\r\n\
|
||||||
|
Accept: image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8\r\n\
|
||||||
|
Referer: http://10.10.10.124:8080/\r\n\
|
||||||
|
Accept-Encoding: gzip, deflate\r\n\
|
||||||
|
Accept-Language: en-US,en;q=0.9\r\n\
|
||||||
|
\r\n";
|
||||||
|
EXPECT_EQ(strlen(m), ParseHttpRequest(req, m, strlen(m)));
|
||||||
|
EXPECT_EQ(kHttpGet, req->method);
|
||||||
|
EXPECT_STREQ("/tool/net/redbean.png", gc(slice(m, req->uri)));
|
||||||
|
EXPECT_STREQ("HTTP/1.1", gc(slice(m, req->version)));
|
||||||
|
EXPECT_STREQ("10.10.10.124:8080", gc(slice(m, req->headers[kHttpHost])));
|
||||||
|
EXPECT_STREQ("1", gc(slice(m, req->headers[kHttpDnt])));
|
||||||
|
EXPECT_STREQ("", gc(slice(m, req->headers[kHttpExpect])));
|
||||||
|
EXPECT_STREQ("", gc(slice(m, req->headers[kHttpContentLength])));
|
||||||
|
EXPECT_STREQ("", gc(slice(m, req->headers[kHttpExpect])));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(ParseHttpRequest, testExtendedHeaders) {
|
||||||
|
static const char m[] = "\
|
||||||
|
GET /foo?bar%20hi HTTP/1.0\r\n\
|
||||||
|
X-User-Agent: hi\r\n\
|
||||||
|
\r\n";
|
||||||
|
EXPECT_EQ(strlen(m), ParseHttpRequest(req, m, strlen(m)));
|
||||||
|
ASSERT_EQ(1, req->xheaders.n);
|
||||||
|
EXPECT_STREQ("X-User-Agent", gc(slice(m, req->xheaders.p[0].k)));
|
||||||
|
EXPECT_STREQ("hi", gc(slice(m, req->xheaders.p[0].v)));
|
||||||
|
}
|
||||||
|
|
|
@ -67,6 +67,9 @@ o/$(MODE)/tool/net/redbean.com.dbg: \
|
||||||
o/$(MODE)/tool/net/redbean.css.zip.o \
|
o/$(MODE)/tool/net/redbean.css.zip.o \
|
||||||
o/$(MODE)/tool/net/redbean.html.zip.o \
|
o/$(MODE)/tool/net/redbean.html.zip.o \
|
||||||
o/$(MODE)/tool/net/redbean.lua.zip.o \
|
o/$(MODE)/tool/net/redbean.lua.zip.o \
|
||||||
|
o/$(MODE)/tool/net/redbean-form.lua.zip.o \
|
||||||
|
o/$(MODE)/tool/net/.init.lua.zip.o \
|
||||||
|
o/$(MODE)/tool/net/.reload.lua.zip.o \
|
||||||
o/$(MODE)/tool/net/net.pkg \
|
o/$(MODE)/tool/net/net.pkg \
|
||||||
$(CRT) \
|
$(CRT) \
|
||||||
$(APE)
|
$(APE)
|
||||||
|
|
70
tool/net/redbean-form.lua
Normal file
70
tool/net/redbean-form.lua
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
-- redbean post request handler demo
|
||||||
|
|
||||||
|
local function main()
|
||||||
|
if GetMethod() ~= 'POST' then
|
||||||
|
ServeError(405)
|
||||||
|
SetHeader('Allow', 'POST')
|
||||||
|
return
|
||||||
|
end
|
||||||
|
SetStatus(200)
|
||||||
|
SetHeader('Content-Type', 'text/html; charset=utf-8')
|
||||||
|
Write('<!doctype html>\n')
|
||||||
|
Write('<title>redbean</title>\n')
|
||||||
|
Write('<h3>POST Request HTML Form Handler Demo</h3>\n')
|
||||||
|
|
||||||
|
Write('<p>')
|
||||||
|
firstname = GetParam('firstname')
|
||||||
|
lastname = GetParam('lastname')
|
||||||
|
if firstname and lastname then
|
||||||
|
Write('Hello ')
|
||||||
|
Write(EscapeHtml(firstname))
|
||||||
|
Write(' ')
|
||||||
|
Write(EscapeHtml(lastname))
|
||||||
|
Write('!<br>')
|
||||||
|
Write('Thank you for using redbean.')
|
||||||
|
end
|
||||||
|
|
||||||
|
Write('<dl>\n')
|
||||||
|
|
||||||
|
Write('<dt>Params\n')
|
||||||
|
Write('<dd>\n')
|
||||||
|
Write('<dl>\n')
|
||||||
|
params = GetParams()
|
||||||
|
for i = 1,#params do
|
||||||
|
Write('<dt>')
|
||||||
|
Write(EscapeHtml(params[i][1]))
|
||||||
|
Write('\n')
|
||||||
|
if params[i][2] then
|
||||||
|
Write('<dd>')
|
||||||
|
Write(EscapeHtml(params[i][2]))
|
||||||
|
Write('\n')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
Write('</dl>\n')
|
||||||
|
|
||||||
|
Write('<dt>Headers\n')
|
||||||
|
Write('<dd>\n')
|
||||||
|
Write('<dl>\n')
|
||||||
|
for k,v in pairs(GetHeaders()) do
|
||||||
|
Write('<dt>')
|
||||||
|
Write(EscapeHtml(k))
|
||||||
|
Write('\n')
|
||||||
|
Write('<dd>')
|
||||||
|
Write(EscapeHtml(v))
|
||||||
|
Write('\n')
|
||||||
|
end
|
||||||
|
Write('</dl>\n')
|
||||||
|
|
||||||
|
Write('<dt>Payload\n')
|
||||||
|
Write('<dd><p>')
|
||||||
|
Write(EscapeHtml(GetPayload()))
|
||||||
|
Write('\n')
|
||||||
|
|
||||||
|
Write('</dl>\n')
|
||||||
|
|
||||||
|
Write('<p>')
|
||||||
|
Write('<a href="/tool/net/redbean.lua">Click here</a> ')
|
||||||
|
Write('to return to the previous page.\n')
|
||||||
|
end
|
||||||
|
|
||||||
|
main()
|
File diff suppressed because it is too large
Load diff
|
@ -1,8 +1,8 @@
|
||||||
<!doctype html>
|
<!doctype html>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>redbean</title>
|
<title>redbean</title>
|
||||||
<link rel="stylesheet" href="redbean.css">
|
<link rel="stylesheet" href="/tool/net/redbean.css">
|
||||||
<img src="redbean.png" class="logo" width="84" height="84">
|
<img src="/tool/net/redbean.png" class="logo" width="84" height="84">
|
||||||
|
|
||||||
<h2>
|
<h2>
|
||||||
<big>redbean</big><br>
|
<big>redbean</big><br>
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
-- redbean lua server page demo
|
-- redbean lua server page demo
|
||||||
|
|
||||||
local function main()
|
local function main()
|
||||||
-- This check is optional.
|
-- This check is pedantic but might be good to have.
|
||||||
-- We do this by default if you don't call GetMethod().
|
|
||||||
if GetMethod() ~= 'GET' and GetMethod() ~= 'HEAD' then
|
if GetMethod() ~= 'GET' and GetMethod() ~= 'HEAD' then
|
||||||
ServeError(405)
|
ServeError(405)
|
||||||
SetHeader('Allow', 'GET, HEAD')
|
SetHeader('Allow', 'GET, HEAD')
|
||||||
|
@ -40,9 +39,35 @@ local function main()
|
||||||
Write('<p>\n')
|
Write('<p>\n')
|
||||||
Write('<em>none</em><br>\n')
|
Write('<em>none</em><br>\n')
|
||||||
Write('ProTip: Try <a href="')
|
Write('ProTip: Try <a href="')
|
||||||
Write(EscapeHtml(EscapePath(GetPath()) .. '?x=hi+there&y&z&z=' .. EscapeParam('&')))
|
Write(EscapeHtml(EscapePath(GetPath()) .. '?x=hi%20there&y&z&z=' .. EscapeParam('&')))
|
||||||
Write('">clicking here</a>!\n')
|
Write('">clicking here</a>!\n')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Access redbean command line arguments.
|
||||||
|
-- These are the ones that come *after* the redbean server arguments.
|
||||||
|
Write('<h3>command line arguments</h3>\n')
|
||||||
|
if #argv > 0 then
|
||||||
|
Write('<ul>\n')
|
||||||
|
for i = 1,#argv do
|
||||||
|
Write('<li>')
|
||||||
|
Write(EscapeHtml(argv[i]))
|
||||||
|
Write('\n')
|
||||||
|
end
|
||||||
|
Write('</ul>\n')
|
||||||
|
else
|
||||||
|
Write('<p><em>none</em>\n')
|
||||||
|
end
|
||||||
|
|
||||||
|
Write('<h3>post request html form demo</h3>\n')
|
||||||
|
Write('<form action="/tool/net/redbean-form.lua" method="post">\n')
|
||||||
|
Write('<input type="text" id="firstname" name="firstname">\n')
|
||||||
|
Write('<label for="firstname">first name</label>\n')
|
||||||
|
Write('<br>\n')
|
||||||
|
Write('<input type="text" id="lastname" name="lastname">\n')
|
||||||
|
Write('<label for="lastname">last name</label>\n')
|
||||||
|
Write('<br>\n')
|
||||||
|
Write('<input type="submit" value="Submit">\n')
|
||||||
|
Write('</form>\n')
|
||||||
end
|
end
|
||||||
|
|
||||||
main()
|
main()
|
||||||
|
|
Loading…
Add table
Reference in a new issue