From 33d7fd632c3b5c311efb0b41705685a3777ae4e6 Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Thu, 4 Apr 2013 15:04:45 +0000 Subject: [PATCH] implemented QSE_DIR_SORT. changed the way directory listing is formatted. --- qse/cmd/http/httpd.c | 60 ++++--- qse/cmd/http/httpd.conf | 28 +-- qse/include/qse/cmn/dir.h | 10 +- qse/include/qse/http/httpd.h | 26 ++- qse/include/qse/http/stdhttpd.h | 8 +- qse/lib/cmn/dir.c | 174 ++++++++++++++---- qse/lib/cmn/lda.c | 1 + qse/lib/cmn/syscall.h | 3 +- qse/lib/http/httpd-cgi.c | 2 +- qse/lib/http/httpd-dir.c | 307 +++++++++++++++++++++----------- qse/lib/http/httpd-std.c | 147 ++------------- qse/lib/http/httpd-task.c | 2 +- qse/samples/cmn/Makefile.am | 3 +- qse/samples/cmn/Makefile.in | 53 +++--- qse/samples/cmn/fma.c | 4 +- qse/samples/cmn/htb.c | 6 +- qse/samples/cmn/rbt.c | 6 +- 17 files changed, 472 insertions(+), 368 deletions(-) diff --git a/qse/cmd/http/httpd.c b/qse/cmd/http/httpd.c index d13f462b..ce2b928d 100644 --- a/qse/cmd/http/httpd.c +++ b/qse/cmd/http/httpd.c @@ -61,12 +61,13 @@ enum enum { - XCFG_NAME, XCFG_ROOT, XCFG_REALM, XCFG_AUTH, - XCFG_DIRCSS, - XCFG_ERRCSS, + XCFG_DIRHEAD, + XCFG_DIRFOOT, + XCFG_ERRHEAD, + XCFG_ERRFOOT, XCFG_MAX }; @@ -463,10 +464,6 @@ static int query_server ( switch (code) { - case QSE_HTTPD_SERVERSTD_NAME: - *(const qse_mchar_t**)result = loccfg->xcfg[XCFG_NAME]; - return 0; - case QSE_HTTPD_SERVERSTD_ROOT: #if 0 if (qse_mbscmp (qse_htre_getqpath(req), QSE_MT("/version")) == 0) @@ -514,12 +511,20 @@ static int query_server ( return 0; } - case QSE_HTTPD_SERVERSTD_DIRCSS: - *(const qse_mchar_t**)result = loccfg->xcfg[XCFG_DIRCSS]; + case QSE_HTTPD_SERVERSTD_DIRHEAD: + *(const qse_mchar_t**)result = loccfg->xcfg[XCFG_DIRHEAD]; return 0; - case QSE_HTTPD_SERVERSTD_ERRCSS: - *(const qse_mchar_t**)result = loccfg->xcfg[XCFG_ERRCSS]; + case QSE_HTTPD_SERVERSTD_DIRFOOT: + *(const qse_mchar_t**)result = loccfg->xcfg[XCFG_DIRFOOT]; + return 0; + + case QSE_HTTPD_SERVERSTD_ERRHEAD: + *(const qse_mchar_t**)result = loccfg->xcfg[XCFG_ERRHEAD]; + return 0; + + case QSE_HTTPD_SERVERSTD_ERRFOOT: + *(const qse_mchar_t**)result = loccfg->xcfg[XCFG_ERRFOOT]; return 0; case QSE_HTTPD_SERVERSTD_INDEX: @@ -643,8 +648,8 @@ static struct const qse_char_t* y; } scfg_items[] = { - { QSE_T("ssl-cert-file"), QSE_T("default.ssl-cert-file") }, - { QSE_T("ssl-key-file"), QSE_T("default.ssl-key-file") } + { QSE_T("ssl-cert-file"), QSE_T("server-default.ssl-cert-file") }, + { QSE_T("ssl-key-file"), QSE_T("server-default.ssl-key-file") } }; static struct @@ -653,12 +658,13 @@ static struct const qse_char_t* y; } loc_xcfg_items[] = { - { QSE_T("name"), QSE_T("default.name") }, - { QSE_T("root"), QSE_T("default.root") }, - { QSE_T("realm"), QSE_T("default.realm") }, - { QSE_T("auth"), QSE_T("default.auth") }, - { QSE_T("dir-css"), QSE_T("default.dir-css") }, - { QSE_T("error-css"), QSE_T("default.error-css") } + { QSE_T("root"), QSE_T("server-default.root") }, + { QSE_T("realm"), QSE_T("server-default.realm") }, + { QSE_T("auth"), QSE_T("server-default.auth") }, + { QSE_T("dir-head"), QSE_T("server-default.dir-head") }, + { QSE_T("dir-foot"), QSE_T("server-default.dir-foot") }, + { QSE_T("error-head"), QSE_T("server-default.error-head") }, + { QSE_T("error-foot"), QSE_T("server-default.error-foot") }, }; static struct @@ -667,8 +673,8 @@ static struct const qse_char_t* y; } loc_acc_items[] = { - { QSE_T("dir-access"), QSE_T("default.dir-access") }, - { QSE_T("file-access"), QSE_T("default.file-access") } + { QSE_T("dir-access"), QSE_T("server-default.dir-access") }, + { QSE_T("file-access"), QSE_T("server-default.file-access") } }; static void free_loccfg_contents (qse_httpd_t* httpd, loccfg_t* loccfg) @@ -1299,6 +1305,15 @@ static int load_config (qse_httpd_t* httpd) if (open_config_file (httpd) <= -1) goto oops; + pair = qse_xli_findpairbyname (httpd_xtn->xli, QSE_NULL, QSE_T("name")); + if (pair && pair->val->type == QSE_XLI_STR) + { + qse_mchar_t* tmp; + tmp = qse_httpd_strtombsdup (httpd, ((qse_xli_str_t*)pair->val)->ptr); + if (tmp) qse_httpd_setname (httpd, tmp); + qse_httpd_freemem (httpd, tmp); + } + for (i = 0; ; i++) { qse_char_t buf[32]; @@ -1343,9 +1358,6 @@ static int load_config (qse_httpd_t* httpd) } } - if (httpd_xtn->dflcfg.xcfg[XCFG_NAME]) - qse_httpd_setname (httpd, httpd_xtn->dflcfg.xcfg[XCFG_NAME]); - close_config_file (httpd); return 0; diff --git a/qse/cmd/http/httpd.conf b/qse/cmd/http/httpd.conf index 2e75a8f0..626ac392 100644 --- a/qse/cmd/http/httpd.conf +++ b/qse/cmd/http/httpd.conf @@ -2,16 +2,15 @@ # this is a sample configuration file for qsehttpd. # -default { +# string to be used as a httpd name +name = "QSEHTTPD v1"; + +server-default { # default ssl certificate file #ssl-cert-file = "/etc/qse/cert.pem"; # default ssl private key file #ssl-key-file = "/etc/qse/key.pem"; - # the default name is used in http headers and in pages - # generated by httpd. - name = "QSEHTTPD v1"; - # document root root = "/"; @@ -54,8 +53,17 @@ default { #other = noent; } - dir-css = ""; - error-css = ""; + dir-head = ""; + + # the directory listing shows the httpd name in the footer. + # you can override it with dir-foot. + #dir-foot = "QSEHTTPD v1"; + + error-head = ""; + + # an error page shows the httpd name in the footer. + # you can override it with error-foot. + #error-foot = "QSEHTTPD v1"; } server { @@ -71,12 +79,6 @@ server { host "*" { location "/" { - # the location-specific name is used in pages - # generated by httpd, not in http headers. - # you can't override the default name for use in - # http headers. - #name = "QSEHTTPD v1"; - # uncomment the followng block to override the default. #root = "/var/www"; diff --git a/qse/include/qse/cmn/dir.h b/qse/include/qse/cmn/dir.h index 5f3a534d..cf933f04 100644 --- a/qse/include/qse/cmn/dir.h +++ b/qse/include/qse/cmn/dir.h @@ -54,20 +54,12 @@ typedef enum qse_dir_errnum_t qse_dir_errnum_t; enum qse_dir_flag_t { QSE_DIR_MBSPATH = (1 << 0), - QSE_DIR_SORT = (1 << 1), - QSE_DIR_STAT = (1 << 2) + QSE_DIR_SORT = (1 << 1) }; struct qse_dir_ent_t { const qse_char_t* name; - - struct - { - int type; - qse_foff_t size; - qse_ntime_t tmmod; - } stat; }; #ifdef __cplusplus diff --git a/qse/include/qse/http/httpd.h b/qse/include/qse/http/httpd.h index d854e249..332a4262 100644 --- a/qse/include/qse/http/httpd.h +++ b/qse/include/qse/http/httpd.h @@ -259,15 +259,6 @@ typedef int (*qse_httpd_fmterr_t) ( int bufsz ); -typedef int (*qse_httpd_fmtdir_t) ( - qse_httpd_t* httpd, - qse_httpd_client_t* client, - const qse_mchar_t* qpath, - const qse_httpd_dirent_t* dirent, - qse_mchar_t* buf, - int bufsz -); - typedef void (*qse_httpd_impede_t) ( qse_httpd_t* httpd ); @@ -305,7 +296,6 @@ struct qse_httpd_rcb_t qse_httpd_peekreq_t peekreq; qse_httpd_pokereq_t pokereq; qse_httpd_fmterr_t fmterr; - qse_httpd_fmtdir_t fmtdir; qse_httpd_impede_t impede; qse_httpd_logact_t logact; }; @@ -492,6 +482,14 @@ struct qse_httpd_rsrc_cgi_t int nph; }; +typedef struct qse_httpd_rsrc_dir_t qse_httpd_rsrc_dir_t; +struct qse_httpd_rsrc_dir_t +{ + const qse_mchar_t* path; + const qse_mchar_t* head; + const qse_mchar_t* foot; +}; + typedef struct qse_httpd_rsrc_t qse_httpd_rsrc_t; struct qse_httpd_rsrc_t { @@ -505,11 +503,7 @@ struct qse_httpd_rsrc_t } auth; qse_httpd_rsrc_cgi_t cgi; - - struct - { - const qse_mchar_t* path; - } dir; + qse_httpd_rsrc_dir_t dir; struct { @@ -827,7 +821,7 @@ QSE_EXPORT qse_httpd_task_t* qse_httpd_entaskdir ( qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* pred, - const qse_mchar_t* name, + qse_httpd_rsrc_dir_t* dir, qse_htre_t* req ); diff --git a/qse/include/qse/http/stdhttpd.h b/qse/include/qse/http/stdhttpd.h index 63a47ec2..c94197e2 100644 --- a/qse/include/qse/http/stdhttpd.h +++ b/qse/include/qse/http/stdhttpd.h @@ -106,12 +106,14 @@ enum qse_httpd_serverstd_query_code_t { QSE_HTTPD_SERVERSTD_SSL, /* qse_httpd_serverstd_ssl_t */ - QSE_HTTPD_SERVERSTD_NAME, /* const qse_mchar_t* */ QSE_HTTPD_SERVERSTD_ROOT, /* qse_httpd_serverstd_root_t */ QSE_HTTPD_SERVERSTD_REALM, /* qse_httpd_serverstd_realm_t */ QSE_HTTPD_SERVERSTD_AUTH, /* qse_httpd_serverstd_auth_t */ - QSE_HTTPD_SERVERSTD_DIRCSS, /* const qse_mchar_t* */ - QSE_HTTPD_SERVERSTD_ERRCSS, /* const qse_mchar_t* */ + QSE_HTTPD_SERVERSTD_ERRHEAD, /* const qse_mchar_t* */ + QSE_HTTPD_SERVERSTD_ERRFOOT, /* const qse_mchar_t* */ + + QSE_HTTPD_SERVERSTD_DIRHEAD, /* const qse_mchar_t* */ + QSE_HTTPD_SERVERSTD_DIRFOOT, /* const qse_mchar_t* */ QSE_HTTPD_SERVERSTD_INDEX, /* qse_httpd_serverstd_index_t */ QSE_HTTPD_SERVERSTD_CGI, /* qse_httpd_serverstd_cgi_t */ diff --git a/qse/lib/cmn/dir.c b/qse/lib/cmn/dir.c index d3245310..8ceb5f68 100644 --- a/qse/lib/cmn/dir.c +++ b/qse/lib/cmn/dir.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "mem.h" #if defined(_WIN32) @@ -37,6 +38,13 @@ # include "syscall.h" #endif + +#define STATUS_OPENED (1 << 0) +#define STATUS_DONE (1 << 1) +#define STATUS_DONE_ERR (1 << 2) +#define STATUS_POPHEAP (1 << 3) +#define STATUS_SORT_ERR (1 << 4) + struct qse_dir_t { qse_mmgr_t* mmgr; @@ -46,10 +54,12 @@ struct qse_dir_t qse_str_t tbuf; qse_mbs_t mbuf; + qse_lda_t* stab; + int status; + #if defined(_WIN32) HANDLE h; WIN32_FIND_DATA wfd; - int done; #elif defined(__OS2__) HDIR h; #if defined(FIL_STANDARDL) @@ -58,11 +68,8 @@ struct qse_dir_t FILEFINDBUF3 ffb; #endif ULONG count; - int opened; #elif defined(__DOS__) struct find_t f; - int done; - int opened; #else DIR* dp; #endif @@ -71,7 +78,9 @@ struct qse_dir_t int qse_dir_init (qse_dir_t* dir, qse_mmgr_t* mmgr, const qse_char_t* path, int flags); void qse_dir_fini (qse_dir_t* dir); +static void close_dir_safely (qse_dir_t* dir); static int reset_to_path (qse_dir_t* dir, const qse_char_t* path); +static int read_ahead_and_sort (qse_dir_t* dir, const qse_char_t* path); #include "syserr.h" IMPLEMENT_SYSERR_TO_ERRNUM (dir, DIR) @@ -122,6 +131,13 @@ qse_dir_errnum_t qse_dir_geterrnum (qse_dir_t* dir) return dir->errnum; } +static int compare_dirent (qse_lda_t* lda, const void* dptr1, size_t dlen1, const void* dptr2, size_t dlen2) +{ + int n = QSE_MEMCMP (dptr1, dptr2, ((dlen1 < dlen2)? dlen1: dlen2)); + if (n == 0 && dlen1 != dlen2) n = (dlen1 > dlen2)? 1: -1; + return -n; +} + int qse_dir_init (qse_dir_t* dir, qse_mmgr_t* mmgr, const qse_char_t* path, int flags) { int n; @@ -131,25 +147,39 @@ int qse_dir_init (qse_dir_t* dir, qse_mmgr_t* mmgr, const qse_char_t* path, int dir->mmgr = mmgr; dir->flags = flags; - if (qse_str_init (&dir->tbuf, mmgr, 256) <= -1) return -1; - if (qse_mbs_init (&dir->mbuf, mmgr, 256) <= -1) - { - qse_str_fini (&dir->tbuf); - return -1; - } + if (qse_str_init (&dir->tbuf, mmgr, 256) <= -1) goto oops_0; + if (qse_mbs_init (&dir->mbuf, mmgr, 256) <= -1) goto oops_1; #if defined(_WIN32) dir->h = INVALID_HANDLE_VALUE; #endif n = reset_to_path (dir, path); - if (n <= -1) + if (n <= -1) goto oops_2; + + if (dir->flags & QSE_DIR_SORT) { - qse_mbs_fini (&dir->mbuf); - qse_str_fini (&dir->tbuf); + dir->stab = qse_lda_open (dir->mmgr, 0, 128); + if (dir->stab == QSE_NULL) goto oops_3; + + /*qse_lda_setscale (dir->stab, 1);*/ + qse_lda_setcopier (dir->stab, QSE_LDA_COPIER_INLINE); + qse_lda_setcomper (dir->stab, compare_dirent); + if (read_ahead_and_sort (dir, path) <= -1) goto oops_4; } return n; + +oops_4: + qse_lda_close (dir->stab); +oops_3: + close_dir_safely (dir); +oops_2: + qse_mbs_fini (&dir->mbuf); +oops_1: + qse_str_fini (&dir->tbuf); +oops_0: + return -1; } static void close_dir_safely (qse_dir_t* dir) @@ -161,16 +191,16 @@ static void close_dir_safely (qse_dir_t* dir) dir->h = INVALID_HANDLE_VALUE; } #elif defined(__OS2__) - if (dir->opened) + if (dir->status & STATUS_OPENED) { DosFindClose (dir->h); - dir->opened = 0; + dir->status &= ~STATUS_OPENED; } #elif defined(__DOS__) - if (dir->opened) + if (dir->status & STATUS_OPENED) { _dos_findclose (&dir->f); - dir->opened = 0; + dir->status &= ~STATUS_OPENED; } #else if (dir->dp) @@ -187,6 +217,8 @@ void qse_dir_fini (qse_dir_t* dir) qse_mbs_fini (&dir->mbuf); qse_str_fini (&dir->tbuf); + + if (dir->stab) qse_lda_close (dir->stab); } static qse_mchar_t* wcs_to_mbuf (qse_dir_t* dir, const qse_wchar_t* wcs, qse_mbs_t* mbs) @@ -316,7 +348,8 @@ static int reset_to_path (qse_dir_t* dir, const qse_char_t* path) /* ------------------------------------------------------------------- */ qse_char_t* tptr; - dir->done = 0; + dir->status &= ~STATUS_DONE; + dir->status &= ~STATUS_DONE_ERR; #if defined(QSE_CHAR_IS_MCHAR) tptr = make_dos_path (dir, path); @@ -390,7 +423,7 @@ static int reset_to_path (qse_dir_t* dir, const qse_char_t* path) return -1; } - dir->opened = 1; + dir->status |= STATUS_OPENED; return 0; /* ------------------------------------------------------------------- */ @@ -400,7 +433,8 @@ static int reset_to_path (qse_dir_t* dir, const qse_char_t* path) unsigned int rc; qse_mchar_t* mptr; - dir->done = 0; + dir->status &= ~STATUS_DONE; + dir->status &= ~STATUS_DONE_ERR; #if defined(QSE_CHAR_IS_MCHAR) mptr = make_dos_path (dir, path); @@ -425,7 +459,7 @@ static int reset_to_path (qse_dir_t* dir, const qse_char_t* path) return -1; } - dir->opened = 1; + dir->status |= STATUS_OPENED; return 0; /* ------------------------------------------------------------------- */ @@ -471,7 +505,23 @@ static int reset_to_path (qse_dir_t* dir, const qse_char_t* path) int qse_dir_reset (qse_dir_t* dir, const qse_char_t* path) { close_dir_safely (dir); - return reset_to_path (dir, path); + if (reset_to_path (dir, path) <= -1) return -1; + + if (dir->flags & QSE_DIR_SORT) + { + qse_lda_clear (dir->stab); + if (read_ahead_and_sort (dir, path) <= -1) + { + dir->status |= STATUS_SORT_ERR; + return -1; + } + else + { + dir->status &= ~STATUS_SORT_ERR; + } + } + + return 0; } static int read_dir_to_tbuf (qse_dir_t* dir, void** name) @@ -479,7 +529,7 @@ static int read_dir_to_tbuf (qse_dir_t* dir, void** name) #if defined(_WIN32) /* ------------------------------------------------------------------- */ - if (dir->done) return (dir->done > 0)? 0: -1; + if (dir->status & STATUS_DONE) return (dir->status & STATUS_DONE_ERR)? -1: 0; #if defined(QSE_CHAR_IS_MCHAR) if (qse_str_cpy (&dir->tbuf, dir->wfd.cFileName) == (qse_size_t)-1) @@ -508,11 +558,12 @@ static int read_dir_to_tbuf (qse_dir_t* dir, void** name) if (FindNextFile (dir->h, &dir->wfd) == FALSE) { DWORD x = GetLastError(); - if (x == ERROR_NO_MORE_FILES) dir->done = 1; + if (x == ERROR_NO_MORE_FILES) dir->status |= STATUS_DONE; else { dir->errnum = syserr_to_errnum (x); - dir->done = -1; + dir->status |= STATUS_DONE; + dir->status |= STATUS_DONE_ERR; } } @@ -565,7 +616,7 @@ static int read_dir_to_tbuf (qse_dir_t* dir, void** name) /* ------------------------------------------------------------------- */ - if (dir->done) return (dir->done > 0)? 0: -1; + if (dir->status & STATUS_DONE) return (dir->status & STATUS_DONE_ERR)? -1: 0; #if defined(QSE_CHAR_IS_MCHAR) if (qse_str_cpy (&dir->tbuf, dir->f.name) == (qse_size_t)-1) @@ -593,11 +644,12 @@ static int read_dir_to_tbuf (qse_dir_t* dir, void** name) if (_dos_findnext (&dir->f) != 0) { - if (errno == ENOENT) dir->done = 1; + if (errno == ENOENT) dir->status |= STATUS_DONE; else { dir->errnum = syserr_to_errnum (errno); - dir->done = -1; + dir->status |= STATUS_DONE; + dir->status |= STATUS_DONE_ERR; } } @@ -643,28 +695,74 @@ static int read_dir_to_tbuf (qse_dir_t* dir, void** name) } #endif - return 1; /* ------------------------------------------------------------------- */ #endif } -int qse_dir_read (qse_dir_t* dir, qse_dir_ent_t* ent) +static int read_ahead_and_sort (qse_dir_t* dir, const qse_char_t* path) { int x; void* name; - x = read_dir_to_tbuf (dir, &name); - if (x >= 1) + while (1) { - QSE_MEMSET (ent, 0, QSE_SIZEOF(ent)); - ent->name = name; - - if (dir->flags & QSE_DIR_STAT) + x = read_dir_to_tbuf (dir, &name); + if (x >= 1) { - /* TODO: more information */ + qse_size_t size; + +#if defined(QSE_CHAR_IS_MCHAR) + size = (qse_mbslen(name) + 1) * QSE_SIZEOF(qse_mchar_t); +#else + if (dir->flags & QSE_DIR_MBSPATH) + size = (qse_mbslen(name) + 1) * QSE_SIZEOF(qse_mchar_t); + else + size = (qse_wcslen(name) + 1) * QSE_SIZEOF(qse_wchar_t); + +#endif + + if (qse_lda_pushheap (dir->stab, name, size) == (qse_size_t)-1) + { + dir->errnum = QSE_DIR_ENOMEM; + return -1; + } } + else if (x == 0) break; + else return -1; } - return x; + dir->status &= ~STATUS_POPHEAP; + return 0; +} + + +int qse_dir_read (qse_dir_t* dir, qse_dir_ent_t* ent) +{ + if (dir->flags & QSE_DIR_SORT) + { + if (dir->status & STATUS_SORT_ERR) return -1; + + if (dir->status & STATUS_POPHEAP) qse_lda_popheap (dir->stab); + else dir->status |= STATUS_POPHEAP; + + if (QSE_LDA_SIZE(dir->stab) <= 0) return 0; /* no more entry */ + + ent->name = QSE_LDA_DPTR(dir->stab, 0); + return 1; + } + else + { + int x; + void* name; + + x = read_dir_to_tbuf (dir, &name); + if (x >= 1) + { + QSE_MEMSET (ent, 0, QSE_SIZEOF(ent)); + ent->name = name; + } + + return x; + } } diff --git a/qse/lib/cmn/lda.c b/qse/lib/cmn/lda.c index eb6eae8b..4df65b1c 100644 --- a/qse/lib/cmn/lda.c +++ b/qse/lib/cmn/lda.c @@ -122,6 +122,7 @@ int qse_lda_init (lda_t* lda, mmgr_t* mmgr, size_t capa) lda->size = 0; lda->capa = 0; lda->slot = QSE_NULL; + lda->scale = 1; lda->copier = QSE_LDA_COPIER_SIMPLE; lda->comper = default_comparator; diff --git a/qse/lib/cmn/syscall.h b/qse/lib/cmn/syscall.h index 26471326..e62f2e05 100644 --- a/qse/lib/cmn/syscall.h +++ b/qse/lib/cmn/syscall.h @@ -370,7 +370,8 @@ /* ===== DIRECTORY - not really system calls ===== */ #define QSE_OPENDIR(name) opendir(name) -#define QSE_CLOSEDIR(name) closedir(name) +#define QSE_CLOSEDIR(dir) closedir(dir) +#define QSE_REWINDDIR(dir) rewinddir(dir) #if defined(HAVE_READDIR64) typedef struct dirent64 qse_dirent_t; diff --git a/qse/lib/http/httpd-cgi.c b/qse/lib/http/httpd-cgi.c index 7819e21b..063ee86d 100644 --- a/qse/lib/http/httpd-cgi.c +++ b/qse/lib/http/httpd-cgi.c @@ -1517,7 +1517,7 @@ qse_httpd_task_t* qse_httpd_entaskcgi ( qse_httpd_client_t* client, qse_httpd_task_t* pred, qse_httpd_rsrc_cgi_t* cgi, - qse_htre_t* req) + qse_htre_t* req) { qse_httpd_task_t task; task_cgi_arg_t arg; diff --git a/qse/lib/http/httpd-dir.c b/qse/lib/http/httpd-dir.c index 67df811b..36a0102d 100644 --- a/qse/lib/http/httpd-dir.c +++ b/qse/lib/http/httpd-dir.c @@ -23,14 +23,19 @@ #include #include +#include /* TODO: remove this */ + typedef struct task_dir_t task_dir_t; struct task_dir_t { qse_mcstr_t path; qse_mcstr_t qpath; + qse_mcstr_t head; + qse_mcstr_t foot; qse_http_version_t version; int keepalive; int method; + qse_ubi_t handle; }; typedef struct task_dseg_t task_dseg_t; @@ -42,6 +47,8 @@ struct task_dseg_t qse_mcstr_t path; qse_mcstr_t qpath; + qse_mcstr_t head; + qse_mcstr_t foot; qse_ubi_t handle; qse_httpd_dirent_t dent; @@ -75,6 +82,11 @@ static int task_init_dseg ( xtn->qpath.ptr = xtn->path.ptr + xtn->path.len + 1; qse_mbscpy ((qse_mchar_t*)xtn->qpath.ptr, arg->qpath.ptr); + xtn->head.ptr = xtn->qpath.ptr + xtn->qpath.len + 1; + qse_mbscpy ((qse_mchar_t*)xtn->head.ptr, arg->head.ptr); + xtn->foot.ptr = xtn->head.ptr + xtn->head.len + 1; + qse_mbscpy ((qse_mchar_t*)xtn->foot.ptr, arg->foot.ptr); + task->ctx = xtn; return 0; @@ -126,6 +138,81 @@ static void fill_chunk_length (task_dseg_t* ctx) while (ctx->buf[ctx->bufpos] == QSE_MT(' ')) ctx->bufpos++; } +static int format_dirent ( + qse_httpd_t* httpd, + qse_httpd_client_t* client, + const qse_httpd_dirent_t* dirent, + qse_mchar_t* buf, int bufsz) +{ +/* TODO: page encoding?? utf-8??? or derive name from cmgr or current locale??? */ + int n; + + qse_mchar_t* encname; + qse_mchar_t* escname; + qse_btime_t bt; + qse_mchar_t tmbuf[32]; + qse_mchar_t fszbuf[64]; + + /* TODO: better buffer management in case there are + * a lot of file names to escape. */ + + /* perform percent-encoding for the anchor */ + encname = qse_perenchttpstrdup (dirent->name, httpd->mmgr); + if (encname == QSE_NULL) + { + httpd->errnum = QSE_HTTPD_ENOMEM; + return -1; + } + + /* perform html escaping for the text */ + escname = qse_httpd_escapehtml (httpd, dirent->name); + if (escname == QSE_NULL) + { + if (encname != dirent->name) QSE_MMGR_FREE (httpd->mmgr, encname); + return -1; + } + + qse_localtime (&dirent->stat.mtime, &bt); + snprintf (tmbuf, QSE_COUNTOF(tmbuf), + QSE_MT("%04d-%02d-%02d %02d:%02d:%02d"), + bt.year + QSE_BTIME_YEAR_BASE, bt.mon + 1, bt.mday, + bt.hour, bt.min, bt.sec); + + if (dirent->stat.isdir) + { + fszbuf[0] = QSE_MT('\0'); + } + else + { + qse_fmtuintmaxtombs ( + fszbuf, QSE_COUNTOF(fszbuf), + dirent->stat.size, 10, -1, QSE_MT('\0'), QSE_NULL + ); + } + + n = snprintf ( + buf, bufsz, + QSE_MT("%s%s%s%s\n"), + encname, + (dirent->stat.isdir? QSE_MT("/"): QSE_MT("")), + (dirent->stat.isdir? QSE_MT("dir"): QSE_MT("file")), + escname, + (dirent->stat.isdir? QSE_MT("/"): QSE_MT("")), + tmbuf, fszbuf + ); + + if (escname != dirent->name) qse_httpd_freemem (httpd, escname); + if (encname != dirent->name) QSE_MMGR_FREE (httpd->mmgr, encname); + + if (n <= -1 || n >= bufsz) + { + httpd->errnum = QSE_HTTPD_ENOBUF; + return -1; + } + + return n; +} + static int add_footer (qse_httpd_t* httpd, qse_httpd_client_t* client, task_dseg_t* ctx) { int x, rem; @@ -137,10 +224,12 @@ static int add_footer (qse_httpd_t* httpd, qse_httpd_client_t* client, task_dseg return -1; } - x = httpd->opt.rcb.fmtdir ( - httpd, client, QSE_NULL, QSE_NULL, - &ctx->buf[ctx->buflen], rem); - if (x <= -1) return -1; + x = snprintf (&ctx->buf[ctx->buflen], rem, QSE_MT("\n\n"), ctx->foot.ptr); + if (x <= -1 || x >= rem) + { + httpd->errnum = QSE_HTTPD_ENOBUF; + return -1; + } QSE_ASSERT (x < rem); @@ -221,7 +310,7 @@ static int task_main_dseg ( if (add_footer (httpd, client, ctx) <= -1) { /* return an error if the buffer is too small to hold the - * trailing footer. you need to increate the buffer size */ + * trailing footer. you need to increase the buffer size */ return -1; } @@ -235,15 +324,31 @@ static int task_main_dseg ( if (!(ctx->state & HEADER_ADDED)) { /* compose the header since this is the first time. */ - x = httpd->opt.rcb.fmtdir ( - httpd, client, ctx->qpath.ptr, QSE_NULL, - &ctx->buf[ctx->buflen], ctx->bufrem); + int is_root; + qse_mchar_t* qpath_esc; + + is_root = (qse_mbscmp (ctx->qpath.ptr, QSE_MT("/")) == 0); + + qpath_esc = qse_httpd_escapehtml (httpd, ctx->qpath.ptr); + if (qpath_esc == QSE_NULL) return -1; + + x = snprintf (&ctx->buf[ctx->buflen], ctx->bufrem, + QSE_MT("%s\n\n
%s
\n
%s"), ctx->head.ptr, qpath_esc, + (is_root? QSE_MT(""): QSE_MT("\n")) + ); + + if (qpath_esc != ctx->qpath.ptr) qse_httpd_freemem (httpd, qpath_esc); + +#if 0 if (x <= -1) +#endif + if (x <= -1 || x >= ctx->bufrem) { /* return an error if the buffer is too small to * hold the header(httpd->errnum == QSE_HTTPD_ENOBUF). - * i need to increate the buffer size. or i have make + * i need to increase the buffer size. or i have make * the buffer dynamic. */ + httpd->errnum = QSE_HTTPD_ENOBUF; return -1; } @@ -290,9 +395,7 @@ static int task_main_dseg ( if (qse_mbscmp (ctx->dent.name, QSE_MT(".")) != 0 && qse_mbscmp (ctx->dent.name, QSE_MT("..")) != 0) { - x = httpd->opt.rcb.fmtdir ( - httpd, client, ctx->qpath.ptr, &ctx->dent, - &ctx->buf[ctx->buflen], ctx->bufrem); + x = format_dirent (httpd, client, &ctx->dent, &ctx->buf[ctx->buflen], ctx->bufrem); if (x <= -1) { /* buffer not large enough to hold this entry */ @@ -358,6 +461,8 @@ static qse_httpd_task_t* entask_directory_segment ( data.chunked = dir->keepalive; data.path = dir->path; data.qpath = dir->qpath; + data.head = dir->head; + data.foot = dir->foot; QSE_MEMSET (&task, 0, QSE_SIZEOF(task)); task.init = task_init_dseg; @@ -365,7 +470,7 @@ static qse_httpd_task_t* entask_directory_segment ( task.fini = task_fini_dseg; task.ctx = &data; - return qse_httpd_entask (httpd, client, pred, &task, QSE_SIZEOF(data) + data.path.len + 1 + data.qpath.len + 1); + return qse_httpd_entask (httpd, client, pred, &task, QSE_SIZEOF(data) + data.path.len + 1 + data.qpath.len + 1 + data.head.len + 1 + data.foot.len + 1); } /*------------------------------------------------------------------------*/ @@ -384,9 +489,13 @@ static int task_init_getdir ( xtn->qpath.ptr = xtn->path.ptr + xtn->path.len + 1; qse_mbscpy ((qse_mchar_t*)xtn->qpath.ptr, arg->qpath.ptr); + xtn->head.ptr = xtn->qpath.ptr + xtn->qpath.len + 1; + qse_mbscpy ((qse_mchar_t*)xtn->head.ptr, arg->head.ptr); + xtn->foot.ptr = xtn->head.ptr + xtn->head.len + 1; + qse_mbscpy ((qse_mchar_t*)xtn->foot.ptr, arg->foot.ptr); + /* switch the context to the extension area */ task->ctx = xtn; - return 0; } @@ -395,105 +504,63 @@ static QSE_INLINE int task_main_getdir ( { task_dir_t* dir; qse_httpd_task_t* x; - qse_ubi_t handle; dir = (task_dir_t*)task->ctx; x = task; - /* - * I've commented out the check for a slash at the end of the query path - * expecting that redirection is performed by the caller if such a condition - * isn't met or that redirection is not required under such a condition. - - if (qse_mbsend (dir->qpath.ptr, QSE_MT("/"))) + /* arrange to return the header part first */ + if (dir->method == QSE_HTTP_HEAD) { - */ - if (httpd->opt.scb.dir.open (httpd, dir->path.ptr, &handle) <= -1) - { - int http_errnum; - http_errnum = (httpd->errnum == QSE_HTTPD_ENOENT)? 404: - (httpd->errnum == QSE_HTTPD_EACCES)? 403: 500; - x = qse_httpd_entask_err ( - httpd, client, x, http_errnum, - dir->method, &dir->version, dir->keepalive); - - return (x == QSE_NULL)? -1: 0; - } - else - { - if (dir->method == QSE_HTTP_HEAD) - { - x = qse_httpd_entaskformat ( - httpd, client, x, - QSE_MT("HTTP/%d.%d 200 OK\r\nServer: %s\r\nDate: %s\r\nConnection: %s\r\nContent-Type: text/html\r\nContent-Length: 0\r\n\r\n"), - dir->version.major, dir->version.minor, - qse_httpd_getname (httpd), - qse_httpd_fmtgmtimetobb (httpd, QSE_NULL, 0), - (dir->keepalive? QSE_MT("keep-alive"): QSE_MT("close")) - ); + x = qse_httpd_entaskformat ( + httpd, client, x, + QSE_MT("HTTP/%d.%d 200 OK\r\nServer: %s\r\nDate: %s\r\nConnection: %s\r\nContent-Type: text/html\r\nContent-Length: 0\r\n\r\n"), + dir->version.major, dir->version.minor, + qse_httpd_getname (httpd), + qse_httpd_fmtgmtimetobb (httpd, QSE_NULL, 0), + (dir->keepalive? QSE_MT("keep-alive"): QSE_MT("close")) + ); - httpd->opt.scb.dir.close (httpd, handle); - return (x == QSE_NULL)? -1: 0; - } - else - { - x = qse_httpd_entaskformat ( - httpd, client, x, - QSE_MT("HTTP/%d.%d 200 OK\r\nServer: %s\r\nDate: %s\r\nConnection: %s\r\nContent-Type: text/html\r\n%s\r\n"), - dir->version.major, dir->version.minor, - qse_httpd_getname (httpd), - qse_httpd_fmtgmtimetobb (httpd, QSE_NULL, 0), - (dir->keepalive? QSE_MT("keep-alive"): QSE_MT("close")), - (dir->keepalive? QSE_MT("Transfer-Encoding: chunked\r\n"): QSE_MT("")) - ); - if (x) - { - x = entask_directory_segment (httpd, client, x, handle, dir); - if (x) return 0; - } - - httpd->opt.scb.dir.close (httpd, handle); - return -1; - } - } - /* + httpd->opt.scb.dir.close (httpd, dir->handle); + return (x == QSE_NULL)? -1: 0; } else { - x = qse_httpd_entask_redir ( - httpd, client, x, dir->qpath.ptr, - &dir->version, dir->keepalive); + x = qse_httpd_entaskformat ( + httpd, client, x, + QSE_MT("HTTP/%d.%d 200 OK\r\nServer: %s\r\nDate: %s\r\nConnection: %s\r\nContent-Type: text/html\r\n%s\r\n"), + dir->version.major, dir->version.minor, + qse_httpd_getname (httpd), + qse_httpd_fmtgmtimetobb (httpd, QSE_NULL, 0), + (dir->keepalive? QSE_MT("keep-alive"): QSE_MT("close")), + (dir->keepalive? QSE_MT("Transfer-Encoding: chunked\r\n"): QSE_MT("")) + ); + if (x) + { + /* arrange to send the actual directory contents */ + x = entask_directory_segment (httpd, client, x, dir->handle, dir); + if (x) return 0; + } - return (x == QSE_NULL)? -1: 0; + httpd->opt.scb.dir.close (httpd, dir->handle); + return -1; } - */ } qse_httpd_task_t* qse_httpd_entaskdir ( qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* pred, - const qse_mchar_t* path, + qse_httpd_rsrc_dir_t* dir, qse_htre_t* req) { - qse_httpd_task_t task; - task_dir_t data; + int method; - QSE_MEMSET (&data, 0, QSE_SIZEOF(data)); - data.path.ptr = path; - data.path.len = qse_mbslen(data.path.ptr); - data.qpath.ptr = qse_htre_getqpath(req); - data.qpath.len = qse_mbslen(data.qpath.ptr); - data.version = *qse_htre_getversion(req); - data.keepalive = (req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE); - data.method = qse_htre_getqmethodtype(req); - - QSE_MEMSET (&task, 0, QSE_SIZEOF(task)); + method = qse_htre_getqmethodtype(req); /* i don't need contents for directories */ qse_htre_discardcontent (req); - switch (data.method) + switch (method) { case QSE_HTTP_OPTIONS: return qse_httpd_entaskallow (httpd, client, pred, @@ -502,16 +569,58 @@ qse_httpd_task_t* qse_httpd_entaskdir ( case QSE_HTTP_HEAD: case QSE_HTTP_GET: case QSE_HTTP_POST: - task.init = task_init_getdir; - task.main = task_main_getdir; - break; + { + task_dir_t data; + QSE_MEMSET (&data, 0, QSE_SIZEOF(data)); + + /* check if the directory stream can be opened before + * creating an actual task. */ + if (httpd->opt.scb.dir.open (httpd, dir->path, &data.handle) <= -1) + { + /* arrange a status code to return */ + int status; + status = (httpd->errnum == QSE_HTTPD_ENOENT)? 404: + (httpd->errnum == QSE_HTTPD_EACCES)? 403: 500; + return qse_httpd_entaskerr (httpd, client, pred, status, req); + } + else + { + /* create a directory listing task */ + qse_httpd_task_t task, * x; + + data.path.ptr = dir->path; + data.path.len = qse_mbslen(data.path.ptr); + data.qpath.ptr = qse_htre_getqpath(req); + data.qpath.len = qse_mbslen(data.qpath.ptr); + data.head.ptr = dir->head? dir->head: QSE_MT(""); + data.head.len = qse_mbslen(data.head.ptr); + data.foot.ptr = dir->foot? dir->foot: qse_httpd_getname(httpd); + data.foot.len = qse_mbslen(data.foot.ptr); + data.version = *qse_htre_getversion(req); + data.keepalive = (req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE); + data.method = method; + + QSE_MEMSET (&task, 0, QSE_SIZEOF(task)); + task.init = task_init_getdir; + task.main = task_main_getdir; + task.ctx = &data; + + x = qse_httpd_entask (httpd, client, pred, &task, + QSE_SIZEOF(task_dir_t) + data.path.len + 1 + data.qpath.len + 1 + + data.head.len + 1 + data.foot.len + 1); + if (x == QSE_NULL) + { + httpd->opt.scb.dir.close (httpd, data.handle); + } + return x; + } + } case QSE_HTTP_PUT: { int status = 201; /* 201 Created */ - - if (httpd->opt.scb.dir.make (httpd, path) <= -1) + if (httpd->opt.scb.dir.make (httpd, dir->path) <= -1) { if (httpd->errnum == QSE_HTTPD_EEXIST) { @@ -520,7 +629,7 @@ qse_httpd_task_t* qse_httpd_entaskdir ( * if not, send '403 forbidden' indicating you can't * change a file to a directory */ qse_httpd_stat_t st; - status = (httpd->opt.scb.dir.stat (httpd, path, &st) <= -1)? 403: 204; + status = (httpd->opt.scb.dir.stat (httpd, dir->path, &st) <= -1)? 403: 204; } else { @@ -537,7 +646,7 @@ qse_httpd_task_t* qse_httpd_entaskdir ( { int status = 200; - if (httpd->opt.scb.dir.purge (httpd, path) <= -1) + if (httpd->opt.scb.dir.purge (httpd, dir->path) <= -1) { status = (httpd->errnum == QSE_HTTPD_ENOENT)? 404: (httpd->errnum == QSE_HTTPD_EACCES)? 403: 500; @@ -550,10 +659,4 @@ qse_httpd_task_t* qse_httpd_entaskdir ( /* Method not allowed */ return qse_httpd_entaskerr (httpd, client, pred, 405, req); } - - task.ctx = &data; - - return qse_httpd_entask (httpd, client, pred, &task, - QSE_SIZEOF(task_dir_t) + data.path.len + 1 + data.qpath.len + 1); } - diff --git a/qse/lib/http/httpd-std.c b/qse/lib/http/httpd-std.c index bd7e555d..46504a13 100644 --- a/qse/lib/http/httpd-std.c +++ b/qse/lib/http/httpd-std.c @@ -2110,22 +2110,22 @@ static int format_error ( { int n; server_xtn_t* server_xtn; - const qse_mchar_t* css, * msg, * name; + const qse_mchar_t* head, * foot, * msg; server_xtn = qse_httpd_getserverxtn (httpd, client->server); - if (server_xtn->query (httpd, client->server, QSE_NULL, QSE_NULL, QSE_HTTPD_SERVERSTD_ERRCSS, &css) <= -1) css = QSE_NULL; - if (css == QSE_NULL) css = QSE_MT(""); + if (server_xtn->query (httpd, client->server, QSE_NULL, QSE_NULL, QSE_HTTPD_SERVERSTD_ERRHEAD, &head) <= -1) head = QSE_NULL; + if (head == QSE_NULL) head = QSE_MT(""); - if (server_xtn->query (httpd, client->server, QSE_NULL, QSE_NULL, QSE_HTTPD_SERVERSTD_NAME, &name) <= -1) name = QSE_NULL; - if (name == QSE_NULL) name = qse_httpd_getname(httpd); + if (server_xtn->query (httpd, client->server, QSE_NULL, QSE_NULL, QSE_HTTPD_SERVERSTD_ERRFOOT, &foot) <= -1) foot = QSE_NULL; + if (foot == QSE_NULL) foot = qse_httpd_getname(httpd); msg = qse_httpstatustombs(code); /* TODO: use my own version of snprintf replacement */ n = snprintf (buf, bufsz, QSE_MT("%s%s
HTTP ERROR
%d %s
"), - css, msg, code, msg, name); + head, msg, code, msg, foot); if (n < 0 || n >= bufsz) { httpd->errnum = QSE_HTTPD_ENOBUF; @@ -2135,122 +2135,6 @@ static int format_error ( return n; } -static int format_dir ( - qse_httpd_t* httpd, qse_httpd_client_t* client, - const qse_mchar_t* qpath, const qse_httpd_dirent_t* dirent, - qse_mchar_t* buf, int bufsz) -{ -/* TODO: page encoding?? utf-8??? or derive name from cmgr or current locale??? */ -/* TODO: html escaping of ctx->qpath.ptr */ - int n; - server_xtn_t* server_xtn; - - server_xtn = qse_httpd_getserverxtn (httpd, client->server); - - if (dirent == QSE_NULL) - { - if (qpath) - { - /* header */ - const qse_mchar_t* css; - int is_root; - qse_mchar_t* qpath_esc; - - is_root = (qse_mbscmp (qpath, QSE_MT("/")) == 0); - - if (server_xtn->query (httpd, client->server, QSE_NULL, QSE_NULL, QSE_HTTPD_SERVERSTD_DIRCSS, &css) <= -1) css = QSE_NULL; - if (css == QSE_NULL) css = QSE_MT(""); - - qpath_esc = qse_httpd_escapehtml (httpd, qpath); - if (qpath_esc == QSE_NULL) return -1; - - n = snprintf (buf, bufsz, - QSE_MT("%s
%s
..
%s"), css, qpath_esc, - (is_root? QSE_MT(""): QSE_MT("")) - ); - - if (qpath_esc != qpath) qse_httpd_freemem (httpd, qpath_esc); - } - else - { - /* footer */ - const qse_mchar_t* name; - - if (server_xtn->query (httpd, client->server, QSE_NULL, QSE_NULL, QSE_HTTPD_SERVERSTD_NAME, &name) <= -1) name = QSE_NULL; - if (name == QSE_NULL) name = qse_httpd_getname(httpd); - - n = snprintf (buf, bufsz, QSE_MT("
..
"), name); - } - } - else - { - /* main entry */ - qse_mchar_t* encname; - qse_mchar_t* escname; - qse_btime_t bt; - qse_mchar_t tmbuf[32]; - qse_mchar_t fszbuf[64]; - - /* TODO: better buffer management in case there are - * a lot of file names to escape. */ - - /* perform percent-encoding for the anchor */ - encname = qse_perenchttpstrdup (dirent->name, httpd->mmgr); - if (encname == QSE_NULL) - { - httpd->errnum = QSE_HTTPD_ENOMEM; - return -1; - } - - /* perform html escaping for the text */ - escname = qse_httpd_escapehtml (httpd, dirent->name); - if (escname == QSE_NULL) - { - if (encname != dirent->name) QSE_MMGR_FREE (httpd->mmgr, encname); - return -1; - } - - qse_localtime (&dirent->stat.mtime, &bt); - snprintf (tmbuf, QSE_COUNTOF(tmbuf), - QSE_MT("%04d-%02d-%02d %02d:%02d:%02d"), - bt.year + QSE_BTIME_YEAR_BASE, bt.mon + 1, bt.mday, - bt.hour, bt.min, bt.sec); - - if (dirent->stat.isdir) - { - fszbuf[0] = QSE_MT('\0'); - } - else - { - qse_fmtuintmaxtombs ( - fszbuf, QSE_COUNTOF(fszbuf), - dirent->stat.size, 10, -1, QSE_MT('\0'), QSE_NULL - ); - } - - n = snprintf ( - buf, bufsz, - QSE_MT("%s%s%s%s"), - encname, - (dirent->stat.isdir? QSE_MT("/"): QSE_MT("")), - escname, - (dirent->stat.isdir? QSE_MT("/"): QSE_MT("")), - tmbuf, fszbuf - ); - - if (escname != dirent->name) qse_httpd_freemem (httpd, escname); - if (encname != dirent->name) QSE_MMGR_FREE (httpd->mmgr, encname); - } - - if (n <= -1 || n >= bufsz) - { - httpd->errnum = QSE_HTTPD_ENOBUF; - return -1; - } - - return n; -} - static void impede_httpd (qse_httpd_t* httpd) { /* do nothing */ @@ -2321,7 +2205,6 @@ static qse_httpd_rcb_t httpd_request_callbacks = QSE_STRUCT_FIELD(peekreq, peek_request), QSE_STRUCT_FIELD(pokereq, poke_request), QSE_STRUCT_FIELD(fmterr, format_error), - QSE_STRUCT_FIELD(fmtdir, format_dir), QSE_STRUCT_FIELD(impede, impede_httpd), QSE_STRUCT_FIELD(logact, logact_httpd) }; @@ -2788,6 +2671,8 @@ auth_ok: { target->type = QSE_HTTPD_RSRC_DIR; 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, req, tmp.xpath, QSE_HTTPD_SERVERSTD_DIRFOOT, &target->u.dir.foot) <= -1) target->u.dir.foot = QSE_NULL; } } else @@ -2842,6 +2727,9 @@ auth_ok: { target->type = QSE_HTTPD_RSRC_DIR; 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, req, tmp.xpath, QSE_HTTPD_SERVERSTD_DIRFOOT, &target->u.dir.foot) <= -1) target->u.dir.foot = QSE_NULL; } else { @@ -2909,10 +2797,6 @@ static int query_server ( qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOENT); return -1; - case QSE_HTTPD_SERVERSTD_NAME: - *(const qse_mchar_t**)result = QSE_NULL; - break; - case QSE_HTTPD_SERVERSTD_ROOT: ((qse_httpd_serverstd_root_t*)result)->type = QSE_HTTPD_SERVERSTD_ROOT_PATH; ((qse_httpd_serverstd_root_t*)result)->u.path.val = QSE_NULL; @@ -2928,11 +2812,16 @@ static int query_server ( ((qse_httpd_serverstd_auth_t*)result)->authok = 1; break; - case QSE_HTTPD_SERVERSTD_ERRCSS: - case QSE_HTTPD_SERVERSTD_DIRCSS: + case QSE_HTTPD_SERVERSTD_ERRHEAD: + case QSE_HTTPD_SERVERSTD_DIRHEAD: *(const qse_mchar_t**)result = QSE_NULL; return 0; + case QSE_HTTPD_SERVERSTD_ERRFOOT: + case QSE_HTTPD_SERVERSTD_DIRFOOT: + *(const qse_mchar_t**)result = qse_httpd_getname(httpd); + return 0; + case QSE_HTTPD_SERVERSTD_INDEX: { qse_httpd_serverstd_index_t* index = (qse_httpd_serverstd_index_t*)result; diff --git a/qse/lib/http/httpd-task.c b/qse/lib/http/httpd-task.c index bcc708ec..aab5f295 100644 --- a/qse/lib/http/httpd-task.c +++ b/qse/lib/http/httpd-task.c @@ -425,7 +425,7 @@ qse_httpd_task_t* qse_httpd_entaskrsrc ( break; case QSE_HTTPD_RSRC_DIR: - task = qse_httpd_entaskdir (httpd, client, pred, rsrc->u.dir.path, req); + task = qse_httpd_entaskdir (httpd, client, pred, &rsrc->u.dir, req); break; case QSE_HTTPD_RSRC_ERR: diff --git a/qse/samples/cmn/Makefile.am b/qse/samples/cmn/Makefile.am index 3c7e968c..c61ceca3 100644 --- a/qse/samples/cmn/Makefile.am +++ b/qse/samples/cmn/Makefile.am @@ -8,8 +8,9 @@ AM_CPPFLAGS = \ bin_PROGRAMS = \ chr01 \ - env01 \ + dir01 \ dll \ + env01 \ fio01 \ fio02 \ fma \ diff --git a/qse/samples/cmn/Makefile.in b/qse/samples/cmn/Makefile.in index bb9eac7f..4073247f 100644 --- a/qse/samples/cmn/Makefile.in +++ b/qse/samples/cmn/Makefile.in @@ -34,16 +34,16 @@ PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ -bin_PROGRAMS = chr01$(EXEEXT) env01$(EXEEXT) dll$(EXEEXT) \ - fio01$(EXEEXT) fio02$(EXEEXT) fma$(EXEEXT) fmt01$(EXEEXT) \ - fmt02$(EXEEXT) fs01$(EXEEXT) htb$(EXEEXT) glob01$(EXEEXT) \ - ipad01$(EXEEXT) lda$(EXEEXT) main01$(EXEEXT) main02$(EXEEXT) \ - mbwc01$(EXEEXT) mbwc02$(EXEEXT) nwad01$(EXEEXT) \ - nwif01$(EXEEXT) nwif02$(EXEEXT) oht$(EXEEXT) path01$(EXEEXT) \ - pio$(EXEEXT) pma$(EXEEXT) rex01$(EXEEXT) rbt$(EXEEXT) \ - sio01$(EXEEXT) sio02$(EXEEXT) sio03$(EXEEXT) sll$(EXEEXT) \ - slmb01$(EXEEXT) str01$(EXEEXT) task01$(EXEEXT) time$(EXEEXT) \ - tre01$(EXEEXT) uri01$(EXEEXT) xma$(EXEEXT) +bin_PROGRAMS = chr01$(EXEEXT) dir01$(EXEEXT) dll$(EXEEXT) \ + env01$(EXEEXT) fio01$(EXEEXT) fio02$(EXEEXT) fma$(EXEEXT) \ + fmt01$(EXEEXT) fmt02$(EXEEXT) fs01$(EXEEXT) htb$(EXEEXT) \ + glob01$(EXEEXT) ipad01$(EXEEXT) lda$(EXEEXT) main01$(EXEEXT) \ + main02$(EXEEXT) mbwc01$(EXEEXT) mbwc02$(EXEEXT) \ + nwad01$(EXEEXT) nwif01$(EXEEXT) nwif02$(EXEEXT) oht$(EXEEXT) \ + path01$(EXEEXT) pio$(EXEEXT) pma$(EXEEXT) rex01$(EXEEXT) \ + rbt$(EXEEXT) sio01$(EXEEXT) sio02$(EXEEXT) sio03$(EXEEXT) \ + sll$(EXEEXT) slmb01$(EXEEXT) str01$(EXEEXT) task01$(EXEEXT) \ + time$(EXEEXT) tre01$(EXEEXT) uri01$(EXEEXT) xma$(EXEEXT) @WCHAR_TRUE@@WIN32_TRUE@am__append_1 = $(UNICOWS_LIBS) subdir = samples/cmn DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in @@ -71,6 +71,10 @@ chr01_DEPENDENCIES = $(am__DEPENDENCIES_2) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent +dir01_SOURCES = dir01.c +dir01_OBJECTS = dir01.$(OBJEXT) +dir01_LDADD = $(LDADD) +dir01_DEPENDENCIES = $(am__DEPENDENCIES_2) am_dll_OBJECTS = dll.$(OBJEXT) dll_OBJECTS = $(am_dll_OBJECTS) dll_LDADD = $(LDADD) @@ -241,18 +245,7 @@ am__v_CCLD_0 = @echo " CCLD " $@; AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; -SOURCES = $(chr01_SOURCES) $(dll_SOURCES) $(env01_SOURCES) \ - $(fio01_SOURCES) $(fio02_SOURCES) $(fma_SOURCES) \ - $(fmt01_SOURCES) $(fmt02_SOURCES) $(fs01_SOURCES) \ - $(glob01_SOURCES) $(htb_SOURCES) $(ipad01_SOURCES) \ - $(lda_SOURCES) $(main01_SOURCES) $(main02_SOURCES) \ - $(mbwc01_SOURCES) $(mbwc02_SOURCES) $(nwad01_SOURCES) nwif01.c \ - nwif02.c $(oht_SOURCES) $(path01_SOURCES) $(pio_SOURCES) \ - $(pma_SOURCES) $(rbt_SOURCES) $(rex01_SOURCES) \ - $(sio01_SOURCES) $(sio02_SOURCES) $(sio03_SOURCES) \ - $(sll_SOURCES) $(slmb01_SOURCES) $(str01_SOURCES) task01.c \ - $(time_SOURCES) $(tre01_SOURCES) uri01.c $(xma_SOURCES) -DIST_SOURCES = $(chr01_SOURCES) $(dll_SOURCES) $(env01_SOURCES) \ +SOURCES = $(chr01_SOURCES) dir01.c $(dll_SOURCES) $(env01_SOURCES) \ $(fio01_SOURCES) $(fio02_SOURCES) $(fma_SOURCES) \ $(fmt01_SOURCES) $(fmt02_SOURCES) $(fs01_SOURCES) \ $(glob01_SOURCES) $(htb_SOURCES) $(ipad01_SOURCES) \ @@ -263,6 +256,18 @@ DIST_SOURCES = $(chr01_SOURCES) $(dll_SOURCES) $(env01_SOURCES) \ $(sio01_SOURCES) $(sio02_SOURCES) $(sio03_SOURCES) \ $(sll_SOURCES) $(slmb01_SOURCES) $(str01_SOURCES) task01.c \ $(time_SOURCES) $(tre01_SOURCES) uri01.c $(xma_SOURCES) +DIST_SOURCES = $(chr01_SOURCES) dir01.c $(dll_SOURCES) \ + $(env01_SOURCES) $(fio01_SOURCES) $(fio02_SOURCES) \ + $(fma_SOURCES) $(fmt01_SOURCES) $(fmt02_SOURCES) \ + $(fs01_SOURCES) $(glob01_SOURCES) $(htb_SOURCES) \ + $(ipad01_SOURCES) $(lda_SOURCES) $(main01_SOURCES) \ + $(main02_SOURCES) $(mbwc01_SOURCES) $(mbwc02_SOURCES) \ + $(nwad01_SOURCES) nwif01.c nwif02.c $(oht_SOURCES) \ + $(path01_SOURCES) $(pio_SOURCES) $(pma_SOURCES) $(rbt_SOURCES) \ + $(rex01_SOURCES) $(sio01_SOURCES) $(sio02_SOURCES) \ + $(sio03_SOURCES) $(sll_SOURCES) $(slmb01_SOURCES) \ + $(str01_SOURCES) task01.c $(time_SOURCES) $(tre01_SOURCES) \ + uri01.c $(xma_SOURCES) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) @@ -560,6 +565,9 @@ clean-binPROGRAMS: chr01$(EXEEXT): $(chr01_OBJECTS) $(chr01_DEPENDENCIES) $(EXTRA_chr01_DEPENDENCIES) @rm -f chr01$(EXEEXT) $(AM_V_CCLD)$(LINK) $(chr01_OBJECTS) $(chr01_LDADD) $(LIBS) +dir01$(EXEEXT): $(dir01_OBJECTS) $(dir01_DEPENDENCIES) $(EXTRA_dir01_DEPENDENCIES) + @rm -f dir01$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(dir01_OBJECTS) $(dir01_LDADD) $(LIBS) dll$(EXEEXT): $(dll_OBJECTS) $(dll_DEPENDENCIES) $(EXTRA_dll_DEPENDENCIES) @rm -f dll$(EXEEXT) $(AM_V_CCLD)$(LINK) $(dll_OBJECTS) $(dll_LDADD) $(LIBS) @@ -676,6 +684,7 @@ distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chr01.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dir01.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dll.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/env01.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fio01.Po@am__quote@ diff --git a/qse/samples/cmn/fma.c b/qse/samples/cmn/fma.c index 3f402cfc..0bcdd34e 100644 --- a/qse/samples/cmn/fma.c +++ b/qse/samples/cmn/fma.c @@ -9,7 +9,7 @@ if (f() == -1) return -1; \ } while (0) -static qse_rbt_mancbs_t mancbs = +static qse_rbt_style_t style = { { QSE_RBT_COPIER_INLINE, @@ -117,7 +117,7 @@ static int test2 () qse_fma_close (fma); return -1; } - qse_rbt_setmancbs (&rbt, &mancbs); + qse_rbt_setstyle (&rbt, &style); for (x = 10; x < 100; x++) { diff --git a/qse/samples/cmn/htb.c b/qse/samples/cmn/htb.c index b3e98f29..02f8be0f 100644 --- a/qse/samples/cmn/htb.c +++ b/qse/samples/cmn/htb.c @@ -115,7 +115,7 @@ static int test1 () qse_printf (QSE_T("cannot open a hash table\n")); return -1; } - qse_htb_setmancbs (s1, qse_gethtbmancbs(QSE_HTB_MANCBS_INLINE_COPIERS)); + qse_htb_setstyle (s1, qse_gethtbstyle(QSE_HTB_STYLE_INLINE_COPIERS)); if (test1_build(s1) == -1) { @@ -167,7 +167,7 @@ static int test2 () qse_printf (QSE_T("cannot open a hash table\n")); return -1; } - qse_htb_setmancbs (s1, qse_gethtbmancbs(QSE_HTB_MANCBS_INLINE_COPIERS)); + qse_htb_setstyle (s1, qse_gethtbstyle(QSE_HTB_STYLE_INLINE_COPIERS)); for (i = 0; i < QSE_COUNTOF(keys); i++) { @@ -384,7 +384,7 @@ static int test5 () qse_printf (QSE_T("cannot open a hash table\n")); return -1; } - qse_htb_setmancbs (s1, qse_gethtbmancbs(QSE_HTB_MANCBS_INLINE_COPIERS)); + qse_htb_setstyle (s1, qse_gethtbstyle(QSE_HTB_STYLE_INLINE_COPIERS)); for (i = 0; i < QSE_COUNTOF(vals); i++) { diff --git a/qse/samples/cmn/rbt.c b/qse/samples/cmn/rbt.c index efbfe8df..4ec81aad 100644 --- a/qse/samples/cmn/rbt.c +++ b/qse/samples/cmn/rbt.c @@ -40,7 +40,7 @@ static int test1 () qse_printf (QSE_T("cannot open a table\n")); return -1; } - qse_rbt_setmancbs (s1, qse_getrbtmancbs(QSE_RBT_MANCBS_INLINE_COPIERS)); + qse_rbt_setstyle (s1, qse_getrbtstyle(QSE_RBT_STYLE_INLINE_COPIERS)); for (i = 0; i < 20; i++) { @@ -100,7 +100,7 @@ static int test2 () qse_printf (QSE_T("cannot open a table\n")); return -1; } - qse_rbt_setmancbs (s1, qse_getrbtmancbs(QSE_RBT_MANCBS_INLINE_COPIERS)); + qse_rbt_setstyle (s1, qse_getrbtstyle(QSE_RBT_STYLE_INLINE_COPIERS)); qse_rbt_insert (s1, QSE_T("hello"), 5, QSE_T("mr. monkey"), 10); qse_rbt_insert (s1, QSE_T("world"), 5, QSE_T("ms. panda"), 9); @@ -192,7 +192,7 @@ static int test5 () qse_printf (QSE_T("cannot open a hash table\n")); return -1; } - qse_rbt_setmancbs (s1, qse_getrbtmancbs(QSE_RBT_MANCBS_INLINE_COPIERS)); + qse_rbt_setstyle (s1, qse_getrbtstyle(QSE_RBT_STYLE_INLINE_COPIERS)); for (i = 0; i < QSE_COUNTOF(vals); i++) {