#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <arpa/inet.h>
#include "../public/nsapi.h"
#include "../util/pool.h"
#include "../util/pblock.h"
#include "../util/io.h"
#include "../util/util.h"
#include "httprequest.h"
#include "config.h"
#include "vserver.h"
#include "event.h"
#include "httplistener.h"
#include "func.h"
#include "error.h"
void http_request_init(HTTPRequest *req) {
memset(req,
0,
sizeof(HTTPRequest));
HeaderArray *hd = malloc(
sizeof(HeaderArray));
hd->next =
NULL;
hd->len =
0;
hd->headers = calloc(
16,
sizeof(Header));
hd->alloc =
16;
req->headers = hd;
req->req_start = time(
NULL);
}
void http_request_cleanup(HTTPRequest *req) {
header_array_free(req->headers);
free(req);
}
sstr_t http_request_get_abspath(HTTPRequest *req) {
sstr_t uri = req->uri;
int i =
0;
if(uri.ptr[
0] ==
'/') {
return uri;
}
else if(sstrprefix(uri,
S(
"http://"))) {
i =
7;
}
else if(sstrprefix(uri,
S(
"https://"))) {
i =
8;
}
else if(!sstrcmp(uri,
S(
"*"))) {
return uri;
}
for(;i<uri.length;i++) {
if(uri.ptr[i] ==
'/') {
return sstrsubs(uri, i);
}
}
return S(
"/");
}
int handle_request(HTTPRequest *request,
threadpool_t *thrpool, EventHandler *ev) {
pool_handle_t *pool = pool_create();
NSAPISession *sn = pool_malloc(pool,
sizeof(NSAPISession));
if(sn ==
NULL) {
}
ZERO(sn,
sizeof(NSAPISession));
NSAPIRequest *rq = pool_malloc(pool,
sizeof(NSAPIRequest));
if(rq ==
NULL) {
}
ZERO(rq,
sizeof(NSAPIRequest));
rq->rq.req_start = request->req_start;
rq->phase = NSAPIAuthTrans;
sn->connection = request->connection;
sn->netbuf = request->netbuf;
sn->sn.pool = pool;
SessionHandler *sh = request->connection->session_handler;
WSBool ssl;
IOStream *io = sh->create_iostream(sh, request->connection, pool, &ssl);
sn->sn.csd = httpstream_new(pool, io);
sn->sn.ssl = ssl;
sn->sn.client = pblock_create_pool(sn->sn.pool,
8);
sn->sn.next =
NULL;
sn->sn.fill =
1;
sn->sn.subject =
NULL;
if(!ev) {
ev = ev_instance(get_default_event_handler());
}
sn->sn.ev = ev;
sn->config = request->connection->listener->cfg;
char ip_str[
INET_ADDRSTRLEN];
if(inet_ntop(
AF_INET,
&request->connection->address.sin_addr,
ip_str,
INET_ADDRSTRLEN) !=
NULL)
{
pblock_kvinsert(pb_key_ip, ip_str,
INET_ADDRSTRLEN, sn->sn.client);
}
if(request_initialize(pool, request, rq) !=
0) {
log_ereport(
LOG_FAILURE,
"Cannot initialize request structure");
pool_destroy(pool);
return 1;
}
rq->vs = request->connection->listener->default_vs.vs;
sstr_t clfreq = request->request_line;
while(clfreq.length >
0 && clfreq.ptr[clfreq.length -
1] <
33) {
clfreq.length--;
}
pblock_kvinsert(
pb_key_clf_request,
clfreq.ptr,
clfreq.length,
rq->rq.reqpb);
pblock_kvinsert(
pb_key_method,
request->method.ptr,
request->method.length,
rq->rq.reqpb);
pblock_kvinsert(
pb_key_protocol,
request->httpv.ptr,
request->httpv.length,
rq->rq.reqpb);
if(!sstrcmp(request->httpv,
S(
"HTTP/1.1"))) {
rq->rq.protv_num =
PROTOCOL_VERSION_HTTP11;
}
else if(!sstrcmp(request->httpv,
S(
"HTTP/1.0"))) {
rq->rq.protv_num =
PROTOCOL_VERSION_HTTP10;
}
else {
log_ereport(
LOG_FAILURE,
"invalid protocol version: %.*s",
(
int)request->httpv.length,
request->httpv.ptr);
pool_destroy(pool);
return 1;
}
sstr_t absPath = http_request_get_abspath(request);
if(!absPath.ptr) {
return 1;
}
else if(absPath.ptr[
0] ==
'*') {
return 1;
}
sstr_t query;
query.length =
0;
for(
int i=
0;i<request->uri.length;i++) {
if(request->uri.ptr[i] ==
'?') {
if(absPath.length > i +
2) {
query.length = absPath.length - i -
1;
query.ptr = absPath.ptr + i +
1;
}
absPath.length = i;
pblock_kvinsert(
pb_key_query,
query.ptr,
query.length,
rq->rq.reqpb);
break;
}
}
sstr_t orig_path = absPath;
absPath.ptr = util_canonicalize_uri(
pool,
absPath.ptr,
absPath.length,
(
int*)&absPath.length);
if(!absPath.ptr) {
log_ereport(
LOG_WARN,
"invalid request path: {%.*s}",
(
int)orig_path.length,
orig_path.ptr);
pool_destroy(pool);
return 1;
}
if(util_uri_unescape_strict(absPath.ptr)) {
pblock_kvinsert(
pb_key_uri,
absPath.ptr,
absPath.length,
rq->rq.reqpb);
}
else {
log_ereport(
LOG_WARN,
"uri unescape failed: {%.*s}",
(
int)absPath.length,
absPath.ptr);
pblock_kvinsert(pb_key_uri,
"/",
1, rq->rq.reqpb);
}
int hlen = request->headers->len;
HeaderArray *ha = request->headers;
for(
int i=
0;i<=hlen;i++) {
if(i == hlen) {
ha = ha->next;
if(ha ==
NULL) {
break;
}
i =
0;
hlen = ha->len;
}
Header header = ha->headers[i];
if(header.name.ptr[
0] <
90) {
header.name.ptr[
0] +=
32;
}
for(
int j=
0;j<header.name.length;j++) {
if(header.name.ptr[j] >
64 && header.name.ptr[j] <
97) {
header.name.ptr[j] +=
32;
}
}
pblock_nvlinsert(
header.name.ptr,
header.name.length,
header.value.ptr,
header.value.length,
rq->rq.headers);
}
char *hosthdr = pblock_findkeyval(pb_key_host, rq->rq.headers);
if(hosthdr) {
char *host = pool_strdup(pool, hosthdr);
char *portstr = strchr(host,
':');
if(portstr) {
*portstr =
'\0';
}
rq->host = host;
}
else {
rq->host =
NULL;
}
rq->port = request->connection->listener->port;
if(rq->host) {
VirtualServer *vs = ucx_map_cstr_get(sn->config->host_vs, rq->host);
if(vs) {
rq->vs = vs;
}
else {
log_ereport(
LOG_VERBOSE,
"Unkown host ''%s'': using default virtual server",
rq->host);
}
}
rq->rq.rq_attr.keep_alive = (rq->rq.protv_num >=
PROTOCOL_VERSION_HTTP11);
char *conn_str = pblock_findkeyval(pb_key_connection, rq->rq.headers);
if(conn_str) {
if(!strcasecmp(conn_str,
"keep-alive")) {
rq->rq.rq_attr.keep_alive =
1;
}
else if(!strcasecmp(conn_str,
"close")) {
rq->rq.rq_attr.keep_alive =
0;
}
}
char *ctlen_str = pblock_findkeyval(pb_key_content_length, rq->rq.headers);
if(ctlen_str) {
int ctlen = atoi(ctlen_str);
netbuf *nb = request->netbuf;
HttpStream *net_io = (HttpStream*)httpstream_new(pool, io);
net_io->max_read = ctlen;
sn->sn.inbuf = pool_malloc(pool,
sizeof(netbuf));
sn->sn.inbuf->sd = net_io;
sn->sn.inbuf->pos =
0;
int cur_input_len = nb->cursize - nb->pos;
if(cur_input_len >= ctlen) {
sn->sn.inbuf->maxsize = ctlen;
sn->sn.inbuf->cursize = ctlen;
sn->sn.inbuf->inbuf = nb->inbuf + nb->pos;
}
else {
sn->sn.inbuf->maxsize = (ctlen >
2048) ? (
2048) : (ctlen);
sn->sn.inbuf->inbuf = pool_malloc(pool, sn->sn.inbuf->maxsize);
if(cur_input_len >
0) {
memcpy(sn->sn.inbuf->inbuf, nb->inbuf+nb->pos, cur_input_len);
}
sn->sn.inbuf->cursize = cur_input_len;
}
}
else {
sn->sn.inbuf =
NULL;
}
threadpool_t *lstp = request->connection->listener->threadpool;
sn->defaultpool = lstp;
if(lstp == thrpool) {
sn->currentpool = thrpool;
nsapi_handle_request(sn, rq);
}
else {
nsapi_change_threadpool(sn, rq, lstp);
}
return 0;
}
void header_add(HeaderArray *hd,
sstr_t name,
sstr_t value) {
while(hd->len >= hd->alloc) {
if(hd->next ==
NULL) {
HeaderArray *block = malloc(
sizeof(HeaderArray));
block->next =
NULL;
block->len =
0;
block->headers = calloc(
16,
sizeof(Header));
block->alloc =
16;
hd->next = block;
}
hd = hd->next;
}
hd->headers[hd->len].name = name;
hd->headers[hd->len].value = value;
hd->len++;
}
void header_array_free(HeaderArray *hd) {
HeaderArray *next;
while(hd) {
next = hd->next;
free(hd->headers);
free(hd);
hd = next;
}
}
int nsapi_handle_request(NSAPISession *sn, NSAPIRequest *rq) {
int r =
REQ_NOACTION;
do {
switch(rq->phase) {
case NSAPIAuthTrans: {
r = nsapi_authtrans(sn, rq);
if(r !=
REQ_PROCEED) {
break;
}
rq->phase++;
nsapi_context_next_stage(&rq->context);
}
case NSAPINameTrans: {
r = nsapi_nametrans(sn, rq);
if(r !=
REQ_PROCEED) {
break;
}
rq->phase++;
nsapi_context_next_stage(&rq->context);
}
case NSAPIPathCheck: {
r = nsapi_pathcheck(sn, rq);
if(r !=
REQ_PROCEED) {
break;
}
rq->phase++;
nsapi_context_next_stage(&rq->context);
}
case NSAPIObjectType: {
r = nsapi_objecttype(sn, rq);
if(r !=
REQ_PROCEED) {
break;
}
rq->phase++;
nsapi_context_next_stage(&rq->context);
}
case NSAPIService: {
r = nsapi_service(sn, rq);
if(r !=
REQ_PROCEED) {
break;
}
rq->phase = NSAPIAddLog;
nsapi_context_next_stage(&rq->context);
}
case NSAPIAddLog: {
r = nsapi_addlog(sn, rq);
if(r ==
REQ_PROCESSING) {
break;
}
r =
REQ_PROCEED;
break;
}
default:
case REQ_FINISH: {
r =
REQ_PROCEED;
break;
}
case NSAPIError: {
r = nsapi_error(sn, rq);
if(r ==
REQ_PROCEED) {
r =
REQ_RESTART;
rq->phase = NSAPIAddLog;
nsapi_context_next_stage(&rq->context);
}
else {
r =
REQ_PROCEED;
break;
}
}
}
if(r ==
REQ_ABORTED) {
rq->phase = NSAPIError;
nsapi_context_next_stage(&rq->context);
r =
REQ_RESTART;
}
}
while (r ==
REQ_RESTART);
if(r !=
REQ_PROCESSING) {
r = nsapi_finish_request(sn, rq);
}
return r;
}
int nsapi_finish_request(NSAPISession *sn, NSAPIRequest *rq) {
if(rq->rq.rq_attr.keep_alive) {
SessionHandler *sh = sn->connection->session_handler;
sh->keep_alive(sh, sn->connection);
}
else {
connection_destroy(sn->connection);
cfg_unref(sn->config);
}
free(sn->netbuf->inbuf);
free(sn->netbuf);
pool_destroy(sn->sn.pool);
return 0;
}
int nsapi_authtrans(NSAPISession *sn, NSAPIRequest *rq) {
HTTPObjectConfig *objconf = rq->vs->objects;
httpd_object *obj = objconf->objects[
0];
dtable *dt = object_get_dtable(obj, NSAPIAuthTrans);
int ret = rq->context.last_req_code;
for(
int i=
NCX_DI(rq);i<dt->ndir;i++) {
if(ret ==
REQ_NOACTION) {
directive *d = dt->dirs[i];
ret = nsapi_exec(d, sn, rq);
}
if(ret !=
REQ_NOACTION) {
if(ret ==
REQ_PROCESSING) {
rq->context.dtable_index = i +
1;
}
return ret;
}
}
return REQ_PROCEED;
}
int nsapi_nametrans(NSAPISession *sn, NSAPIRequest *rq) {
HTTPObjectConfig *objconf = rq->vs->objects;
httpd_objset *objset = objset_create(sn->sn.pool);
rq->rq.os = objset;
objset_add_object(sn->sn.pool, objset, objconf->objects[
0]);
httpd_object *obj = objset->obj[
0];
dtable *dt = object_get_dtable(obj, NSAPINameTrans);
int ret = rq->context.last_req_code;
char *name =
NULL;
char *ppath =
NULL;
for(
int i=
NCX_DI(rq);i<dt->ndir;i++) {
if(ret ==
REQ_NOACTION) {
directive *d = dt->dirs[i];
ret = nsapi_exec(d, sn, rq);
}
name = pblock_findkeyval(pb_key_name, rq->rq.vars);
ppath = pblock_findkeyval(pb_key_ppath, rq->rq.vars);
if(add_objects(objconf, objset, sn, rq, name, ppath) ==
REQ_ABORTED) {
log_ereport(
LOG_FAILURE,
"add_objects failed");
return REQ_ABORTED;
}
if(ret !=
REQ_NOACTION) {
if(ret ==
REQ_PROCESSING) {
rq->context.dtable_index = i +
1;
}
else if(ret ==
REQ_PROCEED) {
char *pp = pblock_findkeyval(pb_key_ppath, rq->rq.vars);
pblock_kvinsert(pb_key_path, pp, strlen(pp), rq->rq.vars);
}
return ret;
}
}
if(ret ==
REQ_NOACTION && ppath ==
NULL) {
sstr_t docroot = rq->vs->document_root;
if(docroot.length <
1) {
log_ereport(
LOG_WARN,
"VirtualServer(%.*s) docroot too short",
(
int)rq->vs->name.length,
rq->vs->name.ptr);
return REQ_ABORTED;
}
sstr_t uri = sstr(pblock_findkeyval(pb_key_uri, rq->rq.reqpb));
request_set_path(docroot, uri, rq->rq.vars);
}
char *pp = pblock_findkeyval(pb_key_ppath, rq->rq.vars);
pblock_kvinsert(pb_key_path, pp, strlen(pp), rq->rq.vars);
return REQ_PROCEED;
}
int nsapi_pathcheck(NSAPISession *sn, NSAPIRequest *rq) {
httpd_objset *objset = rq->rq.os;
if(
NCX_OI(rq) == -
1) {
NCX_OI(rq) = objset->pos -
1;
}
int ret = rq->context.last_req_code;
for(
int i=
NCX_OI(rq);i>=
0;i--) {
httpd_object *obj = objset->obj[i];
dtable *dt = object_get_dtable(obj, NSAPIPathCheck);
for(
int j=
NCX_DI(rq);j<dt->ndir;j++) {
if(ret ==
REQ_NOACTION || ret ==
REQ_PROCEED) {
directive *d = dt->dirs[j];
ret = nsapi_exec(d, sn, rq);
}
else {
if(ret ==
REQ_PROCESSING) {
rq->context.objset_index = i;
rq->context.dtable_index = j +
1;
}
return ret;
}
}
}
return REQ_PROCEED;
}
int nsapi_objecttype(NSAPISession *sn, NSAPIRequest *rq) {
httpd_objset *objset = rq->rq.os;
if(
NCX_OI(rq) == -
1) {
NCX_OI(rq) = objset->pos -
1;
}
int ret = rq->context.last_req_code;
for(
int i=
NCX_OI(rq);i>=
0;i--) {
httpd_object *obj = objset->obj[i];
dtable *dt = object_get_dtable(obj, NSAPIObjectType);
for(
int j=
NCX_DI(rq);j<dt->ndir;j++) {
if(ret ==
REQ_NOACTION) {
directive *d = dt->dirs[j];
ret = nsapi_exec(d, sn, rq);
}
switch(ret) {
case REQ_PROCEED: {
char *type = pblock_findkeyval(
pb_key_content_type,
rq->rq.srvhdrs);
if(type ==
NULL) {
ret =
REQ_NOACTION;
break;
}
return ret;
}
case REQ_PROCESSING: {
rq->context.objset_index = i;
rq->context.dtable_index = j +
1;
return ret;
}
case REQ_NOACTION: {
break;
}
default: {
return ret;
}
}
}
}
sstr_t path = sstr(pblock_findkeyval(pb_key_ppath, rq->rq.vars));
sstr_t ct;
if(path.ptr[path.length -
1] ==
'/') {
ct = sstrn(
"internal/directory",
18);
}
else {
ct = sstrn(
"text/plain",
10);
}
pblock_kvinsert(pb_key_content_type, ct.ptr, ct.length, rq->rq.srvhdrs);
return REQ_PROCEED;
}
int nsapi_service(NSAPISession *sn, NSAPIRequest *rq) {
httpd_objset *objset = rq->rq.os;
if(
NCX_OI(rq) == -
1) {
NCX_OI(rq) = objset->pos -
1;
}
int ret = rq->context.last_req_code;
char *content_type =
NULL;
char *method =
NULL;
for(
int i=
NCX_OI(rq);i>=
0;i--) {
httpd_object *obj = objset->obj[i];
dtable *dt = object_get_dtable(obj, NSAPIService);
for(
int j=
NCX_DI(rq);j<dt->ndir;j++) {
if(ret ==
REQ_NOACTION) {
directive *d = dt->dirs[j];
char *dtp = pblock_findkeyval(pb_key_type, d->param);
if(dtp) {
if(!content_type) {
content_type = pblock_findkeyval(
pb_key_content_type,
rq->rq.srvhdrs);
}
if(!contenttype_match(sstr(dtp), sstr(content_type))) {
continue;
}
}
char *dmt = pblock_findkeyval(pb_key_method, d->param);
if(dmt) {
if(!method) {
method = pblock_findkeyval(pb_key_method, rq->rq.reqpb);
}
if(!method_match(dmt, method)) {
continue;
}
}
ret = nsapi_exec(d, sn, rq);
}
if(ret !=
REQ_NOACTION) {
if(ret ==
REQ_PROCEED) {
net_finish(sn->sn.csd);
}
else if(ret ==
REQ_PROCESSING) {
rq->context.objset_index = i;
rq->context.dtable_index = j +
1;
}
return ret;
}
}
}
return ret;
}
int nsapi_error(NSAPISession *sn, NSAPIRequest *rq) {
httpd_objset *objset = rq->rq.os;
if(
NCX_OI(rq) == -
1) {
NCX_OI(rq) = objset->pos -
1;
}
int ret = rq->context.last_req_code;
for(
int i=
NCX_OI(rq);i>=
0;i--) {
httpd_object *obj = objset->obj[i];
dtable *dt = object_get_dtable(obj, NSAPIError);
for(
int j=
NCX_DI(rq);j<dt->ndir;j++) {
if(ret ==
REQ_NOACTION) {
directive *d = dt->dirs[j];
char *status = pblock_findkeyval(pb_key_type, d->param);
if(status) {
int statuscode = atoi(status);
if(statuscode != rq->rq.status_num) {
continue;
}
}
ret = nsapi_exec(d, sn, rq);
}
if(ret ==
REQ_ABORTED) {
break;
}
if(ret !=
REQ_NOACTION) {
if(ret ==
REQ_PROCEED) {
net_finish(sn->sn.csd);
}
else if(ret ==
REQ_PROCESSING) {
rq->context.objset_index = i;
rq->context.dtable_index = j +
1;
}
return ret;
}
}
}
if(ret !=
REQ_PROCEED) {
nsapi_error_request((Session*)sn, (Request*)rq);
}
return ret;
}
int nsapi_addlog(NSAPISession *sn, NSAPIRequest *rq) {
httpd_objset *objset = rq->rq.os;
if(
NCX_OI(rq) == -
1) {
NCX_OI(rq) = objset->pos -
1;
}
int ret = rq->context.last_req_code;
for(
int i=
NCX_OI(rq);i>=
0;i--) {
httpd_object *obj = objset->obj[i];
dtable *dt = object_get_dtable(obj, NSAPIAddLog);
for(
int j=
NCX_DI(rq);j<dt->ndir;j++) {
if(ret ==
REQ_NOACTION) {
directive *d = dt->dirs[j];
ret = nsapi_exec(d, sn, rq);
}
if(ret !=
REQ_NOACTION) {
if(ret ==
REQ_PROCESSING) {
rq->context.objset_index = i;
rq->context.dtable_index = j +
1;
}
return ret;
}
}
}
return REQ_PROCEED;
}
struct _tpd_data {
NSAPISession *sn;
NSAPIRequest *rq;
directive *directive;
threadpool_t *threadpool;
};
int nsapi_exec(directive *d, NSAPISession *sn, NSAPIRequest *rq) {
if(d->cond) {
if(!condition_evaluate(d->cond, (Session*)sn, (Request*)rq)) {
return REQ_NOACTION;
}
}
char *poolname = pblock_findkeyval(pb_key_pool, d->param);
if(poolname) {
threadpool_t *pool = get_threadpool(sstr(poolname));
if(pool && pool != sn->currentpool) {
return nsapi_exec_tp(d, sn, rq, pool);
}
}
else if(sn->currentpool != sn->defaultpool) {
return nsapi_exec_tp(d, sn, rq, sn->defaultpool);
}
return SAF_EXEC(d->func, d->param, (Session*)sn, (Request*)rq);
}
int nsapi_exec_tp(
directive *d,
NSAPISession *sn,
NSAPIRequest *rq,
threadpool_t *pool)
{
struct _tpd_data *data = malloc(
sizeof(
struct _tpd_data));
if(data ==
NULL) {
return REQ_ABORTED;
}
data->sn = sn;
data->rq = rq;
data->directive = d;
data->threadpool = pool;
sn->currentpool = pool;
threadpool_run(pool, thrpool_exec, data);
return REQ_PROCESSING;
}
void nsapi_function_return(Session *session, Request *request,
int ret) {
NSAPISession *sn = (NSAPISession*)session;
NSAPIRequest *rq = (NSAPIRequest*)request;
rq->context.last_req_code = ret;
if(sn->currentpool != sn->defaultpool) {
nsapi_change_threadpool(sn, rq, sn->defaultpool);
}
else {
nsapi_handle_request(sn, rq);
}
}
void nsapi_change_threadpool(
NSAPISession *sn,
NSAPIRequest *rq,
threadpool_t *thrpool)
{
struct _tpd_data *data = malloc(
sizeof(
struct _tpd_data));
data->sn = sn;
data->rq = rq;
data->threadpool = thrpool;
threadpool_run(thrpool, thrpool_change, data);
}
void* thrpool_exec(
void *d) {
struct _tpd_data *data = d;
data->sn->currentpool = data->threadpool;
int r =
SAF_EXEC(
data->directive->func,
data->directive->param,
(Session*)data->sn,
(Request*)data->rq);
nsapi_function_return((Session*)data->sn, (Request*)data->rq, r);
free(data);
return NULL;
}
void* thrpool_change(
void *d) {
struct _tpd_data *data = d;
data->sn->currentpool = data->threadpool;
nsapi_handle_request(data->sn, data->rq);
free(data);
return NULL;
}
int method_match(
char *cmp,
char *method) {
if(cmp[
0] !=
'(') {
if(!strcmp(cmp, method)) {
return 1;
}
}
else if(cmp[
0] ==
0) {
log_ereport(
LOG_WARN,
"Skipped service saf with empty method parameter");
return 0;
}
size_t method_len = strlen(method);
size_t last_pos =
0;
cmp++;
for(
int i=
0;cmp[i]!=
0;i++) {
char c = cmp[i];
if(c ==
'|' || c ==
')') {
size_t len = i - last_pos;
if(len == method_len) {
char *cp = cmp + last_pos;
if(!memcmp(cp, method, len)) {
return 1;
}
}
last_pos = i +
1;
}
}
return 0;
}
int contenttype_match(
sstr_t cmp,
sstr_t ctype) {
if(cmp.ptr[
0] !=
'(') {
if(cmp.ptr[
0] ==
'*') {
cmp.ptr++;
cmp.length--;
return sstrsuffix(ctype, cmp);
}
else if(cmp.ptr[cmp.length-
1] ==
'*') {
cmp.length--;
return sstrprefix(ctype, cmp);
}
else {
return !sstrcmp(cmp, ctype);
}
}
else if(cmp.ptr[
0] ==
0) {
log_ereport(
LOG_WARN,
"Skipped service saf with empty type parameter");
return 0;
}
cmp = sstrsubsl(cmp,
1, cmp.length -
2);
int begin =
0;
for(
int i=
0;i<cmp.length;i++) {
if(cmp.ptr[i] ==
'|') {
if(contenttype_match(sstrsubsl(cmp, begin, i-begin), ctype)) {
return 1;
}
begin = i +
1;
}
}
return contenttype_match(sstrsubs(cmp, begin), ctype);
}
int add_objects(
HTTPObjectConfig *objs,
httpd_objset *os,
NSAPISession *sn,
NSAPIRequest *rq,
char *name,
char *path)
{
if(name ==
NULL) {
return REQ_PROCEED;
}
for(
int i=
0;i<objs->nobj;i++) {
httpd_object *obj = objs->objects[i];
if(obj->name && !strcmp(name, obj->name)) {
objset_add_object(sn->sn.pool, os, obj);
}
}
return REQ_PROCEED;
}