diff --git a/qse/cmd/http/httpd.c b/qse/cmd/http/httpd.c index 8618f0fe..7244c5de 100644 --- a/qse/cmd/http/httpd.c +++ b/qse/cmd/http/httpd.c @@ -2045,7 +2045,8 @@ static qse_httpd_server_t* attach_server (qse_httpd_t* httpd, int num, qse_xli_l static int load_hook_modules (qse_httpd_t* httpd, qse_xli_list_t* hook_list) { qse_char_t buf[32]; - qse_xli_pair_t* pair, * cfg; + qse_xli_pair_t* file, * cfg, * mod; + qse_httpd_mod_t* module; httpd_xtn_t* httpd_xtn; int i; @@ -2055,19 +2056,59 @@ static int load_hook_modules (qse_httpd_t* httpd, qse_xli_list_t* hook_list) for (i = 0; ; i++) { qse_strxfmt (buf, QSE_COUNTOF(buf), QSE_T("module[%d]"), i); - pair = qse_xli_findpair (httpd_xtn->xli, hook_list, buf); - if (pair == QSE_NULL) break; + mod = qse_xli_findpair (httpd_xtn->xli, hook_list, buf); + if (mod == QSE_NULL) break; - pair = qse_xli_findpair (httpd_xtn->xli, (qse_xli_list_t*)pair->val, QSE_T("file")); - if (pair == QSE_NULL) + file = qse_xli_findpair (httpd_xtn->xli, (qse_xli_list_t*)mod->val, QSE_T("file")); + if (file == QSE_NULL) { /* TODO: log warning when file is not found in module */ } else { - cfg = qse_xli_findpair (httpd_xtn->xli, (qse_xli_list_t*)pair->val, QSE_T("config")); - qse_httpd_loadmod (httpd, ((qse_xli_str_t*)pair->val)->ptr, (cfg? cfg->val: QSE_NULL)); - /* TODO: error handling and logging */ + module = qse_httpd_loadmod (httpd, ((qse_xli_str_t*)file->val)->ptr); + if (!module) + { + /* TODO: better error handling and logging */ + qse_printf (QSE_T("WARNING: failed to load module [%s]\n"), ((qse_xli_str_t*)file->val)->ptr); + } + else + { + cfg = qse_xli_findpair (httpd_xtn->xli, (qse_xli_list_t*)mod->val, QSE_T("config")); + if (cfg) + { + if (!module->config) + { + qse_printf (QSE_T("WARNING: unneeded configuration for [%s]. no configuration handler\n"), + ((qse_xli_str_t*)file->val)->ptr); + } + else + { + const qse_xli_atom_t* atom; + const qse_xli_pair_t* pair; + int x; + + for (atom = ((qse_xli_list_t*)(cfg->val))->head; atom; atom = atom->next) + { + if (atom->type != QSE_XLI_PAIR) continue; + pair = (qse_xli_pair_t*)atom; + + if (pair->val->type != QSE_XLI_STR) continue; + x = qse_httpd_configmod (httpd, module, pair->key, ((qse_xli_str_t*)pair->val)->ptr); + if (x <= -1) + { + qse_printf (QSE_T("WARNING: failed to set module configuration [%s] to [%s] for [%s]\n"), + pair->key, ((qse_xli_str_t*)pair->val)->ptr, ((qse_xli_str_t*)file->val)->ptr); + } + else if (x == 0) + { + qse_printf (QSE_T("WARNING: invalid module configuration item [%s] for [%s]\n"), + pair->key, ((qse_xli_str_t*)file->val)->ptr); + } + } + } + } + } } } @@ -2093,8 +2134,8 @@ static int open_config_file (qse_httpd_t* httpd) { 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_XLI_SCM_RELAXED, 0, 0 } }, + { QSE_T("hooks.module.config"), { QSE_XLI_SCM_VALLIST | + QSE_XLI_SCM_KEYNODUP | QSE_XLI_SCM_VALIFFY, 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 } }, diff --git a/qse/include/qse/awk/awk.h b/qse/include/qse/awk/awk.h index ddcc2254..2a561a96 100644 --- a/qse/include/qse/awk/awk.h +++ b/qse/include/qse/awk/awk.h @@ -1452,7 +1452,7 @@ struct qse_awk_nrflt_t }; typedef struct qse_awk_nrflt_t qse_awk_nrflt_t; -#ifdef __cplusplus +#if defined(__cplusplus) extern "C" { #endif @@ -2869,7 +2869,7 @@ QSE_EXPORT qse_awk_val_t* qse_getawknilval ( void ); -#ifdef __cplusplus +#if defined(__cplusplus) } #endif diff --git a/qse/include/qse/cmn/env.h b/qse/include/qse/cmn/env.h index 5004baf5..cd2e548b 100644 --- a/qse/include/qse/cmn/env.h +++ b/qse/include/qse/cmn/env.h @@ -68,7 +68,7 @@ struct qse_env_t }; -#ifdef __cplusplus +#if defined(__cplusplus) extern "C" { #endif @@ -179,7 +179,7 @@ QSE_EXPORT int qse_env_deletembs ( # define qse_env_delete(env,name) qse_env_deletewcs(env,name) #endif -#ifdef __cplusplus +#if defined(__cplusplus) } #endif diff --git a/qse/include/qse/cmn/fio.h b/qse/include/qse/cmn/fio.h index 8ddfa8ee..858e5daa 100644 --- a/qse/include/qse/cmn/fio.h +++ b/qse/include/qse/cmn/fio.h @@ -162,7 +162,7 @@ struct qse_fio_lck_t #define QSE_FIO_HANDLE(fio) ((fio)->handle) -#ifdef __cplusplus +#if defined(__cplusplus) extern "C" { #endif @@ -312,7 +312,7 @@ QSE_EXPORT int qse_getstdfiohandle ( qse_fio_hnd_t* hnd ); -#ifdef __cplusplus +#if defined(__cplusplus) } #endif diff --git a/qse/include/qse/cmn/mux.h b/qse/include/qse/cmn/mux.h index 08420798..cf4d9353 100644 --- a/qse/include/qse/cmn/mux.h +++ b/qse/include/qse/cmn/mux.h @@ -81,7 +81,7 @@ struct qse_mux_evt_t void* data; }; -#ifdef __cplusplus +#if defined(__cplusplus) extern "C" { #endif @@ -124,7 +124,7 @@ QSE_EXPORT int qse_mux_poll ( const qse_ntime_t* tmout ); -#ifdef __cplusplus +#if defined(__cplusplus) } #endif diff --git a/qse/include/qse/cmn/nwad.h b/qse/include/qse/cmn/nwad.h index 6aa5c834..00802e11 100644 --- a/qse/include/qse/cmn/nwad.h +++ b/qse/include/qse/cmn/nwad.h @@ -114,7 +114,7 @@ struct qse_skad_t qse_uintptr_t dummy; }; -#ifdef __cplusplus +#if defined(__cplusplus) extern "C" { #endif @@ -201,7 +201,7 @@ QSE_EXPORT int qse_skadfamily ( const qse_skad_t* skad ); -#ifdef __cplusplus +#if defined(__cplusplus) } #endif diff --git a/qse/include/qse/cmn/pio.h b/qse/include/qse/cmn/pio.h index 7594d008..4c4d7733 100644 --- a/qse/include/qse/cmn/pio.h +++ b/qse/include/qse/cmn/pio.h @@ -218,7 +218,7 @@ struct qse_pio_t /** get the native handle from the #qse_pio_t structure */ #define QSE_PIO_HANDLE(pio,hid) ((pio)->pin[hid].handle) -#ifdef __cplusplus +#if defined(__cplusplus) extern "C" { #endif @@ -410,7 +410,7 @@ QSE_EXPORT int qse_pio_kill ( qse_pio_t* pio /**< pio object */ ); -#ifdef __cplusplus +#if defined(__cplusplus) } #endif diff --git a/qse/include/qse/cmn/str.h b/qse/include/qse/cmn/str.h index 4bc07d25..a4702205 100644 --- a/qse/include/qse/cmn/str.h +++ b/qse/include/qse/cmn/str.h @@ -364,7 +364,7 @@ enum qse_wcsfnmat_flag_t # define QSE_STRFNMAT_IGNORECASE QSE_WCSFNMAT_IGNORECASE #endif -#ifdef __cplusplus +#if defined(__cplusplus) extern "C" { #endif @@ -3318,7 +3318,7 @@ QSE_EXPORT qse_size_t qse_wcs_fmt ( #endif -#ifdef __cplusplus +#if defined(__cplusplus) } #endif diff --git a/qse/include/qse/cmn/tmr.h b/qse/include/qse/cmn/tmr.h index daa68893..ebb17ffe 100644 --- a/qse/include/qse/cmn/tmr.h +++ b/qse/include/qse/cmn/tmr.h @@ -64,7 +64,7 @@ struct qse_tmr_event_t #define QSE_TMR_SIZE(tmr) ((tmr)->size) #define QSE_TMR_CAPA(tmr) ((tmr)->capa); -#ifdef __cplusplus +#if defined(__cplusplus) extern "C" { #endif @@ -142,7 +142,7 @@ QSE_EXPORT qse_tmr_event_t* qse_tmr_getevent ( qse_tmr_index_t index ); -#ifdef __cplusplus +#if defined(__cplusplus) } #endif diff --git a/qse/include/qse/http/htrd.h b/qse/include/qse/http/htrd.h index ba24bae4..e954d67a 100644 --- a/qse/include/qse/http/htrd.h +++ b/qse/include/qse/http/htrd.h @@ -109,7 +109,7 @@ struct qse_htrd_t int clean; }; -#ifdef __cplusplus +#if defined(__cplusplus) extern "C" { #endif @@ -211,7 +211,7 @@ QSE_EXPORT int qse_htrd_scanqparam ( const qse_mcstr_t* cstr ); -#ifdef __cplusplus +#if defined(__cplusplus) } #endif diff --git a/qse/include/qse/http/htre.h b/qse/include/qse/http/htre.h index f1fcc76b..430ec597 100644 --- a/qse/include/qse/http/htre.h +++ b/qse/include/qse/http/htre.h @@ -152,7 +152,7 @@ typedef int (*qse_htre_header_walker_t) ( void* ctx ); -#ifdef __cplusplus +#if defined(__cplusplus) extern "C" { #endif @@ -238,7 +238,7 @@ QSE_EXPORT int qse_htre_perdecqpath ( qse_htre_t* req ); -#ifdef __cplusplus +#if defined(__cplusplus) } #endif diff --git a/qse/include/qse/http/http.h b/qse/include/qse/http/http.h index 211188b5..8e751986 100644 --- a/qse/include/qse/http/http.h +++ b/qse/include/qse/http/http.h @@ -161,7 +161,7 @@ enum qse_perenchttpstr_opt_t }; typedef enum qse_perenchttpstr_opt_t qse_perenchttpstr_opt_t; -#ifdef __cplusplus +#if defined(__cplusplus) extern "C" { #endif @@ -226,7 +226,7 @@ QSE_EXPORT qse_mchar_t* qse_perenchttpstrdup ( qse_mmgr_t* mmgr ); -#ifdef __cplusplus +#if defined(__cplusplus) } #endif diff --git a/qse/include/qse/http/httpd.h b/qse/include/qse/http/httpd.h index 9e748386..fd0c3561 100644 --- a/qse/include/qse/http/httpd.h +++ b/qse/include/qse/http/httpd.h @@ -29,7 +29,6 @@ #include #include #include -#include typedef struct qse_httpd_t qse_httpd_t; typedef struct qse_httpd_mate_t qse_httpd_mate_t; @@ -58,15 +57,17 @@ enum qse_httpd_errnum_t QSE_HTTPD_EPIPE, QSE_HTTPD_EAGAIN, - QSE_HTTPD_ENOSVR, /* no active servers */ - QSE_HTTPD_ECONN, /* connection failure */ - QSE_HTTPD_ESCONN, /* secure connection failure */ - QSE_HTTPD_ENOBUF, /* no buffer available */ - QSE_HTTPD_EDISCON, /* client disconnnected */ - QSE_HTTPD_EBADREQ, /* bad request */ - QSE_HTTPD_ENODNS, /* dns service not activated/enabled or no valid dns server specified */ - QSE_HTTPD_ENOURS, /* urs service not activated/enabled or no valid urs server specified */ - QSE_HTTPD_ETASK + QSE_HTTPD_ENOSVR, /* no active servers */ + QSE_HTTPD_ECONN, /* connection failure */ + QSE_HTTPD_ESCONN, /* secure connection failure */ + QSE_HTTPD_ENOBUF, /* no buffer available */ + QSE_HTTPD_EDISCON, /* client disconnnected */ + QSE_HTTPD_EBADREQ, /* bad request */ + QSE_HTTPD_ENODNS, /* dns service not activated/enabled or no valid dns server specified */ + QSE_HTTPD_ENOURS, /* urs service not activated/enabled or no valid urs server specified */ + QSE_HTTPD_ETASK, /* general error in the task handler */ + QSE_HTTPD_ENOMODCONFIG, /* module doesn't have the config callback */ + QSE_HTTPD_EMODCFGKEY /* module configuration key is invalid or unknown */ }; typedef enum qse_httpd_errnum_t qse_httpd_errnum_t; @@ -103,14 +104,19 @@ typedef enum qse_httpd_trait_t qse_httpd_trait_t; typedef struct qse_httpd_mod_t qse_httpd_mod_t; typedef int (*qse_httpd_mod_load_t) ( - qse_httpd_mod_t* mod, - const qse_xli_list_t* cfg + qse_httpd_mod_t* mod ); typedef void (*qse_httpd_mod_unload_t) ( qse_httpd_mod_t* mod ); +typedef int (*qse_httpd_mod_config_t) ( + qse_httpd_mod_t* mod, + const qse_char_t* key, + const qse_char_t* value +); + typedef int (*qse_httpd_mod_dns_preresolve_t) ( qse_httpd_mod_t* mod, qse_httpd_client_t* client, @@ -128,10 +134,12 @@ typedef int (*qse_httpd_mod_urs_prerewrite_t) ( struct qse_httpd_mod_t { - /* private */ + /* next and handle are for internal use only*/ qse_httpd_mod_t* next; void* handle; /* set to the return value of mod.open() */ + /* ------------------------------------------- */ + /* module may access these fields for rererence */ qse_httpd_t* httpd; qse_char_t* name; /* portable module name */ @@ -140,6 +148,8 @@ struct qse_httpd_mod_t /* module's entry point may set these items */ void* ctx; qse_httpd_mod_unload_t unload; + /** return -1 upon error, 0 if a key is unknown/invalid, 1 upon success */ + qse_httpd_mod_config_t config; qse_httpd_mod_dns_preresolve_t dns_preresolve; qse_httpd_mod_urs_prerewrite_t urs_prerewrite; @@ -1030,7 +1040,7 @@ struct qse_httpd_ecb_t qse_httpd_ecb_t* next; }; -#ifdef __cplusplus +#if defined(__cplusplus) extern "C" { #endif @@ -1419,10 +1429,9 @@ QSE_EXPORT int qse_httpd_rewriteurl ( void* ctx ); -QSE_EXPORT int qse_httpd_loadmod ( +QSE_EXPORT qse_httpd_mod_t* qse_httpd_loadmod ( qse_httpd_t* httpd, - const qse_char_t* name, - const qse_xli_list_t* list + const qse_char_t* name ); QSE_EXPORT qse_httpd_mod_t* qse_httpd_findmod ( @@ -1430,6 +1439,12 @@ QSE_EXPORT qse_httpd_mod_t* qse_httpd_findmod ( const qse_char_t* name ); +QSE_EXPORT int qse_httpd_configmod ( + qse_httpd_t* httpd, + qse_httpd_mod_t* mod, + const qse_char_t* key, + const qse_char_t* value +); /* -------------------------------------------- */ @@ -1447,7 +1462,7 @@ QSE_EXPORT void qse_httpd_removetimerevent ( /* -------------------------------------------- */ -#ifdef __cplusplus +#if defined(__cplusplus) } #endif diff --git a/qse/include/qse/http/stdhttpd.h b/qse/include/qse/http/stdhttpd.h index 1ab19828..099251b5 100644 --- a/qse/include/qse/http/stdhttpd.h +++ b/qse/include/qse/http/stdhttpd.h @@ -271,7 +271,7 @@ QSE_EXPORT int qse_httpd_loopstd ( const qse_httpd_ursstd_t* urs ); -#ifdef __cplusplus +#if defined(__cplusplus) } #endif diff --git a/qse/include/qse/xli/xli.h b/qse/include/qse/xli/xli.h index 8e36aee6..ff5ff5fb 100644 --- a/qse/include/qse/xli/xli.h +++ b/qse/include/qse/xli/xli.h @@ -335,12 +335,20 @@ enum qse_xli_scm_flag_t QSE_XLI_SCM_VALNIL = (1 << 1), QSE_XLI_SCM_VALSTR = (1 << 2), QSE_XLI_SCM_VALLIST = (1 << 3), + QSE_XLI_SCM_KEYNODUP = (1 << 4), QSE_XLI_SCM_KEYALIAS = (1 << 5), - /* skips the validation of child pairs under a list. - * useful with #QSE_XLI_SCM_VALLIST only. */ - QSE_XLI_SCM_RELAXED = (1 << 6) + /** Indicates that the value is a list with uncertain definitions with + * the following constraints: + * no key aliases and duplicate keys are allowed. + * only a single-segment string is allowed as a value. + * + * Each pair in the list is treated as if { QSE_SLI_SCM_VALSTR | QSE_XLI_SCM_KEYNODUP, 1, 1 } + * is specified. + * + * Applies only if #QSE_XLI_SCM_VALLIST is set. */ + QSE_XLI_SCM_VALIFFY = (1 << 6) }; typedef enum qse_xli_scm_flag_t qse_xli_scm_flag_t;