|
|
|
@ -129,6 +129,43 @@ httpRequestSkip(char ** data) |
|
|
|
for (; 0 != **data && ! isalpha(**data); (*data)++); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* SDBM hashing algorithm: |
|
|
|
* |
|
|
|
* this algorithm was created for sdbm (a public-domain reimplementation of |
|
|
|
* ndbm) database library. it was found to do well in scrambling bits, |
|
|
|
* causing better distribution of the keys and fewer splits. it also happens |
|
|
|
* to be a good general hashing function with good distribution. the actual |
|
|
|
* function is hash(i) = hash(i - 1) * 65599 + str[i]; what is included below |
|
|
|
* is the faster version used in gawk. [there is even a faster, duff-device |
|
|
|
* version] the magic constant 65599 was picked out of thin air while |
|
|
|
* experimenting with different constants, and turns out to be a prime. this |
|
|
|
* is one of the algorithms used in berkeley db (see sleepycat) and elsewhere. |
|
|
|
*/ |
|
|
|
static |
|
|
|
inline |
|
|
|
unsigned long |
|
|
|
sdbm(unsigned char * str) |
|
|
|
{ |
|
|
|
unsigned long hash = 0; |
|
|
|
int c; |
|
|
|
|
|
|
|
while ((c = *str++)) |
|
|
|
hash = c + (hash << 6) + (hash << 16) - hash; |
|
|
|
|
|
|
|
return hash; |
|
|
|
} |
|
|
|
|
|
|
|
static |
|
|
|
inline |
|
|
|
int |
|
|
|
comp (const void * _a, const void * _b) |
|
|
|
{ |
|
|
|
const struct HttpRequestHeader * a = _a; |
|
|
|
const struct HttpRequestHeader * b = _b; |
|
|
|
return (a->hash < b->hash)? -1 : (a->hash > b->hash)? 1 : 0; |
|
|
|
} |
|
|
|
|
|
|
|
static |
|
|
|
void |
|
|
|
httpRequestParserParse(HttpRequestParser this) |
|
|
|
@ -207,21 +244,43 @@ httpRequestParserParse(HttpRequestParser this) |
|
|
|
*delim = 0; |
|
|
|
(request->header)[header_idx].name = malloc(strlen(line) + 1); |
|
|
|
strcpy((request->header)[header_idx].name, line); |
|
|
|
(request->header)[header_idx].hash = sdbm((unsigned char *)line); |
|
|
|
|
|
|
|
line = delim + 1; |
|
|
|
for (; *line == ' ' && *line != 0; line++); |
|
|
|
|
|
|
|
(request->header)[header_idx].value = malloc(strlen(line) + 1); |
|
|
|
strcpy((request->header)[header_idx].value, line); |
|
|
|
|
|
|
|
header_idx++; |
|
|
|
request->nheader++; |
|
|
|
} |
|
|
|
|
|
|
|
header_idx++; |
|
|
|
break; |
|
|
|
|
|
|
|
case HTTP_REQUEST_HEADERS_DONE: |
|
|
|
/** |
|
|
|
* @TODO: here comes the body handling |
|
|
|
*/ |
|
|
|
qsort( |
|
|
|
request->header, |
|
|
|
request->nheader, |
|
|
|
sizeof(struct HttpRequestHeader), |
|
|
|
comp); |
|
|
|
|
|
|
|
{ |
|
|
|
char * bodylen; |
|
|
|
|
|
|
|
bodylen = httpRequestHeaderGet(request, "Content-Length"); |
|
|
|
|
|
|
|
if (NULL != bodylen) { |
|
|
|
request->nbody = atoi(bodylen); |
|
|
|
request->body = calloc(1, request->nbody + 1); |
|
|
|
memcpy(request->body, data, request->nbody); |
|
|
|
data += request->nbody; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
this->state = HTTP_REQUEST_DONE; |
|
|
|
break; |
|
|
|
|
|
|
|
|