enhanced httpd

This commit is contained in:
hyung-hwan 2014-08-11 05:44:03 +00:00
parent 1ba63f1829
commit 2fa6802c03
11 changed files with 481 additions and 134 deletions

View File

@ -10,6 +10,7 @@
#include <qse/cmn/opt.h> #include <qse/cmn/opt.h>
#include <qse/cmn/htb.h> #include <qse/cmn/htb.h>
#include <qse/cmn/fmt.h> #include <qse/cmn/fmt.h>
#include <qse/cmn/hton.h>
#include <signal.h> #include <signal.h>
#include <locale.h> #include <locale.h>
@ -150,6 +151,7 @@ struct loccfg_t
qse_mcstr_t locname; qse_mcstr_t locname;
qse_mchar_t* xcfg[XCFG_MAX]; qse_mchar_t* xcfg[XCFG_MAX];
int root_is_nwad; int root_is_nwad;
qse_nwad_t root_nwad; qse_nwad_t root_nwad;
struct struct
@ -182,6 +184,14 @@ struct loccfg_t
struct access_t* tail; struct access_t* tail;
} access[2][ACCESS_MAX]; } access[2][ACCESS_MAX];
struct
{
int allow_http: 1;
int allow_connect: 1;
qse_nwad_t dns_nwad; /* TODO: multiple dns */
qse_nwad_t urs_nwad; /* TODO: multiple urs */
} proxy;
loccfg_t* next; loccfg_t* next;
}; };
@ -351,8 +361,8 @@ static int make_resource (
/* TODO: implement a better check that the /* TODO: implement a better check that the
* destination is not one of the local addresses */ * destination is not one of the local addresses */
rsrc->type = QSE_HTTPD_RSRC_ERR; rsrc->type = QSE_HTTPD_RSRC_ERROR;
rsrc->u.err.code = 500; rsrc->u.error.code = 500;
} }
else else
{ {
@ -376,8 +386,8 @@ static int make_resource (
{ {
/* prohibit no directory listing */ /* prohibit no directory listing */
server_xtn->orgfreersrc (httpd, client, req, rsrc); server_xtn->orgfreersrc (httpd, client, req, rsrc);
rsrc->type = QSE_HTTPD_RSRC_ERR; rsrc->type = QSE_HTTPD_RSRC_ERROR;
rsrc->u.err.code = 403; rsrc->u.error.code = 403;
} }
return 0; return 0;
} }
@ -417,14 +427,14 @@ static loccfg_t* find_loccfg (
/* the location names are inspected in the order as shown /* the location names are inspected in the order as shown
* in the configuration. */ * in the configuration. */
for (loccfg = hostcfg->loccfg; loccfg; loccfg = loccfg->next) for (loccfg = hostcfg->loccfg; loccfg; loccfg = loccfg->next)
{ {
QSE_ASSERT (loccfg->locname.len > 0); QSE_ASSERT (loccfg->locname.len > 0);
if (qse_mbsbeg (qpath, loccfg->locname.ptr) &&
if (qse_mbsbeg (qpath, loccfg->locname.ptr) &&
(loccfg->locname.ptr[loccfg->locname.len - 1] == QSE_MT('/') || (loccfg->locname.ptr[loccfg->locname.len - 1] == QSE_MT('/') ||
qpath[loccfg->locname.len] == QSE_MT('/') || qpath[loccfg->locname.len] == QSE_MT('/') ||
qpath[loccfg->locname.len] == QSE_MT('\0'))) qpath[loccfg->locname.len] == QSE_MT('\0')))
{ {
return loccfg; return loccfg;
} }
@ -434,11 +444,119 @@ static loccfg_t* find_loccfg (
return QSE_NULL; return QSE_NULL;
} }
static int get_server_root (
qse_httpd_t* httpd,
qse_httpd_server_t* server,
loccfg_t* loccfg,
const qse_httpd_serverstd_query_info_t* qinfo,
qse_httpd_serverstd_root_t* root)
{
qse_http_method_t mth;
qse_mchar_t* qpath;
qse_memset (root, 0, QSE_SIZEOF(*root));
mth = qse_htre_getqmethodtype (qinfo->req);
qpath = qse_htre_getqpath(qinfo->req);
qse_memset (root, 0, QSE_SIZEOF(*root));
if (mth == QSE_HTTP_CONNECT)
{
if (loccfg->proxy.allow_connect)
{
/* TODO: check on what conditions CONNECT is allowed. */
/* TODO: disallow connecting back to self */
/* TODO: Proxy-Authorization???? */
root->type = QSE_HTTPD_SERVERSTD_ROOT_PROXY;
root->u.proxy.flags |= QSE_HTTPD_RSRC_PROXY_RAW;
if (qse_mbstonwad(qpath, &root->u.proxy.dst.nwad) <= -1)
{
root->u.proxy.flags |= QSE_HTTPD_RSRC_PROXY_DST_STR;
root->u.proxy.dst.str = qpath;
}
else
{
/* make the source binding type the same as destination */
/* no default port for raw proxying */
root->u.proxy.src.nwad.type = root->u.proxy.dst.nwad.type;
}
return 0;
}
else
{
root->type = QSE_HTTPD_SERVERSTD_ROOT_ERROR;
root->u.error.code = 403; /* forbidden */
return 0;
}
}
if (loccfg->proxy.allow_http)
{
if (qse_mbszcasecmp (qpath, QSE_MT("http://"), 7) == 0)
{
qse_mchar_t* host, * slash;
host = qpath + 7;
slash = qse_mbschr (host, QSE_MT('/'));
if (slash && slash - host > 0)
{
/* TODO: refrain from manipulating the request like this */
root->type = QSE_HTTPD_SERVERSTD_ROOT_PROXY;
qse_memmove (host - 1, host, slash - host);
slash[-1] = QSE_MT('\0');
host = host - 1;
root->u.proxy.host = host;
if (qse_mbstonwad (host, &root->u.proxy.dst.nwad) <= -1)
{
root->u.proxy.flags |= QSE_HTTPD_RSRC_PROXY_DST_STR;
root->u.proxy.dst.str = host;
}
else
{
/* make the source binding type the same as destination */
if (qse_getnwadport(&root->u.proxy.dst.nwad) == 0)
qse_setnwadport (&root->u.proxy.dst.nwad, qse_hton16(80));
root->u.proxy.src.nwad.type = root->u.proxy.dst.nwad.type;
}
/* TODO: refrain from manipulating the request like this */
qinfo->req->u.q.path = slash; /* TODO: use setqpath or something... */
return 0;
}
}
else
{
root->type = QSE_HTTPD_SERVERSTD_ROOT_ERROR;
root->u.error.code = 403; /* forbidden */
return 0;
}
}
if (loccfg->root_is_nwad)
{
root->type = QSE_HTTPD_SERVERSTD_ROOT_NWAD;
root->u.nwad = loccfg->root_nwad;
}
else
{
root->type = QSE_HTTPD_SERVERSTD_ROOT_PATH;
root->u.path.val = loccfg->xcfg[XCFG_ROOT];
root->u.path.rpl = loccfg->locname.len;
}
return 0;
}
static int query_server ( static int query_server (
qse_httpd_t* httpd, qse_httpd_server_t* server, qse_httpd_t* httpd, qse_httpd_server_t* server,
qse_htre_t* req, const qse_mchar_t* xpath, qse_httpd_serverstd_query_code_t code,
qse_httpd_serverstd_query_code_t code, void* result) qse_httpd_serverstd_query_info_t* qinfo, void* result)
{ {
httpd_xtn_t* httpd_xtn; httpd_xtn_t* httpd_xtn;
server_xtn_t* server_xtn; server_xtn_t* server_xtn;
@ -460,42 +578,87 @@ static int query_server (
if (server_xtn->cfgtab) if (server_xtn->cfgtab)
{ {
if (req && server_xtn->cfgtab) if (qinfo && qinfo->req && server_xtn->cfgtab)
{ {
const qse_htre_hdrval_t* hosthdr; const qse_mchar_t* host = QSE_NULL;
const qse_mchar_t* host;
const qse_mchar_t* qpath; const qse_mchar_t* qpath;
qse_http_method_t mth;
qpath = qse_htre_getqpath (req); mth = qse_htre_getqmethodtype (qinfo->req);
qpath = qse_htre_getqpath (qinfo->req);
if (mth == QSE_HTTP_CONNECT)
{
/* the query path for CONNECT is not a path name, but
* a host name. the path is adjusted to the root directory. */
host = qpath;
qpath = QSE_MT("/");
}
else
{
const qse_htre_hdrval_t* hosthdr;
hosthdr = qse_htre_getheaderval (req, QSE_MT("Host")); hosthdr = qse_htre_getheaderval (qinfo->req, QSE_MT("Host"));
if (hosthdr) if (hosthdr)
{
/*while (hosthdr->next) hosthdr = hosthdr->next; */
host = hosthdr->ptr;
}
}
if (host)
{ {
const qse_mchar_t* colon; const qse_mchar_t* colon;
qse_size_t hostlen; qse_size_t hostlen;
/*while (hosthdr->next) hosthdr = hosthdr->next; */
host = hosthdr->ptr;
/* remove :port-number if the host name contains it */ /* remove :port-number if the host name contains it */
colon = qse_mbsrchr(host, QSE_MT(':')); colon = qse_mbsrchr(host, QSE_MT(':'));
if (colon) hostlen = colon - host; if (colon) hostlen = colon - host;
else hostlen = qse_mbslen(host); else hostlen = qse_mbslen(host);
loccfg = find_loccfg (httpd, server_xtn->cfgtab, host, hostlen, qpath); /* Wild card search
*
* www.tango.com =>
* www.tango.com
* tango.com
* com <-- up to here
* *
*
* tango.com =>
* tango.com
* com <-- up to here
* *
*/
while (hostlen > 0)
{
qse_mchar_t c;
loccfg = find_loccfg (httpd, server_xtn->cfgtab, host, hostlen, qpath);
if (loccfg) goto found;
/* skip the current segment */
do
{
c = *host++;
hostlen--;
}
while (c != QSE_MT('.') && hostlen > 0);
}
} }
if (loccfg == QSE_NULL) loccfg = find_loccfg (httpd, server_xtn->cfgtab, QSE_MT("*"), 1, qpath); if (loccfg == QSE_NULL) loccfg = find_loccfg (httpd, server_xtn->cfgtab, QSE_MT("*"), 1, qpath);
} }
if (loccfg == QSE_NULL) loccfg = find_loccfg (httpd, server_xtn->cfgtab, QSE_MT("*"), 1, QSE_MT("/")); if (loccfg == QSE_NULL) loccfg = find_loccfg (httpd, server_xtn->cfgtab, QSE_MT("*"), 1, QSE_MT("/"));
} }
if (loccfg == QSE_NULL) loccfg = &httpd_xtn->dflcfg; if (loccfg == QSE_NULL) loccfg = &httpd_xtn->dflcfg;
found:
switch (code) switch (code)
{ {
case QSE_HTTPD_SERVERSTD_ROOT: case QSE_HTTPD_SERVERSTD_ROOT:
#if 0 #if 0
if (qse_mbscmp (qse_htre_getqpath(req), QSE_MT("/version")) == 0) if (qse_mbscmp (qse_htre_getqpath(qinfo->req), QSE_MT("/version")) == 0)
{ {
/* return static text without inspecting further */ /* return static text without inspecting further */
((qse_httpd_serverstd_root_t*)result)->type = QSE_HTTPD_SERVERSTD_ROOT_TEXT; ((qse_httpd_serverstd_root_t*)result)->type = QSE_HTTPD_SERVERSTD_ROOT_TEXT;
@ -505,6 +668,8 @@ static int query_server (
else else
#endif #endif
return get_server_root (httpd, server, loccfg, qinfo, result);
/*
if (loccfg->root_is_nwad) if (loccfg->root_is_nwad)
{ {
((qse_httpd_serverstd_root_t*)result)->type = QSE_HTTPD_SERVERSTD_ROOT_NWAD; ((qse_httpd_serverstd_root_t*)result)->type = QSE_HTTPD_SERVERSTD_ROOT_NWAD;
@ -516,7 +681,7 @@ static int query_server (
((qse_httpd_serverstd_root_t*)result)->u.path.val = loccfg->xcfg[XCFG_ROOT]; ((qse_httpd_serverstd_root_t*)result)->u.path.val = loccfg->xcfg[XCFG_ROOT];
((qse_httpd_serverstd_root_t*)result)->u.path.rpl = loccfg->locname.len; ((qse_httpd_serverstd_root_t*)result)->u.path.rpl = loccfg->locname.len;
} }
return 0; return 0;*/
case QSE_HTTPD_SERVERSTD_REALM: case QSE_HTTPD_SERVERSTD_REALM:
{ {
@ -525,7 +690,7 @@ static int query_server (
((qse_httpd_serverstd_realm_t*)result)->name = loccfg->xcfg[XCFG_REALM]; ((qse_httpd_serverstd_realm_t*)result)->name = loccfg->xcfg[XCFG_REALM];
apath = xpath? xpath: qse_htre_getqpath (req); apath = qinfo->xpath? qinfo->xpath: qse_htre_getqpath (qinfo->req);
if (apath) if (apath)
{ {
const qse_mchar_t* base; const qse_mchar_t* base;
@ -609,7 +774,7 @@ static int query_server (
qse_httpd_serverstd_cgi_t* scgi; qse_httpd_serverstd_cgi_t* scgi;
const qse_mchar_t* xpath_base; const qse_mchar_t* xpath_base;
xpath_base = qse_mbsbasename (xpath); xpath_base = qse_mbsbasename (qinfo->xpath);
scgi = (qse_httpd_serverstd_cgi_t*)result; scgi = (qse_httpd_serverstd_cgi_t*)result;
qse_memset (scgi, 0, QSE_SIZEOF(*scgi)); qse_memset (scgi, 0, QSE_SIZEOF(*scgi));
@ -639,7 +804,7 @@ static int query_server (
qse_size_t i; qse_size_t i;
const qse_mchar_t* xpath_base; const qse_mchar_t* xpath_base;
xpath_base = qse_mbsbasename (xpath); xpath_base = qse_mbsbasename (qinfo->xpath);
*(const qse_mchar_t**)result = QSE_NULL; *(const qse_mchar_t**)result = QSE_NULL;
for (i = 0; i < QSE_COUNTOF(loccfg->mime); i++) for (i = 0; i < QSE_COUNTOF(loccfg->mime); i++)
@ -663,7 +828,7 @@ static int query_server (
case QSE_HTTPD_SERVERSTD_DIRACC: case QSE_HTTPD_SERVERSTD_DIRACC:
case QSE_HTTPD_SERVERSTD_FILEACC: case QSE_HTTPD_SERVERSTD_FILEACC:
{ {
switch (qse_htre_getqmethodtype(req)) switch (qse_htre_getqmethodtype(qinfo->req))
{ {
case QSE_HTTP_OPTIONS: case QSE_HTTP_OPTIONS:
case QSE_HTTP_HEAD: case QSE_HTTP_HEAD:
@ -678,7 +843,7 @@ static int query_server (
id = (code == QSE_HTTPD_SERVERSTD_DIRACC)? 0: 1; id = (code == QSE_HTTPD_SERVERSTD_DIRACC)? 0: 1;
xpath_base = qse_mbsbasename (xpath); xpath_base = qse_mbsbasename (qinfo->xpath);
*(int*)result = 200; *(int*)result = 200;
for (i = 0; i < QSE_COUNTOF(loccfg->access[id]); i++) for (i = 0; i < QSE_COUNTOF(loccfg->access[id]); i++)
@ -708,7 +873,7 @@ static int query_server (
} }
} }
return server_xtn->orgquery (httpd, server, req, xpath, code, result); return server_xtn->orgquery (httpd, server, code, qinfo, result);
} }
/* --------------------------------------------------------------------- */ /* --------------------------------------------------------------------- */
@ -739,11 +904,12 @@ static struct
{ QSE_T("pseudonym"), QSE_T("server-default.pseudonym") } { QSE_T("pseudonym"), QSE_T("server-default.pseudonym") }
}; };
/* local access items */
static struct static struct
{ {
const qse_char_t* x; const qse_char_t* x;
const qse_char_t* y; const qse_char_t* y;
} loc_acc_items[] = } loc_acc_items[] =
{ {
{ QSE_T("dir-access"), QSE_T("server-default.dir-access") }, { QSE_T("dir-access"), QSE_T("server-default.dir-access") },
{ QSE_T("file-access"), QSE_T("server-default.file-access") } { QSE_T("file-access"), QSE_T("server-default.file-access") }
@ -841,19 +1007,86 @@ static void free_loccfg_contents (qse_httpd_t* httpd, loccfg_t* loccfg)
if (loccfg->locname.ptr) qse_httpd_freemem (httpd, loccfg->locname.ptr); if (loccfg->locname.ptr) qse_httpd_freemem (httpd, loccfg->locname.ptr);
} }
static int load_loccfg (qse_httpd_t* httpd, qse_xli_list_t* list, loccfg_t* cfg) static int get_boolean (const qse_xli_str_t* v)
{
return (qse_strxcasecmp (v->ptr, v->len, QSE_T("yes")) == 0 ||
qse_strxcasecmp (v->ptr, v->len, QSE_T("on")) == 0);
}
static int load_loccfg_proxy (qse_httpd_t* httpd, qse_xli_t* xli, qse_xli_list_t* list, loccfg_t* cfg)
{
qse_xli_pair_t* pair;
qse_xli_list_t* proxy = QSE_NULL;
qse_xli_list_t* default_proxy = QSE_NULL;
/*qse_xli_atom_t* atom;*/
pair = qse_xli_findpair (xli, list, QSE_T("proxy"));
if (pair)
{
QSE_ASSERT (pair->val->type == QSE_XLI_LIST);
proxy = (qse_xli_list_t*)pair->val;
}
pair = qse_xli_findpair (xli, QSE_NULL, QSE_T("server-default.proxy"));
if (pair)
{
QSE_ASSERT (pair->val->type == QSE_XLI_LIST);
default_proxy = (qse_xli_list_t*)pair->val;
}
pair = QSE_NULL;
if (proxy) pair = qse_xli_findpair (xli, proxy, QSE_T("http")); /* server.host[].location[].proxy.http */
if (!pair && default_proxy) pair = qse_xli_findpair (xli, default_proxy, QSE_T("http")); /* server-default.proxy.http */
if (pair) cfg->proxy.allow_http = get_boolean ((qse_xli_str_t*)pair->val);
pair = QSE_NULL;
if (proxy) pair = qse_xli_findpair (xli, proxy, QSE_T("connect"));
if (!pair && default_proxy) pair = qse_xli_findpair (xli, default_proxy, QSE_T("connect"));
if (pair) cfg->proxy.allow_connect = get_boolean ((qse_xli_str_t*)pair->val);
pair = QSE_NULL;
if (proxy) pair = qse_xli_findpair (xli, proxy, QSE_T("dns-server"));
if (!pair && default_proxy) pair = qse_xli_findpair (xli, default_proxy, QSE_T("dns-server"));
if (pair)
{
qse_xli_str_t* str = (qse_xli_str_t*)pair->val;
if (qse_strtonwad (str->ptr, &cfg->proxy.dns_nwad) <= -1)
{
qse_printf (QSE_T("ERROR: invalid address for proxy dns - %s"), str->ptr);
return -1;
}
}
pair = QSE_NULL;
if (proxy) pair = qse_xli_findpair (xli, proxy, QSE_T("urs-server"));
if (!pair && default_proxy) pair = qse_xli_findpair (xli, default_proxy, QSE_T("urs-server"));
if (pair)
{
qse_xli_str_t* str = (qse_xli_str_t*)pair->val;
if (qse_strtonwad (str->ptr, &cfg->proxy.urs_nwad) <= -1)
{
qse_printf (QSE_T("ERROR: invalid address for proxy urs - %s"), str->ptr);
return -1;
}
}
return 0;
}
static int load_loccfg (qse_httpd_t* httpd, qse_xli_t* xli, qse_xli_list_t* list, loccfg_t* cfg)
{ {
qse_size_t i; qse_size_t i;
qse_xli_pair_t* pair; qse_xli_pair_t* pair;
qse_xli_atom_t* atom; qse_xli_atom_t* atom;
httpd_xtn_t* httpd_xtn; /*httpd_xtn_t* httpd_xtn;
httpd_xtn = qse_httpd_getxtnstd (httpd); httpd_xtn = qse_httpd_getxtnstd (httpd);*/
for (i = 0; i < QSE_COUNTOF(loc_xcfg_items); i++) for (i = 0; i < QSE_COUNTOF(loc_xcfg_items); i++)
{ {
pair = qse_xli_findpair (httpd_xtn->xli, list, loc_xcfg_items[i].x); pair = qse_xli_findpair (xli, list, loc_xcfg_items[i].x);
if (!pair) pair = qse_xli_findpair (httpd_xtn->xli, QSE_NULL, loc_xcfg_items[i].y); if (!pair) pair = qse_xli_findpair (xli, QSE_NULL, loc_xcfg_items[i].y);
if (pair && pair->val->type == QSE_XLI_STR) if (pair && pair->val->type == QSE_XLI_STR)
{ {
cfg->xcfg[i] = qse_httpd_strntombsdup (httpd, ((qse_xli_str_t*)pair->val)->ptr, ((qse_xli_str_t*)pair->val)->len); cfg->xcfg[i] = qse_httpd_strntombsdup (httpd, ((qse_xli_str_t*)pair->val)->ptr, ((qse_xli_str_t*)pair->val)->len);
@ -866,14 +1099,14 @@ static int load_loccfg (qse_httpd_t* httpd, qse_xli_list_t* list, loccfg_t* cfg)
} }
} }
pair = qse_xli_findpair (httpd_xtn->xli, list, QSE_T("index")); pair = qse_xli_findpair (xli, list, QSE_T("index"));
if (!pair) pair = qse_xli_findpair (httpd_xtn->xli, QSE_NULL, QSE_T("server-default.index")); if (!pair) pair = qse_xli_findpair (xli, QSE_NULL, QSE_T("server-default.index"));
if (pair && pair->val->type == QSE_XLI_STR) if (pair && pair->val->type == QSE_XLI_STR)
{ {
qse_char_t* duptmp; qse_char_t* duptmp;
qse_size_t count, duplen; qse_size_t count, duplen;
duptmp = qse_xli_dupflatstr (httpd_xtn->xli, (qse_xli_str_t*)pair->val, &duplen, &count); duptmp = qse_xli_dupflatstr (xli, (qse_xli_str_t*)pair->val, &duplen, &count);
if (duptmp == QSE_NULL) if (duptmp == QSE_NULL)
{ {
qse_printf (QSE_T("ERROR: memory failure in copying index\n")); qse_printf (QSE_T("ERROR: memory failure in copying index\n"));
@ -881,7 +1114,7 @@ static int load_loccfg (qse_httpd_t* httpd, qse_xli_list_t* list, loccfg_t* cfg)
} }
cfg->index.files = qse_httpd_strntombsdup (httpd, duptmp, duplen); cfg->index.files = qse_httpd_strntombsdup (httpd, duptmp, duplen);
qse_xli_freemem (httpd_xtn->xli, duptmp); qse_xli_freemem (xli, duptmp);
if (cfg->index.files == QSE_NULL) if (cfg->index.files == QSE_NULL)
{ {
@ -892,8 +1125,8 @@ static int load_loccfg (qse_httpd_t* httpd, qse_xli_list_t* list, loccfg_t* cfg)
cfg->index.count = count; cfg->index.count = count;
} }
pair = qse_xli_findpair (httpd_xtn->xli, list, QSE_T("cgi")); pair = qse_xli_findpair (xli, list, QSE_T("cgi"));
if (!pair) pair = qse_xli_findpair (httpd_xtn->xli, QSE_NULL, QSE_T("server-default.cgi")); if (!pair) pair = qse_xli_findpair (xli, QSE_NULL, QSE_T("server-default.cgi"));
if (pair && pair->val->type == QSE_XLI_LIST) if (pair && pair->val->type == QSE_XLI_LIST)
{ {
qse_xli_list_t* cgilist = (qse_xli_list_t*)pair->val; qse_xli_list_t* cgilist = (qse_xli_list_t*)pair->val;
@ -965,8 +1198,8 @@ static int load_loccfg (qse_httpd_t* httpd, qse_xli_list_t* list, loccfg_t* cfg)
} }
} }
pair = qse_xli_findpair (httpd_xtn->xli, list, QSE_T("auth-rule")); pair = qse_xli_findpair (xli, list, QSE_T("auth-rule"));
if (!pair) pair = qse_xli_findpair (httpd_xtn->xli, QSE_NULL, QSE_T("server-default.auth-rule")); if (!pair) pair = qse_xli_findpair (xli, QSE_NULL, QSE_T("server-default.auth-rule"));
if (pair && pair->val->type == QSE_XLI_LIST) if (pair && pair->val->type == QSE_XLI_LIST)
{ {
qse_xli_list_t* auth_rule_list = (qse_xli_list_t*)pair->val; qse_xli_list_t* auth_rule_list = (qse_xli_list_t*)pair->val;
@ -1015,8 +1248,8 @@ static int load_loccfg (qse_httpd_t* httpd, qse_xli_list_t* list, loccfg_t* cfg)
} }
} }
pair = qse_xli_findpair (httpd_xtn->xli, list, QSE_T("mime")); pair = qse_xli_findpair (xli, list, QSE_T("mime"));
if (!pair) pair = qse_xli_findpair (httpd_xtn->xli, QSE_NULL, QSE_T("server-default.mime")); if (!pair) pair = qse_xli_findpair (xli, QSE_NULL, QSE_T("server-default.mime"));
if (pair && pair->val->type == QSE_XLI_LIST) if (pair && pair->val->type == QSE_XLI_LIST)
{ {
qse_xli_list_t* mimelist = (qse_xli_list_t*)pair->val; qse_xli_list_t* mimelist = (qse_xli_list_t*)pair->val;
@ -1070,8 +1303,8 @@ static int load_loccfg (qse_httpd_t* httpd, qse_xli_list_t* list, loccfg_t* cfg)
for (i = 0; i < 2; i++) for (i = 0; i < 2; i++)
{ {
pair = qse_xli_findpair (httpd_xtn->xli, list, loc_acc_items[i].x); pair = qse_xli_findpair (xli, list, loc_acc_items[i].x);
if (!pair) pair = qse_xli_findpair (httpd_xtn->xli, QSE_NULL, loc_acc_items[i].y); if (!pair) pair = qse_xli_findpair (xli, QSE_NULL, loc_acc_items[i].y);
if (pair && pair->val->type == QSE_XLI_LIST) if (pair && pair->val->type == QSE_XLI_LIST)
{ {
qse_xli_list_t* acclist = (qse_xli_list_t*)pair->val; qse_xli_list_t* acclist = (qse_xli_list_t*)pair->val;
@ -1129,8 +1362,11 @@ static int load_loccfg (qse_httpd_t* httpd, qse_xli_list_t* list, loccfg_t* cfg)
} }
} }
if (load_loccfg_proxy (httpd, xli, list, cfg) <= -1) return -1;
/* TODO: support multiple auth entries here and above */ /* TODO: support multiple auth entries here and above */
#if 0 #if 0
/* TODO: perform more sanity check */ /* TODO: perform more sanity check */
if (qse_mbschr (cfg->xcfg[XCFG_AUTH], QSE_MT(':')) == QSE_NULL) if (qse_mbschr (cfg->xcfg[XCFG_AUTH], QSE_MT(':')) == QSE_NULL)
@ -1155,7 +1391,7 @@ static void free_server_hostcfg (qse_httpd_t* httpd, server_hostcfg_t* hostcfg)
while (lc) while (lc)
{ {
cur = lc; cur = lc;
lc = lc->next; lc = lc->next;
free_loccfg_contents (httpd, cur); free_loccfg_contents (httpd, cur);
qse_httpd_freemem (httpd, cur); qse_httpd_freemem (httpd, cur);
@ -1272,7 +1508,7 @@ static int load_server_config (qse_httpd_t* httpd, qse_httpd_server_t* server, q
hostcfg->loccfg = loccfg; hostcfg->loccfg = loccfg;
/* load the data now */ /* load the data now */
if (load_loccfg (httpd, (qse_xli_list_t*)loc->val, loccfg) <= -1) goto oops; if (load_loccfg (httpd, httpd_xtn->xli, (qse_xli_list_t*)loc->val, loccfg) <= -1) goto oops;
/* clone the location name */ /* clone the location name */
loccfg->locname.ptr = qse_httpd_strtombsdup (httpd, loccfg->locname.ptr = qse_httpd_strtombsdup (httpd,
@ -1432,6 +1668,16 @@ static int open_config_file (qse_httpd_t* httpd)
{ QSE_T("server-default.error-head"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, { QSE_T("server-default.error-head"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } },
{ QSE_T("server-default.error-foot"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, { QSE_T("server-default.error-foot"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } },
{ QSE_T("server-default.pseudonym"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, { QSE_T("server-default.pseudonym"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } },
{ QSE_T("server-default.proxy"), { QSE_XLI_SCM_VALLIST | QSE_XLI_SCM_KEYNODUP, 0, 0 } },
{ QSE_T("server-default.proxy.http"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } },
{ QSE_T("server-default.proxy.connect"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } },
{ QSE_T("server-default.proxy.pseudonym"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } },
{ QSE_T("server-default.proxy.dns-server"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } },
{ QSE_T("server-default.proxy.dns-timeout"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } },
{ QSE_T("server-default.proxy.dns-retries"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } },
{ QSE_T("server-default.proxy.urs-server"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } },
{ QSE_T("server-default.proxy.urs-timeout"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } },
{ QSE_T("server-default.proxy.urs-retries"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } },
{ QSE_T("server"), { QSE_XLI_SCM_VALLIST, 0, 0 } }, { QSE_T("server"), { QSE_XLI_SCM_VALLIST, 0, 0 } },
{ QSE_T("server.bind"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, { QSE_T("server.bind"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } },
@ -1472,7 +1718,18 @@ static int open_config_file (qse_httpd_t* httpd)
{ QSE_T("server.host.location.dir-foot"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, { QSE_T("server.host.location.dir-foot"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } },
{ QSE_T("server.host.location.error-head"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, { QSE_T("server.host.location.error-head"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } },
{ QSE_T("server.host.location.error-foot"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, { QSE_T("server.host.location.error-foot"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } },
{ QSE_T("server.host.location.pseudonym"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } } { QSE_T("server.host.location.pseudonym"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } },
{ QSE_T("server.host.location.proxy"), { QSE_XLI_SCM_VALLIST | QSE_XLI_SCM_KEYNODUP, 0, 0 } },
{ QSE_T("server.host.location.proxy.http"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } },
{ QSE_T("server.host.location.proxy.connect"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } },
{ QSE_T("server.host.location.proxy.pseudonym"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } },
{ QSE_T("server.host.location.proxy.dns-server"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } },
{ QSE_T("server.host.location.proxy.dns-timeout"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } },
{ QSE_T("server.host.location.proxy.dns-retries"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } },
{ QSE_T("server.host.location.proxy.urs-server"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } },
{ QSE_T("server.host.location.proxy.urs-timeout"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } },
{ QSE_T("server.host.location.proxy.urs-retries"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } },
}; };
@ -1645,7 +1902,7 @@ static int load_config (qse_httpd_t* httpd)
pair = qse_xli_findpair (httpd_xtn->xli, QSE_NULL, QSE_T("server-default")); pair = qse_xli_findpair (httpd_xtn->xli, QSE_NULL, QSE_T("server-default"));
if (pair && pair->val->type == QSE_XLI_LIST) if (pair && pair->val->type == QSE_XLI_LIST)
{ {
if (load_loccfg (httpd, (qse_xli_list_t*)pair->val, &httpd_xtn->dflcfg) <= -1) if (load_loccfg (httpd, httpd_xtn->xli, (qse_xli_list_t*)pair->val, &httpd_xtn->dflcfg) <= -1)
{ {
qse_fprintf (QSE_STDERR, QSE_T("failed to load configuration from %s\n"), httpd_xtn->cfgfile); qse_fprintf (QSE_STDERR, QSE_T("failed to load configuration from %s\n"), httpd_xtn->cfgfile);
goto oops; goto oops;

View File

@ -39,6 +39,7 @@ server-default {
#} #}
cgi { cgi {
#name "t3.nph" = "nph"; #name "t3.nph" = "nph";
#prefix "t3." = "nph"; #prefix "t3." = "nph";
suffix ".cgi"; suffix ".cgi";
@ -53,6 +54,27 @@ server-default {
@include "httpd-mime.conf"; @include "httpd-mime.conf";
} }
####################################################################
#
# Accee control including dir-access and file-access can be
# defined using patterns and actions shown below
#
# Pattern
# prefix ".xxxx" (prefix match)
# suffix "xxxx." (suffix match)
# name "xxxx.yyyy" (exact match)
# other (all others)
#
# Action
# noent
# forbid
# ok
#
####################################################################
#################################################################### ####################################################################
# control access to directories # control access to directories
#################################################################### ####################################################################
@ -100,6 +122,14 @@ server-default {
# override it with error-foot. # override it with error-foot.
#################################################################### ####################################################################
#error-foot = "QSEHTTPD v1"; #error-foot = "QSEHTTPD v1";
####################################################################
# Default proxy configuration
####################################################################
proxy {
http = yes;
connect = yes;
}
} }
server { server {
@ -155,7 +185,6 @@ server {
} }
# virtual hosts are not supported yet.
#host "www.google.com" { #host "www.google.com" {
# location "/" { # location "/" {
# root = "/home/www/google"; # root = "/home/www/google";

View File

@ -78,17 +78,17 @@ struct qse_htre_t
qse_http_method_t type; qse_http_method_t type;
const qse_mchar_t* name; const qse_mchar_t* name;
} method; } method;
const qse_mchar_t* path; qse_mchar_t* path;
const qse_mchar_t* param; qse_mchar_t* param;
} q; } q;
struct struct
{ {
struct struct
{ {
int val; int val;
const qse_mchar_t* str; qse_mchar_t* str;
} code; } code;
const qse_mchar_t* mesg; qse_mchar_t* mesg;
} s; } s;
} u; } u;

View File

@ -528,7 +528,7 @@ enum qse_httpd_rsrc_type_t
QSE_HTTPD_RSRC_AUTH, QSE_HTTPD_RSRC_AUTH,
QSE_HTTPD_RSRC_CGI, QSE_HTTPD_RSRC_CGI,
QSE_HTTPD_RSRC_DIR, QSE_HTTPD_RSRC_DIR,
QSE_HTTPD_RSRC_ERR, QSE_HTTPD_RSRC_ERROR,
QSE_HTTPD_RSRC_FILE, QSE_HTTPD_RSRC_FILE,
QSE_HTTPD_RSRC_PROXY, QSE_HTTPD_RSRC_PROXY,
QSE_HTTPD_RSRC_RELOC, QSE_HTTPD_RSRC_RELOC,
@ -606,7 +606,7 @@ struct qse_httpd_rsrc_t
struct struct
{ {
int code; int code;
} err; } error;
struct struct
{ {

View File

@ -41,7 +41,9 @@ enum qse_httpd_serverstd_root_type_t
{ {
QSE_HTTPD_SERVERSTD_ROOT_PATH, QSE_HTTPD_SERVERSTD_ROOT_PATH,
QSE_HTTPD_SERVERSTD_ROOT_NWAD, QSE_HTTPD_SERVERSTD_ROOT_NWAD,
QSE_HTTPD_SERVERSTD_ROOT_TEXT QSE_HTTPD_SERVERSTD_ROOT_TEXT,
QSE_HTTPD_SERVERSTD_ROOT_PROXY,
QSE_HTTPD_SERVERSTD_ROOT_ERROR
}; };
typedef enum qse_httpd_serverstd_root_type_t qse_httpd_serverstd_root_type_t; typedef enum qse_httpd_serverstd_root_type_t qse_httpd_serverstd_root_type_t;
@ -56,12 +58,21 @@ struct qse_httpd_serverstd_root_t
const qse_mchar_t* val; const qse_mchar_t* val;
qse_size_t rpl; /* replacement length */ qse_size_t rpl; /* replacement length */
} path; } path;
qse_nwad_t nwad; qse_nwad_t nwad;
struct struct
{ {
const qse_mchar_t* ptr; const qse_mchar_t* ptr;
const qse_mchar_t* mime; const qse_mchar_t* mime;
} text; } text;
struct qse_httpd_rsrc_proxy_t proxy;
struct
{
int code; /* http error code */
} error;
} u; } u;
}; };
@ -101,37 +112,51 @@ struct qse_httpd_serverstd_ssl_t
const qse_mchar_t* keyfile; const qse_mchar_t* keyfile;
}; };
typedef struct qse_httpd_serverstd_proxy_t qse_httpd_serverstd_proxy_t;
struct qse_httpd_serverstd_proxy_t
{
int tproxy: 1;
const qse_mchar_t* pseudonym;
};
enum qse_httpd_serverstd_query_code_t enum qse_httpd_serverstd_query_code_t
{ {
QSE_HTTPD_SERVERSTD_SSL, /* qse_httpd_serverstd_ssl_t */ QSE_HTTPD_SERVERSTD_SSL, /* qse_httpd_serverstd_ssl_t */
QSE_HTTPD_SERVERSTD_ROOT, /* qse_httpd_serverstd_root_t */ QSE_HTTPD_SERVERSTD_ROOT, /* qse_httpd_serverstd_root_t */
QSE_HTTPD_SERVERSTD_REALM, /* qse_httpd_serverstd_realm_t */ QSE_HTTPD_SERVERSTD_REALM, /* qse_httpd_serverstd_realm_t */
QSE_HTTPD_SERVERSTD_AUTH, /* qse_httpd_serverstd_auth_t */ QSE_HTTPD_SERVERSTD_AUTH, /* qse_httpd_serverstd_auth_t */
QSE_HTTPD_SERVERSTD_ERRHEAD, /* const qse_mchar_t* */ QSE_HTTPD_SERVERSTD_ERRHEAD, /* const qse_mchar_t* */
QSE_HTTPD_SERVERSTD_ERRFOOT, /* const qse_mchar_t* */ QSE_HTTPD_SERVERSTD_ERRFOOT, /* const qse_mchar_t* */
QSE_HTTPD_SERVERSTD_DIRHEAD, /* const qse_mchar_t* */ QSE_HTTPD_SERVERSTD_DIRHEAD, /* const qse_mchar_t* */
QSE_HTTPD_SERVERSTD_DIRFOOT, /* const qse_mchar_t* */ QSE_HTTPD_SERVERSTD_DIRFOOT, /* const qse_mchar_t* */
QSE_HTTPD_SERVERSTD_PSEUDONYM, /* const qse_mchar_t*, pseudonym to use in Via: */ QSE_HTTPD_SERVERSTD_PSEUDONYM, /* const qse_mchar_t*, pseudonym to use in Via: */
QSE_HTTPD_SERVERSTD_INDEX, /* qse_httpd_serverstd_index_t */ QSE_HTTPD_SERVERSTD_INDEX, /* qse_httpd_serverstd_index_t */
QSE_HTTPD_SERVERSTD_CGI, /* qse_httpd_serverstd_cgi_t */ QSE_HTTPD_SERVERSTD_CGI, /* qse_httpd_serverstd_cgi_t */
QSE_HTTPD_SERVERSTD_MIME, /* const qse_mchar_t* */ QSE_HTTPD_SERVERSTD_MIME, /* const qse_mchar_t* */
QSE_HTTPD_SERVERSTD_DIRACC, /* int (http error code) */ QSE_HTTPD_SERVERSTD_DIRACC, /* int (http error code) */
QSE_HTTPD_SERVERSTD_FILEACC /* int (http error code) */ QSE_HTTPD_SERVERSTD_FILEACC /* int (http error code) */
}; };
typedef enum qse_httpd_serverstd_query_code_t qse_httpd_serverstd_query_code_t; typedef enum qse_httpd_serverstd_query_code_t qse_httpd_serverstd_query_code_t;
struct qse_httpd_serverstd_query_info_t
{
qse_htre_t* req;
qse_mchar_t* xpath; /* query path combined with document root */
};
typedef struct qse_httpd_serverstd_query_info_t qse_httpd_serverstd_query_info_t;
typedef int (*qse_httpd_serverstd_query_t) ( typedef int (*qse_httpd_serverstd_query_t) (
qse_httpd_t* httpd, qse_httpd_t* httpd,
qse_httpd_server_t* server, qse_httpd_server_t* server,
qse_htre_t* req, qse_httpd_serverstd_query_code_t code,
const qse_mchar_t* xpath, const qse_httpd_serverstd_query_info_t* info,
qse_httpd_serverstd_query_code_t code, void* result
void* result
); );
enum qse_httpd_serverstd_opt_t enum qse_httpd_serverstd_opt_t

View File

@ -58,11 +58,11 @@ struct task_cgi_t
int init_failed; int init_failed;
qse_httpd_t* httpd; qse_httpd_t* httpd;
const qse_mchar_t* path; qse_mchar_t* path;
const qse_mchar_t* script; qse_mchar_t* script;
const qse_mchar_t* suffix; qse_mchar_t* suffix;
const qse_mchar_t* root; qse_mchar_t* root;
const qse_mchar_t* shebang; qse_mchar_t* shebang;
int method; int method;
qse_http_version_t version; qse_http_version_t version;
@ -1601,16 +1601,16 @@ qse_httpd_task_t* qse_httpd_entaskcgi (
if (rsrc.root == QSE_NULL) rsrc.root = QSE_MT(""); if (rsrc.root == QSE_NULL) rsrc.root = QSE_MT("");
if (rsrc.shebang == QSE_NULL) rsrc.shebang = QSE_MT(""); if (rsrc.shebang == QSE_NULL) rsrc.shebang = QSE_MT("");
arg.path.ptr = rsrc.path; arg.path.ptr = (qse_mchar_t*)rsrc.path;
arg.path.len = qse_mbslen(rsrc.path); arg.path.len = qse_mbslen(rsrc.path);
arg.script.ptr = rsrc.script; arg.script.ptr = (qse_mchar_t*)rsrc.script;
arg.script.len = qse_mbslen(rsrc.script); arg.script.len = qse_mbslen(rsrc.script);
arg.suffix.ptr = rsrc.suffix; arg.suffix.ptr = (qse_mchar_t*)rsrc.suffix;
arg.suffix.len = qse_mbslen(rsrc.suffix); arg.suffix.len = qse_mbslen(rsrc.suffix);
arg.root.ptr = rsrc.root; arg.root.ptr = (qse_mchar_t*)rsrc.root;
arg.root.len = qse_mbslen(rsrc.root); arg.root.len = qse_mbslen(rsrc.root);
arg.nph = rsrc.nph; arg.nph = rsrc.nph;
arg.shebang.ptr = rsrc.shebang; arg.shebang.ptr = (qse_mchar_t*)rsrc.shebang;
arg.shebang.len = qse_mbslen(rsrc.shebang); arg.shebang.len = qse_mbslen(rsrc.shebang);
arg.req = req; arg.req = req;

View File

@ -606,11 +606,11 @@ qse_httpd_task_t* qse_httpd_entaskdir (
/* create a directory listing task */ /* create a directory listing task */
qse_httpd_task_t task, * x; qse_httpd_task_t task, * x;
data.path.ptr = dir->path; data.path.ptr = (qse_mchar_t*)dir->path;
data.path.len = qse_mbslen(data.path.ptr); data.path.len = qse_mbslen(data.path.ptr);
data.qpath.ptr = qse_htre_getqpath(req); data.qpath.ptr = qse_htre_getqpath(req);
data.qpath.len = qse_mbslen(data.qpath.ptr); data.qpath.len = qse_mbslen(data.qpath.ptr);
data.head.ptr = dir->head? dir->head: QSE_MT("<style type='text/css'>body { background-color:#d0e4fe; font-size: 0.9em; } div.header { font-weight: bold; margin-bottom: 5px; } div.footer { border-top: 1px solid #99AABB; text-align: right; } table { font-size: 0.9em; } td { white-space: nowrap; } td.size { text-align: right; }</style>"); data.head.ptr = dir->head? (qse_mchar_t*)dir->head: QSE_MT("<style type='text/css'>body { background-color:#d0e4fe; font-size: 0.9em; } div.header { font-weight: bold; margin-bottom: 5px; } div.footer { border-top: 1px solid #99AABB; text-align: right; } table { font-size: 0.9em; } td { white-space: nowrap; } td.size { text-align: right; }</style>");
data.head.len = qse_mbslen(data.head.ptr); data.head.len = qse_mbslen(data.head.ptr);
data.foot.ptr = dir->foot? dir->foot: qse_httpd_getname(httpd); data.foot.ptr = dir->foot? dir->foot: qse_httpd_getname(httpd);
data.foot.len = qse_mbslen(data.foot.ptr); data.foot.len = qse_mbslen(data.foot.ptr);

View File

@ -539,7 +539,7 @@ qse_httpd_task_t* qse_httpd_entaskfile (
qse_size_t xtnsize; qse_size_t xtnsize;
QSE_MEMSET (&data, 0, QSE_SIZEOF(data)); QSE_MEMSET (&data, 0, QSE_SIZEOF(data));
data.path.ptr = path; data.path.ptr = (qse_mchar_t*)path;
data.path.len = qse_mbslen(path); data.path.len = qse_mbslen(path);
data.version = *qse_htre_getversion(req); data.version = *qse_htre_getversion(req);
data.keepalive = (req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE); data.keepalive = (req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE);
@ -563,7 +563,7 @@ qse_httpd_task_t* qse_httpd_entaskfile (
if (mime) if (mime)
{ {
data.u.get.mime.ptr = mime; data.u.get.mime.ptr = (qse_mchar_t*)mime;
data.u.get.mime.len = qse_mbslen(mime); data.u.get.mime.len = qse_mbslen(mime);
xtnsize += data.u.get.mime.len + 1; xtnsize += data.u.get.mime.len + 1;
} }

View File

@ -943,7 +943,7 @@ static int task_init_proxy (
{ {
const qse_mchar_t* qpath; const qse_mchar_t* qpath;
const qse_mchar_t* metnam; const qse_mchar_t* metnam;
const qse_mchar_t* host_ptr; const qse_mchar_t* host_ptr = QSE_NULL;
qse_mchar_t cliaddrbuf[128]; qse_mchar_t cliaddrbuf[128];
qse_size_t total_len; qse_size_t total_len;

View File

@ -554,14 +554,14 @@ static int init_xtn_ssl (qse_httpd_t* httpd, qse_httpd_server_t* server)
xtn = (httpd_xtn_t*)qse_httpd_getxtn (httpd); xtn = (httpd_xtn_t*)qse_httpd_getxtn (httpd);
server_xtn = (server_xtn_t*)qse_httpd_getserverxtn (httpd, server); server_xtn = (server_xtn_t*)qse_httpd_getserverxtn (httpd, server);
if (server_xtn->query (httpd, server, QSE_NULL, QSE_NULL, QSE_HTTPD_SERVERSTD_SSL, &ssl) <= -1) if (server_xtn->query (httpd, server, QSE_HTTPD_SERVERSTD_SSL, QSE_NULL, &ssl) <= -1)
{ {
return -1; return -1;
} }
if (ssl.certfile == QSE_NULL || ssl.keyfile == QSE_NULL) if (ssl.certfile == QSE_NULL || ssl.keyfile == QSE_NULL)
{ {
qse_httpd_seterrnum (httpd, QSE_HTTPD_EINVAL); qse_httpd_seterrnum (httpd, QSE_HTTPD_EINVAL);
return -1; return -1;
} }
@ -2126,7 +2126,7 @@ if (qse_htre_getcontentlen(req) > 0)
/* failed to make a resource. just send the internal server error. /* failed to make a resource. just send the internal server error.
* the makersrc handler can return a negative number to return * the makersrc handler can return a negative number to return
* '500 Internal Server Error'. If it wants to return a specific * '500 Internal Server Error'. If it wants to return a specific
* error code, it should return 0 with the QSE_HTTPD_RSRC_ERR * error code, it should return 0 with the QSE_HTTPD_RSRC_ERROR
* resource. */ * resource. */
qse_httpd_discardcontent (httpd, req); qse_httpd_discardcontent (httpd, req);
task = qse_httpd_entaskerr (httpd, client, QSE_NULL, 500, req); task = qse_httpd_entaskerr (httpd, client, QSE_NULL, 500, req);
@ -2148,7 +2148,7 @@ if (qse_htre_getcontentlen(req) > 0)
/* if the resource is indicating to return an error, /* if the resource is indicating to return an error,
* discard the contents since i won't return them */ * discard the contents since i won't return them */
if (rsrc.type == QSE_HTTPD_RSRC_ERR) if (rsrc.type == QSE_HTTPD_RSRC_ERROR)
{ {
qse_httpd_discardcontent (httpd, req); qse_httpd_discardcontent (httpd, req);
} }
@ -2175,7 +2175,7 @@ printf ("CANOT MAKE RESOURCE.... %s\n", qse_htre_getqpath(req));
/* failed to make a resource. just send the internal server error. /* failed to make a resource. just send the internal server error.
* the makersrc handler can return a negative number to return * the makersrc handler can return a negative number to return
* '500 Internal Server Error'. If it wants to return a specific * '500 Internal Server Error'. If it wants to return a specific
* error code, it should return 0 with the QSE_HTTPD_RSRC_ERR * error code, it should return 0 with the QSE_HTTPD_RSRC_ERROR
* resource. */ * resource. */
task = qse_httpd_entaskerr (httpd, client, QSE_NULL, 500, req); task = qse_httpd_entaskerr (httpd, client, QSE_NULL, 500, req);
} }
@ -2237,10 +2237,10 @@ static int format_error (
server_xtn = qse_httpd_getserverxtn (httpd, client->server); server_xtn = qse_httpd_getserverxtn (httpd, client->server);
if (server_xtn->query (httpd, client->server, QSE_NULL, QSE_NULL, QSE_HTTPD_SERVERSTD_ERRHEAD, &head) <= -1) head = QSE_NULL; if (server_xtn->query (httpd, client->server, QSE_HTTPD_SERVERSTD_ERRHEAD, QSE_NULL, &head) <= -1) head = QSE_NULL;
if (head == QSE_NULL) head = QSE_MT("<style type='text/css'>body { background-color:#d0e4fe; font-size: 0.9em; } div.header { font-weight: bold; margin-bottom: 5px; } div.footer { border-top: 1px solid #99AABB; text-align: right; }</style>"); if (head == QSE_NULL) head = QSE_MT("<style type='text/css'>body { background-color:#d0e4fe; font-size: 0.9em; } div.header { font-weight: bold; margin-bottom: 5px; } div.footer { border-top: 1px solid #99AABB; text-align: right; }</style>");
if (server_xtn->query (httpd, client->server, QSE_NULL, QSE_NULL, QSE_HTTPD_SERVERSTD_ERRFOOT, &foot) <= -1) foot = QSE_NULL; if (server_xtn->query (httpd, client->server, QSE_HTTPD_SERVERSTD_ERRFOOT, QSE_NULL, &foot) <= -1) foot = QSE_NULL;
if (foot == QSE_NULL) foot = qse_httpd_getname(httpd); if (foot == QSE_NULL) foot = qse_httpd_getname(httpd);
msg = qse_httpstatustombs(code); msg = qse_httpstatustombs(code);
@ -2486,8 +2486,15 @@ static int attempt_cgi (
if (tmp->final_match) if (tmp->final_match)
{ {
qse_httpd_serverstd_query_info_t qinfo;
/* it is a final match. tmp->xpath is tmp->root + tmp->qpath */ /* it is a final match. tmp->xpath is tmp->root + tmp->qpath */
if (server_xtn->query (httpd, client->server, req, tmp->xpath, QSE_HTTPD_SERVERSTD_CGI, &cgi) >= 0 && cgi.cgi)
QSE_MEMSET (&qinfo, 0, QSE_SIZEOF(qinfo));
qinfo.req = req;
qinfo.xpath = tmp->xpath;
if (server_xtn->query (httpd, client->server, QSE_HTTPD_SERVERSTD_CGI, &qinfo, &cgi) >= 0 && cgi.cgi)
{ {
if (tmp->idxfile) if (tmp->idxfile)
{ {
@ -2555,7 +2562,13 @@ static int attempt_cgi (
if (!st.isdir) if (!st.isdir)
{ {
if (server_xtn->query (httpd, client->server, req, tmp->xpath, QSE_HTTPD_SERVERSTD_CGI, &cgi) >= 0 && cgi.cgi) qse_httpd_serverstd_query_info_t qinfo;
QSE_MEMSET (&qinfo, 0, QSE_SIZEOF(qinfo));
qinfo.req = req;
qinfo.xpath = tmp->xpath;
if (server_xtn->query (httpd, client->server, QSE_HTTPD_SERVERSTD_CGI, &qinfo, &cgi) >= 0 && cgi.cgi)
{ {
/* the script name is composed of the orginal query path. /* the script name is composed of the orginal query path.
* the pointer held in 'slash' is valid for tmp->qpath as * the pointer held in 'slash' is valid for tmp->qpath as
@ -2620,6 +2633,8 @@ static int make_resource (
qse_httpd_stat_t st; qse_httpd_stat_t st;
int n, stx, acc; int n, stx, acc;
qse_httpd_serverstd_query_info_t qinfo;
QSE_MEMSET (&tmp, 0, QSE_SIZEOF(tmp)); QSE_MEMSET (&tmp, 0, QSE_SIZEOF(tmp));
tmp.qpath = qse_htre_getqpath(req); tmp.qpath = qse_htre_getqpath(req);
tmp.qpath_len = qse_mbslen (tmp.qpath); tmp.qpath_len = qse_mbslen (tmp.qpath);
@ -2628,6 +2643,10 @@ static int make_resource (
server_xtn = qse_httpd_getserverxtn (httpd, client->server); server_xtn = qse_httpd_getserverxtn (httpd, client->server);
QSE_MEMSET (&qinfo, 0, QSE_SIZEOF(qinfo));
qinfo.req = req;
#if 0
mth = qse_htre_getqmethodtype (req); mth = qse_htre_getqmethodtype (req);
if (mth == QSE_HTTP_CONNECT) if (mth == QSE_HTTP_CONNECT)
{ {
@ -2653,7 +2672,7 @@ static int make_resource (
} }
/* pseudonym for raw proxying should not be useful. but set it for consistency */ /* pseudonym for raw proxying should not be useful. but set it for consistency */
if (server_xtn->query (httpd, client->server, QSE_NULL, QSE_NULL, QSE_HTTPD_SERVERSTD_PSEUDONYM, &target->u.proxy.pseudonym) <= -1) if (server_xtn->query (httpd, client->server, QSE_HTTPD_SERVERSTD_PSEUDONYM, &qinfo, &target->u.proxy.pseudonym) <= -1)
target->u.proxy.pseudonym = QSE_NULL; target->u.proxy.pseudonym = QSE_NULL;
/******************************************************************/ /******************************************************************/
@ -2693,11 +2712,11 @@ static int make_resource (
{ {
/* make the source binding type the same as destination */ /* make the source binding type the same as destination */
if (qse_getnwadport(&target->u.proxy.dst.nwad) == 0) if (qse_getnwadport(&target->u.proxy.dst.nwad) == 0)
qse_setnwadport (&target->u.proxy.dst.nwad, qse_hton16(80)); qse_setnwadport (&target->u.proxy.dst.nwad, qse_hton16(QSE_HTTPD_DEFAULT_PORT));
target->u.proxy.src.nwad.type = target->u.proxy.dst.nwad.type; target->u.proxy.src.nwad.type = target->u.proxy.dst.nwad.type;
} }
if (server_xtn->query (httpd, client->server, QSE_NULL, QSE_NULL, QSE_HTTPD_SERVERSTD_PSEUDONYM, &target->u.proxy.pseudonym) <= -1) if (server_xtn->query (httpd, client->server, QSE_HTTPD_SERVERSTD_PSEUDONYM, &qinfo, &target->u.proxy.pseudonym) <= -1)
target->u.proxy.pseudonym = QSE_NULL; target->u.proxy.pseudonym = QSE_NULL;
/* TODO: refrain from manipulating the request like this */ /* TODO: refrain from manipulating the request like this */
@ -2705,7 +2724,7 @@ static int make_resource (
/******************************************************************/ /******************************************************************/
/*TODO: load this from configuration. reamove this after debugging */ /*TODO: load this from configuration. reamove this after debugging */
target->u.proxy.flags |= QSE_HTTPD_RSRC_PROXY_URS; //target->u.proxy.flags |= QSE_HTTPD_RSRC_PROXY_URS;
/******************************************************************/ /******************************************************************/
/* mark that this request is going to be proxied. */ /* mark that this request is going to be proxied. */
@ -2714,7 +2733,9 @@ target->u.proxy.flags |= QSE_HTTPD_RSRC_PROXY_URS;
} }
} }
if (server_xtn->query (httpd, client->server, req, QSE_NULL, QSE_HTTPD_SERVERSTD_ROOT, &tmp.root) <= -1) return -1; #endif
if (server_xtn->query (httpd, client->server, QSE_HTTPD_SERVERSTD_ROOT, &qinfo, &tmp.root) <= -1) return -1;
switch (tmp.root.type) switch (tmp.root.type)
{ {
case QSE_HTTPD_SERVERSTD_ROOT_NWAD: case QSE_HTTPD_SERVERSTD_ROOT_NWAD:
@ -2730,7 +2751,7 @@ target->u.proxy.flags |= QSE_HTTPD_RSRC_PROXY_URS;
target->u.proxy.dst.nwad = tmp.root.u.nwad; target->u.proxy.dst.nwad = tmp.root.u.nwad;
target->u.proxy.src.nwad.type = target->u.proxy.dst.nwad.type; target->u.proxy.src.nwad.type = target->u.proxy.dst.nwad.type;
if (server_xtn->query (httpd, client->server, QSE_NULL, QSE_NULL, QSE_HTTPD_SERVERSTD_PSEUDONYM, &target->u.proxy.pseudonym) <= -1) if (server_xtn->query (httpd, client->server, QSE_HTTPD_SERVERSTD_PSEUDONYM, &qinfo, &target->u.proxy.pseudonym) <= -1)
target->u.proxy.pseudonym = QSE_NULL; target->u.proxy.pseudonym = QSE_NULL;
/* mark that this request is going to be proxied. */ /* mark that this request is going to be proxied. */
@ -2742,13 +2763,24 @@ target->u.proxy.flags |= QSE_HTTPD_RSRC_PROXY_URS;
target->u.text.ptr = tmp.root.u.text.ptr; target->u.text.ptr = tmp.root.u.text.ptr;
target->u.text.mime = tmp.root.u.text.mime; target->u.text.mime = tmp.root.u.text.mime;
return 0; return 0;
case QSE_HTTPD_SERVERSTD_ROOT_PROXY:
target->type = QSE_HTTPD_RSRC_PROXY;
target->u.proxy = tmp.root.u.proxy;
req->attr.flags |= QSE_HTRE_ATTR_PROXIED;
return 0;
case QSE_HTTPD_SERVERSTD_ROOT_ERROR:
target->type = QSE_HTTPD_RSRC_ERROR;
target->u.error.code = tmp.root.u.error.code;
return 0;
} }
/* handle the request locally */ /* handle the request locally */
QSE_ASSERT (tmp.root.type == QSE_HTTPD_SERVERSTD_ROOT_PATH); QSE_ASSERT (tmp.root.type == QSE_HTTPD_SERVERSTD_ROOT_PATH);
if (server_xtn->query (httpd, client->server, req, QSE_NULL, QSE_HTTPD_SERVERSTD_REALM, &tmp.realm) <= -1 || if (server_xtn->query (httpd, client->server, QSE_HTTPD_SERVERSTD_REALM, &qinfo, &tmp.realm) <= -1 ||
server_xtn->query (httpd, client->server, req, QSE_NULL, QSE_HTTPD_SERVERSTD_INDEX, &tmp.index) <= -1) server_xtn->query (httpd, client->server, QSE_HTTPD_SERVERSTD_INDEX, &qinfo, &tmp.index) <= -1)
{ {
return -1; return -1;
} }
@ -2792,7 +2824,7 @@ target->u.proxy.flags |= QSE_HTTPD_RSRC_PROXY_URS;
tmp.auth.key.ptr = server_xtn->auth.ptr; tmp.auth.key.ptr = server_xtn->auth.ptr;
tmp.auth.key.len = authl2; tmp.auth.key.len = authl2;
if (server_xtn->query (httpd, client->server, req, QSE_NULL, QSE_HTTPD_SERVERSTD_AUTH, &tmp.auth) >= 0 && tmp.auth.authok) goto auth_ok; if (server_xtn->query (httpd, client->server, QSE_HTTPD_SERVERSTD_AUTH, &qinfo, &tmp.auth) >= 0 && tmp.auth.authok) goto auth_ok;
} }
} }
@ -2825,8 +2857,8 @@ auth_ok:
{ {
/* Expectation Failed */ /* Expectation Failed */
qse_htre_discardcontent (req); qse_htre_discardcontent (req);
target->type = QSE_HTTPD_RSRC_ERR; target->type = QSE_HTTPD_RSRC_ERROR;
target->u.err.code = 417; target->u.error.code = 417;
return 0; return 0;
} }
} }
@ -2891,12 +2923,14 @@ auth_ok:
} }
} }
qinfo.xpath = tmp.xpath;
/* it is a directory - should i allow it? */ /* it is a directory - should i allow it? */
if (server_xtn->query (httpd, client->server, req, tmp.xpath, QSE_HTTPD_SERVERSTD_DIRACC, &target->u.err.code) <= -1) target->u.err.code = 500; if (server_xtn->query (httpd, client->server, QSE_HTTPD_SERVERSTD_DIRACC, &qinfo, &target->u.error.code) <= -1) target->u.error.code = 500;
if (target->u.err.code < 200 || target->u.err.code > 299) if (target->u.error.code < 200 || target->u.error.code > 299)
{ {
qse_htre_discardcontent (req); qse_htre_discardcontent (req);
target->type = QSE_HTTPD_RSRC_ERR; target->type = QSE_HTTPD_RSRC_ERROR;
/* free xpath since it won't be used */ /* free xpath since it won't be used */
QSE_MMGR_FREE (httpd->mmgr, tmp.xpath); QSE_MMGR_FREE (httpd->mmgr, tmp.xpath);
} }
@ -2913,8 +2947,8 @@ auth_ok:
{ {
target->type = QSE_HTTPD_RSRC_DIR; target->type = QSE_HTTPD_RSRC_DIR;
target->u.dir.path = tmp.xpath; target->u.dir.path = tmp.xpath;
if (server_xtn->query (httpd, client->server, req, tmp.xpath, QSE_HTTPD_SERVERSTD_DIRHEAD, &target->u.dir.head) <= -1) target->u.dir.head = QSE_NULL; if (server_xtn->query (httpd, client->server, QSE_HTTPD_SERVERSTD_DIRHEAD, &qinfo, &target->u.dir.head) <= -1) target->u.dir.head = QSE_NULL;
if (server_xtn->query (httpd, client->server, req, tmp.xpath, QSE_HTTPD_SERVERSTD_DIRFOOT, &target->u.dir.foot) <= -1) target->u.dir.foot = QSE_NULL; if (server_xtn->query (httpd, client->server, QSE_HTTPD_SERVERSTD_DIRFOOT, &qinfo, &target->u.dir.foot) <= -1) target->u.dir.foot = QSE_NULL;
} }
} }
else else
@ -2937,18 +2971,19 @@ auth_ok:
} }
if (n >= 1) return 0; if (n >= 1) return 0;
acc = (tmp.idxfile || !qse_mbsend(tmp.qpath, QSE_MT("/")))? qinfo.xpath = tmp.xpath;
QSE_HTTPD_SERVERSTD_FILEACC: QSE_HTTPD_SERVERSTD_DIRACC;
/* check file's access permission */ /* check file's access permission */
if (server_xtn->query (httpd, client->server, req, tmp.xpath, acc, &target->u.err.code) <= -1) target->u.err.code = 500; acc = (tmp.idxfile || !qse_mbsend(tmp.qpath, QSE_MT("/")))?
QSE_HTTPD_SERVERSTD_FILEACC: QSE_HTTPD_SERVERSTD_DIRACC;
if (server_xtn->query (httpd, client->server, acc, &qinfo, &target->u.error.code) <= -1) target->u.error.code = 500;
if (target->u.err.code < 200 || target->u.err.code > 299) if (target->u.error.code < 200 || target->u.error.code > 299)
{ {
/* free xpath since it won't be used */ /* free xpath since it won't be used */
qse_htre_discardcontent (req); qse_htre_discardcontent (req);
QSE_MMGR_FREE (httpd->mmgr, tmp.xpath); QSE_MMGR_FREE (httpd->mmgr, tmp.xpath);
target->type = QSE_HTTPD_RSRC_ERR; target->type = QSE_HTTPD_RSRC_ERROR;
} }
else else
{ {
@ -2970,15 +3005,15 @@ auth_ok:
target->type = QSE_HTTPD_RSRC_DIR; target->type = QSE_HTTPD_RSRC_DIR;
target->u.dir.path = tmp.xpath; target->u.dir.path = tmp.xpath;
if (server_xtn->query (httpd, client->server, req, tmp.xpath, QSE_HTTPD_SERVERSTD_DIRHEAD, &target->u.dir.head) <= -1) target->u.dir.head = QSE_NULL; if (server_xtn->query (httpd, client->server, QSE_HTTPD_SERVERSTD_DIRHEAD, &qinfo, &target->u.dir.head) <= -1) target->u.dir.head = QSE_NULL;
if (server_xtn->query (httpd, client->server, req, tmp.xpath, QSE_HTTPD_SERVERSTD_DIRFOOT, &target->u.dir.foot) <= -1) target->u.dir.foot = QSE_NULL; if (server_xtn->query (httpd, client->server, QSE_HTTPD_SERVERSTD_DIRFOOT, &qinfo, &target->u.dir.foot) <= -1) target->u.dir.foot = QSE_NULL;
} }
else else
{ {
target->type = QSE_HTTPD_RSRC_FILE; target->type = QSE_HTTPD_RSRC_FILE;
target->u.file.path = tmp.xpath; target->u.file.path = tmp.xpath;
if (server_xtn->query (httpd, client->server, req, tmp.xpath, QSE_HTTPD_SERVERSTD_MIME, &target->u.file.mime) <= -1) if (server_xtn->query (httpd, client->server, QSE_HTTPD_SERVERSTD_MIME, &qinfo, &target->u.file.mime) <= -1)
{ {
/* don't care about failure */ /* don't care about failure */
target->u.file.mime = QSE_NULL; target->u.file.mime = QSE_NULL;
@ -3026,8 +3061,9 @@ static struct cgi_tab_t cgitab[] =
static int query_server ( static int query_server (
qse_httpd_t* httpd, qse_httpd_server_t* server, qse_httpd_t* httpd, qse_httpd_server_t* server,
qse_htre_t* req, const qse_mchar_t* xpath, qse_httpd_serverstd_query_code_t code,
qse_httpd_serverstd_query_code_t code, void* result) const qse_httpd_serverstd_query_info_t* qinfo,
void* result)
{ {
qse_size_t i; qse_size_t i;
@ -3077,7 +3113,7 @@ static int query_server (
qse_httpd_serverstd_cgi_t* cgi = (qse_httpd_serverstd_cgi_t*)result; qse_httpd_serverstd_cgi_t* cgi = (qse_httpd_serverstd_cgi_t*)result;
for (i = 0; i < QSE_COUNTOF(cgitab); i++) for (i = 0; i < QSE_COUNTOF(cgitab); i++)
{ {
if (qse_mbsend (xpath, cgitab[i].suffix)) if (qse_mbsend (qinfo->xpath, cgitab[i].suffix))
{ {
QSE_MEMCPY (cgi, &cgitab[i].cgi, QSE_SIZEOF(*cgi)); QSE_MEMCPY (cgi, &cgitab[i].cgi, QSE_SIZEOF(*cgi));
return 0; return 0;
@ -3092,7 +3128,7 @@ static int query_server (
/* TODO: binary search if the table is large */ /* TODO: binary search if the table is large */
for (i = 0; i < QSE_COUNTOF(mimetab); i++) for (i = 0; i < QSE_COUNTOF(mimetab); i++)
{ {
if (qse_mbsend (xpath, mimetab[i].suffix)) if (qse_mbsend (qinfo->xpath, mimetab[i].suffix))
{ {
*(const qse_mchar_t**)result = mimetab[i].type; *(const qse_mchar_t**)result = mimetab[i].type;
return 0; return 0;
@ -3108,7 +3144,7 @@ static int query_server (
/* i don't allow PUT or DELET by default. /* i don't allow PUT or DELET by default.
* override this query result if you want to change * override this query result if you want to change
* the behavior. */ * the behavior. */
switch (qse_htre_getqmethodtype(req)) switch (qse_htre_getqmethodtype(qinfo->req))
{ {
case QSE_HTTP_OPTIONS: case QSE_HTTP_OPTIONS:
case QSE_HTTP_HEAD: case QSE_HTTP_HEAD:

View File

@ -390,8 +390,8 @@ qse_httpd_task_t* qse_httpd_entaskrsrc (
task = qse_httpd_entaskdir (httpd, client, pred, &rsrc->u.dir, req); task = qse_httpd_entaskdir (httpd, client, pred, &rsrc->u.dir, req);
break; break;
case QSE_HTTPD_RSRC_ERR: case QSE_HTTPD_RSRC_ERROR:
task = qse_httpd_entaskerr (httpd, client, pred, rsrc->u.err.code, req); task = qse_httpd_entaskerr (httpd, client, pred, rsrc->u.error.code, req);
break; break;
case QSE_HTTPD_RSRC_FILE: case QSE_HTTPD_RSRC_FILE: