From bfeb437225c844d347c1dcbd394b60361139a363 Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Thu, 4 Sep 2014 16:55:45 +0000 Subject: [PATCH] added qse_httpd_mod_t and supporting functions --- qse/cmd/http/httpd.c | 286 ++++++++++++++------------------ qse/include/qse/awk/awk.h | 6 +- qse/include/qse/http/httpd.h | 49 +++++- qse/include/qse/http/stdhttpd.h | 2 +- qse/lib/http/httpd-proxy.c | 7 +- qse/lib/http/httpd-std-mod.h | 140 ++++------------ qse/lib/http/httpd.c | 73 +++++++- 7 files changed, 285 insertions(+), 278 deletions(-) diff --git a/qse/cmd/http/httpd.c b/qse/cmd/http/httpd.c index d57da402..d9dd7706 100644 --- a/qse/cmd/http/httpd.c +++ b/qse/cmd/http/httpd.c @@ -197,6 +197,7 @@ struct loccfg_t int dns_retries; int urs_timeout; int urs_retries; + qse_httpd_mod_t* urs_prerewrite_mod; qse_mchar_t pseudonym[128]; /* TODO: good size? */ } proxy; @@ -214,7 +215,6 @@ struct server_hostcfg_t typedef struct server_xtn_t server_xtn_t; struct server_xtn_t { - int tproxy; int nodir; /* no directory listing */ int num; @@ -363,44 +363,15 @@ static int make_resource ( server_xtn = qse_httpd_getserverstdxtn (httpd, client->server); -#if 0 - if (server_xtn->tproxy) + if (server_xtn->orgmakersrc (httpd, client, req, rsrc) <= -1) return -1; + if (server_xtn->nodir && rsrc->type == QSE_HTTPD_RSRC_DIR) { - if (client->status & QSE_HTTPD_CLIENT_INTERCEPTED) - { - rsrc->type = QSE_HTTPD_RSRC_PROXY; - rsrc->u.proxy.flags = 0; - rsrc->u.proxy.dst.nwad = client->orgdst_addr; - rsrc->u.proxy.src.nwad = client->remote_addr; - - qse_setnwadport (&rsrc->u.proxy.src.nwad, 0); - } - else - { - /* TODO: implement a better check that the - * destination is not one of the local addresses */ - - rsrc->type = QSE_HTTPD_RSRC_ERROR; - rsrc->u.error.code = 500; - } - - return 0; + /* prohibit no directory listing */ + server_xtn->orgfreersrc (httpd, client, req, rsrc); + rsrc->type = QSE_HTTPD_RSRC_ERROR; + rsrc->u.error.code = 403; } - else - { -#endif - if (server_xtn->orgmakersrc (httpd, client, req, rsrc) <= -1) return -1; - if (server_xtn->nodir && rsrc->type == QSE_HTTPD_RSRC_DIR) - { - /* prohibit no directory listing */ - server_xtn->orgfreersrc (httpd, client, req, rsrc); - rsrc->type = QSE_HTTPD_RSRC_ERROR; - rsrc->u.error.code = 403; - } - return 0; -#if 0 - } -#endif + return 0; } static void free_resource ( @@ -410,19 +381,7 @@ static void free_resource ( server_xtn_t* server_xtn; server_xtn = qse_httpd_getserverstdxtn (httpd, client->server); - -#if 0 - if (server_xtn->tproxy) - { - /* nothing to do */ - } - else - { -#endif - server_xtn->orgfreersrc (httpd, client, req, rsrc); -#if 0 - } -#endif + server_xtn->orgfreersrc (httpd, client, req, rsrc); } /* --------------------------------------------------------------------- */ @@ -477,6 +436,8 @@ static int get_server_root ( if ((qinfo->client->status & QSE_HTTPD_CLIENT_INTERCEPTED) /*&& loccfg->proxy.allow_intercept */) { + /* transparent proxying */ + root->type = QSE_HTTPD_SERVERSTD_ROOT_PROXY; root->u.proxy.dst.nwad = qinfo->client->orgdst_addr; /* if TPROXY is used, set the source to the original source. @@ -611,6 +572,7 @@ proxy_ok: root->u.proxy.urs_server.nwad = loccfg->proxy.urs_nwad; root->u.proxy.urs_server.tmout.sec = loccfg->proxy.urs_timeout; root->u.proxy.urs_server.retries = loccfg->proxy.urs_retries; + root->u.proxy.urs_prerewrite_mod = loccfg->proxy.urs_prerewrite_mod; } return 0; @@ -1413,7 +1375,6 @@ static int load_loccfg_proxy (qse_httpd_t* httpd, qse_xli_t* xli, qse_xli_list_t 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 */ @@ -1503,6 +1464,16 @@ static int load_loccfg_proxy (qse_httpd_t* httpd, qse_xli_t* xli, qse_xli_list_t if (pair) cfg->proxy.urs_retries = get_integer ((qse_xli_str_t*)pair->val); else cfg->proxy.urs_retries = -1; + pair = QSE_NULL; + if (proxy) pair = qse_xli_findpair (xli, proxy, QSE_T("urs-prerewrite-hook")); + if (!pair && default_proxy) pair = qse_xli_findpair (xli, default_proxy, QSE_T("urs-prerewrite-hook")); + if (pair) + { + cfg->proxy.urs_prerewrite_mod = qse_httpd_findmod (httpd, ((qse_xli_str_t*)pair->val)->ptr); + if (!cfg->proxy.urs_prerewrite_mod) + qse_printf (QSE_T("WARNING: urs-prerewrite-hook not found - %s\n"), ((qse_xli_str_t*)pair->val)->ptr); + } + return 0; } @@ -1823,115 +1794,116 @@ static int open_config_file (qse_httpd_t* httpd) qse_xli_scm_t scm; } defs[] = { - { QSE_T("name"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, - { QSE_T("max-nofile"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, - { QSE_T("max-nproc"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, + { QSE_T("name"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, + { QSE_T("max-nofile"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, + { QSE_T("max-nproc"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, - { QSE_T("hooks"), { QSE_XLI_SCM_VALLIST | QSE_XLI_SCM_KEYNODUP, 0, 0 } }, - { QSE_T("hooks.module"), { QSE_XLI_SCM_VALLIST | QSE_XLI_SCM_KEYALIAS, 0, 0 } }, - { QSE_T("hooks.module.file"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, - /*{ QSE_T("hooks.module.config"), { QSE_XLI_SCM_VALLIST | QSE_XLI_SCM_KEYNODUP | QSE_SLI_SCM_SKIPVALIDATE, 0, 0 } },*/ + { QSE_T("hooks"), { QSE_XLI_SCM_VALLIST | QSE_XLI_SCM_KEYNODUP, 0, 0 } }, + { QSE_T("hooks.module"), { QSE_XLI_SCM_VALLIST | QSE_XLI_SCM_KEYALIAS, 0, 0 } }, + { QSE_T("hooks.module.file"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, + /*{ QSE_T("hooks.module.config"), { QSE_XLI_SCM_VALLIST | QSE_XLI_SCM_KEYNODUP | QSE_SLI_SCM_SKIPVALIDATE, 0, 0 } },*/ - { QSE_T("server-default"), { QSE_XLI_SCM_VALLIST | QSE_XLI_SCM_KEYNODUP, 0, 0 } }, - { QSE_T("server-default.ssl-cert-file"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, - { QSE_T("server-default.ssl-key-file"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, - { QSE_T("server-default.root"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, - { QSE_T("server-default.realm"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 0, 1 } }, - { QSE_T("server-default.auth"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 0, 1 } }, - { QSE_T("server-default.index"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 0xFFFF } }, - { QSE_T("server-default.auth-rule"), { QSE_XLI_SCM_VALLIST | QSE_XLI_SCM_KEYNODUP, 0, 0 } }, - { QSE_T("server-default.auth-rule.prefix"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 1, 1 } }, - { QSE_T("server-default.auth-rule.suffix"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 1, 1 } }, - { QSE_T("server-default.auth-rule.name"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 1, 1 } }, - { QSE_T("server-default.auth-rule.other"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, - { QSE_T("server-default.cgi"), { QSE_XLI_SCM_VALLIST | QSE_XLI_SCM_KEYNODUP, 0, 0 } }, - { QSE_T("server-default.cgi.prefix"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 0, 2 } }, - { QSE_T("server-default.cgi.suffix"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 0, 2 } }, - { QSE_T("server-default.cgi.name"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 0, 2 } }, - { QSE_T("server-default.mime"), { QSE_XLI_SCM_VALLIST | QSE_XLI_SCM_KEYNODUP, 0, 0 } }, - { QSE_T("server-default.mime.prefix"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 1, 1 } }, - { QSE_T("server-default.mime.suffix"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 1, 1 } }, - { QSE_T("server-default.mime.name"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 1, 1 } }, - { QSE_T("server-default.mime.other"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, - { QSE_T("server-default.dir-access"), { QSE_XLI_SCM_VALLIST | QSE_XLI_SCM_KEYNODUP, 0, 0 } }, - { QSE_T("server-default.dir-access.prefix"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 1, 1 } }, - { QSE_T("server-default.dir-access.suffix"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 1, 1 } }, - { QSE_T("server-default.dir-access.name"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 1, 1 } }, - { QSE_T("server-default.dir-access.other"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, - { QSE_T("server-default.file-access"), { QSE_XLI_SCM_VALLIST | QSE_XLI_SCM_KEYNODUP, 0, 0 } }, - { QSE_T("server-default.file-access.prefix"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 1, 1 } }, - { QSE_T("server-default.file-access.suffix"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 1, 1 } }, - { QSE_T("server-default.file-access.name"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 1, 1 } }, - { QSE_T("server-default.file-access.other"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, - { QSE_T("server-default.dir-head"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, - { QSE_T("server-default.dir-foot"), { 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.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-enabled"), { 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-enabled"), { 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-default"), { QSE_XLI_SCM_VALLIST | QSE_XLI_SCM_KEYNODUP, 0, 0 } }, + { QSE_T("server-default.ssl-cert-file"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, + { QSE_T("server-default.ssl-key-file"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, + { QSE_T("server-default.root"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, + { QSE_T("server-default.realm"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 0, 1 } }, + { QSE_T("server-default.auth"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 0, 1 } }, + { QSE_T("server-default.index"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 0xFFFF } }, + { QSE_T("server-default.auth-rule"), { QSE_XLI_SCM_VALLIST | QSE_XLI_SCM_KEYNODUP, 0, 0 } }, + { QSE_T("server-default.auth-rule.prefix"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 1, 1 } }, + { QSE_T("server-default.auth-rule.suffix"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 1, 1 } }, + { QSE_T("server-default.auth-rule.name"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 1, 1 } }, + { QSE_T("server-default.auth-rule.other"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, + { QSE_T("server-default.cgi"), { QSE_XLI_SCM_VALLIST | QSE_XLI_SCM_KEYNODUP, 0, 0 } }, + { QSE_T("server-default.cgi.prefix"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 0, 2 } }, + { QSE_T("server-default.cgi.suffix"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 0, 2 } }, + { QSE_T("server-default.cgi.name"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 0, 2 } }, + { QSE_T("server-default.mime"), { QSE_XLI_SCM_VALLIST | QSE_XLI_SCM_KEYNODUP, 0, 0 } }, + { QSE_T("server-default.mime.prefix"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 1, 1 } }, + { QSE_T("server-default.mime.suffix"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 1, 1 } }, + { QSE_T("server-default.mime.name"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 1, 1 } }, + { QSE_T("server-default.mime.other"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, + { QSE_T("server-default.dir-access"), { QSE_XLI_SCM_VALLIST | QSE_XLI_SCM_KEYNODUP, 0, 0 } }, + { QSE_T("server-default.dir-access.prefix"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 1, 1 } }, + { QSE_T("server-default.dir-access.suffix"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 1, 1 } }, + { QSE_T("server-default.dir-access.name"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 1, 1 } }, + { QSE_T("server-default.dir-access.other"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, + { QSE_T("server-default.file-access"), { QSE_XLI_SCM_VALLIST | QSE_XLI_SCM_KEYNODUP, 0, 0 } }, + { QSE_T("server-default.file-access.prefix"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 1, 1 } }, + { QSE_T("server-default.file-access.suffix"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 1, 1 } }, + { QSE_T("server-default.file-access.name"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 1, 1 } }, + { QSE_T("server-default.file-access.other"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, + { QSE_T("server-default.dir-head"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, + { QSE_T("server-default.dir-foot"), { 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.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-enabled"), { 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-enabled"), { 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-default.proxy.urs-prerewrite-hook"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, - { 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.ssl"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, - { QSE_T("server.ssl-cert-file"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, - { QSE_T("server.ssl-key-file"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, - { QSE_T("server.host"), { QSE_XLI_SCM_VALLIST | QSE_XLI_SCM_KEYALIAS, 0, 0 } }, - { QSE_T("server.host.location"), { QSE_XLI_SCM_VALLIST | QSE_XLI_SCM_KEYALIAS, 0, 0 } }, - { QSE_T("server.host.location.root"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 0, 1 } }, - { QSE_T("server.host.location.realm"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 0, 1 } }, - { QSE_T("server.host.location.auth"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, - { QSE_T("server.host.location.index"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 0xFFFF } }, - { QSE_T("server.host.location.auth-rule"), { QSE_XLI_SCM_VALLIST | QSE_XLI_SCM_KEYNODUP, 0, 0 } }, - { QSE_T("server.host.location.auth-rule.prefix"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 1, 1 } }, - { QSE_T("server.host.location.auth-rule.suffix"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 1, 1 } }, - { QSE_T("server.host.location.auth-rule.name"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 1, 1 } }, - { QSE_T("server.host.location.auth-rule.other"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, - { QSE_T("server.host.location.cgi"), { QSE_XLI_SCM_VALLIST | QSE_XLI_SCM_KEYNODUP, 0, 0 } }, - { QSE_T("server.host.location.cgi.prefix"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 0, 2 } }, - { QSE_T("server.host.location.cgi.suffix"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 0, 2 } }, - { QSE_T("server.host.location.cgi.name"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 0, 2 } }, - { QSE_T("server.host.location.mime"), { QSE_XLI_SCM_VALLIST | QSE_XLI_SCM_KEYNODUP, 0, 0 } }, - { QSE_T("server.host.location.mime.prefix"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 1, 1 } }, - { QSE_T("server.host.location.mime.suffix"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 1, 1 } }, - { QSE_T("server.host.location.mime.name"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 1, 1 } }, - { QSE_T("server.host.location.mime.other"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, - { QSE_T("server.host.location.dir-access"), { QSE_XLI_SCM_VALLIST | QSE_XLI_SCM_KEYNODUP, 0, 0 } }, - { QSE_T("server.host.location.dir-access.prefix"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 1, 1 } }, - { QSE_T("server.host.location.dir-access.suffix"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 1, 1 } }, - { QSE_T("server.host.location.dir-access.name"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 1, 1 } }, - { QSE_T("server.host.location.dir-access.other"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, - { QSE_T("server.host.location.file-access"), { QSE_XLI_SCM_VALLIST | QSE_XLI_SCM_KEYNODUP, 0, 0 } }, - { QSE_T("server.host.location.file-access.prefix"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 1, 1 } }, - { QSE_T("server.host.location.file-access.suffix"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 1, 1 } }, - { QSE_T("server.host.location.file-access.name"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 1, 1 } }, - { QSE_T("server.host.location.file-access.other"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, - { QSE_T("server.host.location.dir-head"), { 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-foot"), { 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-enabled"), { 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-enabled"), { 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 } }, - { QSE_T("server.host.location.proxy.urs-prerewrite"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } } + { 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.ssl"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, + { QSE_T("server.ssl-cert-file"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, + { QSE_T("server.ssl-key-file"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, + { QSE_T("server.host"), { QSE_XLI_SCM_VALLIST | QSE_XLI_SCM_KEYALIAS, 0, 0 } }, + { QSE_T("server.host.location"), { QSE_XLI_SCM_VALLIST | QSE_XLI_SCM_KEYALIAS, 0, 0 } }, + { QSE_T("server.host.location.root"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 0, 1 } }, + { QSE_T("server.host.location.realm"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 0, 1 } }, + { QSE_T("server.host.location.auth"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, + { QSE_T("server.host.location.index"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 0xFFFF } }, + { QSE_T("server.host.location.auth-rule"), { QSE_XLI_SCM_VALLIST | QSE_XLI_SCM_KEYNODUP, 0, 0 } }, + { QSE_T("server.host.location.auth-rule.prefix"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 1, 1 } }, + { QSE_T("server.host.location.auth-rule.suffix"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 1, 1 } }, + { QSE_T("server.host.location.auth-rule.name"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 1, 1 } }, + { QSE_T("server.host.location.auth-rule.other"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, + { QSE_T("server.host.location.cgi"), { QSE_XLI_SCM_VALLIST | QSE_XLI_SCM_KEYNODUP, 0, 0 } }, + { QSE_T("server.host.location.cgi.prefix"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 0, 2 } }, + { QSE_T("server.host.location.cgi.suffix"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 0, 2 } }, + { QSE_T("server.host.location.cgi.name"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 0, 2 } }, + { QSE_T("server.host.location.mime"), { QSE_XLI_SCM_VALLIST | QSE_XLI_SCM_KEYNODUP, 0, 0 } }, + { QSE_T("server.host.location.mime.prefix"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 1, 1 } }, + { QSE_T("server.host.location.mime.suffix"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 1, 1 } }, + { QSE_T("server.host.location.mime.name"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 1, 1 } }, + { QSE_T("server.host.location.mime.other"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, + { QSE_T("server.host.location.dir-access"), { QSE_XLI_SCM_VALLIST | QSE_XLI_SCM_KEYNODUP, 0, 0 } }, + { QSE_T("server.host.location.dir-access.prefix"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 1, 1 } }, + { QSE_T("server.host.location.dir-access.suffix"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 1, 1 } }, + { QSE_T("server.host.location.dir-access.name"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 1, 1 } }, + { QSE_T("server.host.location.dir-access.other"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, + { QSE_T("server.host.location.file-access"), { QSE_XLI_SCM_VALLIST | QSE_XLI_SCM_KEYNODUP, 0, 0 } }, + { QSE_T("server.host.location.file-access.prefix"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 1, 1 } }, + { QSE_T("server.host.location.file-access.suffix"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 1, 1 } }, + { QSE_T("server.host.location.file-access.name"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYALIAS, 1, 1 } }, + { QSE_T("server.host.location.file-access.other"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } }, + { QSE_T("server.host.location.dir-head"), { 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-foot"), { 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-enabled"), { 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-enabled"), { 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 } }, + { QSE_T("server.host.location.proxy.urs-prerewrite-hook"), { QSE_XLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } } }; diff --git a/qse/include/qse/awk/awk.h b/qse/include/qse/awk/awk.h index 33663513..da671f9c 100644 --- a/qse/include/qse/awk/awk.h +++ b/qse/include/qse/awk/awk.h @@ -847,10 +847,10 @@ typedef void (*qse_awk_mod_fini_t) ( struct qse_awk_mod_t { qse_awk_mod_query_t query; - qse_awk_mod_unload_t unload; + qse_awk_mod_unload_t unload; /* unload the module */ - qse_awk_mod_init_t init; - qse_awk_mod_fini_t fini; + qse_awk_mod_init_t init; /* per-rtx initialization */ + qse_awk_mod_fini_t fini; /* per-rtx finalization */ void* ctx; }; diff --git a/qse/include/qse/http/httpd.h b/qse/include/qse/http/httpd.h index eb346d6c..cee1cabd 100644 --- a/qse/include/qse/http/httpd.h +++ b/qse/include/qse/http/httpd.h @@ -89,15 +89,55 @@ enum qse_httpd_trait_t }; typedef enum qse_httpd_trait_t qse_httpd_trait_t; +#if !defined(QSE_HTTPD_DEFAULT_MODPREFIX) +# if defined(_WIN32) +# define QSE_HTTPD_DEFAULT_MODPREFIX "qsehttpd-" +# elif defined(__OS2__) +# define QSE_HTTPD_DEFAULT_MODPREFIX "htd-" +# elif defined(__DOS__) +# define QSE_HTTPD_DEFAULT_MODPREFIX "htd-" +# else +# define QSE_HTTPD_DEFAULT_MODPREFIX "libqsehttpd-" +# endif +#endif + +#if !defined(QSE_HTTPD_DEFAULT_MODPOSTFIX) +# define QSE_HTTPD_DEFAULT_MODPOSTFIX "" +#endif typedef struct qse_httpd_mod_t qse_httpd_mod_t; + +typedef int (*qse_httpd_mod_load_t) ( + qse_httpd_mod_t* mod +); + +typedef int (*qse_httpd_mod_unload_t) ( + qse_httpd_mod_t* mod +); + +typedef int (*qse_httpd_mod_urs_prerewrite_t) ( + qse_httpd_mod_t* mod, + qse_httpd_client_t* client, + qse_htre_t* req, + const qse_mchar_t* host, + qse_mchar_t** url +); + struct qse_httpd_mod_t { - /* set before mod.open() */ - qse_char_t* name; + /* set before mod.open(). + * mod.open() and other callbacks can refer to these. */ + qse_httpd_t* httpd; + qse_char_t* name; /* portable module name */ + qse_char_t* fullname; /* name to use when loading module from the system. */ - /* manipulatable by the implementer */ - void* handle; + /* mod.open() may set this */ + void* handle; /* mod.open() can set this */ + + /* module's entry point may set these items */ + void* ctx; + qse_httpd_mod_unload_t unload; + qse_httpd_mod_urs_prerewrite_t urs_prerewrite; /* private */ qse_httpd_mod_t* next; @@ -686,6 +726,7 @@ struct qse_httpd_rsrc_proxy_t qse_httpd_natr_t dns_server; qse_httpd_natr_t urs_server; + qse_httpd_mod_t* urs_prerewrite_mod; /* optional pseudonym to use for Via: */ const qse_mchar_t* pseudonym; diff --git a/qse/include/qse/http/stdhttpd.h b/qse/include/qse/http/stdhttpd.h index 590287ed..3e8ff971 100644 --- a/qse/include/qse/http/stdhttpd.h +++ b/qse/include/qse/http/stdhttpd.h @@ -64,7 +64,7 @@ struct qse_httpd_serverstd_root_t const qse_mchar_t* mime; } text; - struct qse_httpd_rsrc_proxy_t proxy; + qse_httpd_rsrc_proxy_t proxy; struct { diff --git a/qse/lib/http/httpd-proxy.c b/qse/lib/http/httpd-proxy.c index 4c40d3df..7625d826 100644 --- a/qse/lib/http/httpd-proxy.c +++ b/qse/lib/http/httpd-proxy.c @@ -975,7 +975,12 @@ static int task_init_proxy ( if (arg->rsrc->flags & QSE_HTTPD_RSRC_PROXY_ENABLE_URS) { - int x = httpd->opt.scb.urs.prerewrite (httpd, client, arg->req, arg->rsrc->host, &proxy->url_to_rewrite); + int x; + + if (arg->rsrc->urs_prerewrite_mod && arg->rsrc->urs_prerewrite_mod->urs_prerewrite) + x = arg->rsrc->urs_prerewrite_mod->urs_prerewrite (arg->rsrc->urs_prerewrite_mod, client, arg->req, arg->rsrc->host, &proxy->url_to_rewrite); + else + x = httpd->opt.scb.urs.prerewrite (httpd, client, arg->req, arg->rsrc->host, &proxy->url_to_rewrite); if (x <= -1) goto oops; printf (">>>>>>>>>>>>>>>>>>>>>>>> [%s] <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n", proxy->url_to_rewrite); diff --git a/qse/lib/http/httpd-std-mod.h b/qse/lib/http/httpd-std-mod.h index e48c9c1e..e6d7e17e 100644 --- a/qse/lib/http/httpd-std-mod.h +++ b/qse/lib/http/httpd-std-mod.h @@ -1,50 +1,17 @@ -#if !defined(QSE_HTTPD_DEFAULT_MODPREFIX) -# if defined(_WIN32) -# define QSE_HTTPD_DEFAULT_MODPREFIX "qsehttpd-" -# elif defined(__OS2__) -# define QSE_HTTPD_DEFAULT_MODPREFIX "htd-" -# elif defined(__DOS__) -# define QSE_HTTPD_DEFAULT_MODPREFIX "htd-" -# else -# define QSE_HTTPD_DEFAULT_MODPREFIX "libqsehttpd-" -# endif -#endif - -#if !defined(QSE_HTTPD_DEFAULT_MODPOSTFIX) -# define QSE_HTTPD_DEFAULT_MODPOSTFIX "" -#endif static int mod_open (qse_httpd_t* httpd, qse_httpd_mod_t* mod) { #if defined(USE_LTDL) void* h; - qse_mchar_t* modpath; - const qse_char_t* tmp[4]; - int count; - count = 0; - if (spec->prefix) tmp[count++] = spec->prefix; - tmp[count++] = mod->name; - if (spec->postfix) tmp[count++] = spec->postfix; - tmp[count] = QSE_NULL; - - #if defined(QSE_CHAR_IS_MCHAR) - modpath = qse_mbsadup (tmp, QSE_NULL, httpd->mmgr); - #else - modpath = qse_wcsatombsdup (tmp, QSE_NULL, httpd->mmgr); - #endif - if (!modpath) + h = lt_dlopenext (mod->fullname); + if (h == QSE_NULL) { - qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOMEM, QSE_NULL); + qse_httpd_seterrnum (httpd, syserr_to_errnum(errno)); return -1; } - h = lt_dlopenext (modpath); - - QSE_MMGR_FREE (httpd->mmgr, modpath); - - if (h == QSE_NULL) return -1; mod->handle = h; return 0; @@ -52,69 +19,42 @@ static int mod_open (qse_httpd_t* httpd, qse_httpd_mod_t* mod) #elif defined(_WIN32) HMODULE h; - qse_char_t* modpath; - const qse_char_t* tmp[4]; - int count; - count = 0; - if (spec->prefix) tmp[count++] = spec->prefix; - tmp[count++] = spec->name; - if (spec->postfix) tmp[count++] = spec->postfix; - tmp[count] = QSE_NULL; + QSE_ASSERT (QSE_SIZEOF(h) <= QSE_SIZEOF(void*)); - modpath = qse_stradup (tmp, QSE_NULL, httpd->mmgr); - if (!modpath) + h = LoadLibrary (mod->fullname); + if (h == QSE_NULL) { - qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOMEM, QSE_NULL); + qse_httpd_seterrnum (httpd, syserr_to_errnum(GetLastError())); return -1; } - h = LoadLibrary (modpath); - - QSE_MMGR_FREE (httpd->mmgr, modpath); - - QSE_ASSERT (QSE_SIZEOF(h) <= QSE_SIZEOF(void*)); - - if (h == QSE_NULL) return -1; mod->handle = h; return 0; #elif defined(__OS2__) HMODULE h; - qse_mchar_t* modpath; - const qse_char_t* tmp[4]; - int count; char errbuf[CCHMAXPATH]; APIRET rc; - count = 0; - if (spec->prefix) tmp[count++] = spec->prefix; - tmp[count++] = spec->name; - if (spec->postfix) tmp[count++] = spec->postfix; - tmp[count] = QSE_NULL; - - #if defined(QSE_CHAR_IS_MCHAR) - modpath = qse_mbsadup (tmp, QSE_NULL, httpd->mmgr); - #else - modpath = qse_wcsatombsdup (tmp, QSE_NULL, httpd->mmgr); - #endif - if (!modpath) - { - qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOMEM, QSE_NULL); - return -1; - } + QSE_ASSERT (QSE_SIZEOF(h) <= QSE_SIZEOF(void*)); /* DosLoadModule() seems to have severe limitation on * the file name it can load (max-8-letters.xxx) */ rc = DosLoadModule (errbuf, QSE_COUNTOF(errbuf) - 1, modpath, &h); - if (rc != NO_ERROR) h = QSE_NULL; + if (rc != NO_ERROR) + { + qse_httpd_seterrnum (httpd, syserr_to_errnum(rc)); + return -1; + } - QSE_MMGR_FREE (httpd->mmgr, modpath); + if (h == QSE_NULL) + { + qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOENT); /* is this error code ok? */ + return -1; + } - QSE_ASSERT (QSE_SIZEOF(h) <= QSE_SIZEOF(void*)); - - if (h == QSE_NULL) return -1; mod->handle = h; return 0; @@ -125,34 +65,14 @@ static int mod_open (qse_httpd_t* httpd, qse_httpd_mod_t* mod) * dos-extender only. the best is to enable QSE_ENABLE_STATIC_MODULE * when building for DOS. */ void* h; - qse_mchar_t* modpath; - const qse_char_t* tmp[4]; - int count; - - count = 0; - if (spec->prefix) tmp[count++] = spec->prefix; - tmp[count++] = spec->name; - if (spec->postfix) tmp[count++] = spec->postfix; - tmp[count] = QSE_NULL; - - #if defined(QSE_CHAR_IS_MCHAR) - modpath = qse_mbsadup (tmp, QSE_NULL, httpd->mmgr); - #else - modpath = qse_wcsatombsdup (tmp, QSE_NULL, httpd->mmgr); - #endif - if (!modpath) - { - qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOMEM, QSE_NULL); - return 01; - } h = LoadModule (modpath); + if (h == QSE_NULL) + { + qse_httpd_seterrnum (httpd, syserr_to_errnum(errno)); + return -1; + } - QSE_MMGR_FREE (httpd->mmgr, modpath); - - QSE_ASSERT (QSE_SIZEOF(h) <= QSE_SIZEOF(void*)); - - if (h == QSE_NULL) return -1; mod->handle = h; return 0; @@ -195,14 +115,26 @@ static void* mod_symbol (qse_httpd_t* httpd, qse_httpd_mod_t* handle, const qse_ #if defined(USE_LTDL) s = lt_dlsym (mod->handle, mname); + if (s == QSE_NULL) qse_httpd_seterrnum (httpd, syserr_to_errnum(errno)); #elif defined(_WIN32) s = GetProcAddress ((HMODULE)mod->handle, mname); + if (s == QSE_NULL) qse_httpd_seterrnum (httpd, syserr_to_errnum(GetLastError())); #elif defined(__OS2__) - if (DosQueryProcAddr ((HMODULE)mod->handle, 0, mname, (PFN*)&s) != NO_ERROR) s = QSE_NULL; + { + APIRET rc; + rc = DosQueryProcAddr ((HMODULE)mod->handle, 0, mname, (PFN*)&s); + if (rc != NO_ERROR) + { + qse_httpd_seterrnum (httpd, syserr_to_errnum(rc)); + s = QSE_NULL; + } + } #elif defined(__DOS__) s = GetProcAddress (mod->handle, mname); + if (s == QSE_NULL) qse_httpd_seterrnum (httpd, syserr_to_errnum(errno)); #else s = QSE_NULL; + qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOIMPL); #endif #if defined(QSE_CHAR_IS_MCHAR) diff --git a/qse/lib/http/httpd.c b/qse/lib/http/httpd.c index 163c23a9..cc99f0a0 100644 --- a/qse/lib/http/httpd.c +++ b/qse/lib/http/httpd.c @@ -217,7 +217,6 @@ int qse_httpd_setopt (qse_httpd_t* httpd, qse_httpd_opt_t id, const void* value) httpd->opt.rcb = *(qse_httpd_rcb_t*)value; return 0; - } httpd->errnum = QSE_HTTPD_EINVAL; @@ -1900,7 +1899,7 @@ static void unload_all_modules (qse_httpd_t* httpd) mod = httpd->modlist; httpd->modlist = mod->next; -/* call fini */ + if (mod->unload) mod->unload (mod); httpd->opt.scb.mod.close (httpd, mod); qse_httpd_freemem (httpd, mod); } @@ -1909,29 +1908,87 @@ static void unload_all_modules (qse_httpd_t* httpd) int qse_httpd_loadmod (qse_httpd_t* httpd, const qse_char_t* name) { qse_httpd_mod_t* mod; - qse_size_t name_len; + qse_size_t name_len, prefix_len, postfix_len, fullname_len; + const qse_char_t* prefix, * postfix; + qse_char_t* entry_point_name; + qse_httpd_mod_load_t load; /* TODO: no singly linked list speed up */ + name_len = qse_strlen(name); - mod = qse_httpd_allocmem (httpd, QSE_SIZEOF(*mod) + name_len + 1); + if (httpd->opt.mod[0].len > 0) + { + prefix = httpd->opt.mod[0].ptr; + prefix_len = httpd->opt.mod[0].len; + } + else + { + prefix = QSE_T(QSE_HTTPD_DEFAULT_MODPREFIX); + prefix_len = qse_strlen(prefix); + } + + if (httpd->opt.mod[1].len > 0) + { + postfix = httpd->opt.mod[1].ptr; + postfix_len = httpd->opt.mod[1].len; + } + else + { + postfix = QSE_T(QSE_HTTPD_DEFAULT_MODPOSTFIX); + postfix_len = qse_strlen(postfix); + } + + /* + * +15: length of _qse_httpd_mod_ + * +2: _\0 + */ + fullname_len = prefix_len + name_len + postfix_len; + mod = qse_httpd_allocmem (httpd, QSE_SIZEOF(*mod) + (name_len + 1 + fullname_len + 1 + 15 + name_len + 2) * QSE_SIZEOF(qse_char_t)); if (mod == QSE_NULL) return -1; QSE_MEMSET (mod, 0, QSE_SIZEOF(*mod)); - mod->name = mod + 1; - qse_strcpy (mod->name, name); + mod->name = (qse_char_t*)(mod + 1); + mod->fullname = mod->name + name_len + 1; + entry_point_name = mod->fullname + fullname_len + 1; + qse_strcpy (mod->name, name); + qse_strjoin (mod->fullname, prefix, name, postfix, QSE_NULL); + qse_strjoin (entry_point_name, QSE_T("_qse_httpd_mod_"), name, QSE_NULL); + +printf ("%ls %ls %ls\n", mod->name, mod->fullname, entry_point_name); if (httpd->opt.scb.mod.open (httpd, mod) <= -1) { +printf ("FAIL => %ls %ls %ls\n", mod->name, mod->fullname, entry_point_name); qse_httpd_freemem (httpd, mod); return -1; } -/* TODO: find init and execute it. if it fails, unload it. */ +printf ("OK => %ls %ls %ls\n", mod->name, mod->fullname, entry_point_name); + /* attempt qse_httpd_mod_xxx */ + load = httpd->opt.scb.mod.symbol (httpd, mod, &entry_point_name[1]); + if (!load) + { + /* attempt _qse_awk_mod_xxx */ + load = httpd->opt.scb.mod.symbol (httpd, mod, &entry_point_name[0]); + if (!load) + { + /* attempt qse_awk_mod_xxx_ */ + entry_point_name[15 + name_len] = QSE_T('_'); + entry_point_name[15 + name_len + 1] = QSE_T('\0'); + load = httpd->opt.scb.mod.symbol (httpd, mod, &entry_point_name[1]); + } + } + + if (load == QSE_NULL || load (mod) <= -1) + { + httpd->opt.scb.mod.close (httpd, mod); + qse_httpd_freemem (httpd, mod); + return -1; + } mod->next = httpd->modlist; httpd->modlist = mod; - return 0; }