From a523f1443b4bac68b936016a31222f60d6935f72 Mon Sep 17 00:00:00 2001 From: hyung-hwan Date: Mon, 10 Dec 2012 03:10:44 +0000 Subject: [PATCH] added qse_isdriveabspath(). enhanced httpd to accept drive path as a doc root for win/os2 --- qse/include/qse/cmn/mux.h | 4 ++ qse/include/qse/cmn/path.h | 18 ++++++ qse/include/qse/net/httpd.h | 1 - qse/lib/cmn/mux.c | 40 +++++++------- qse/lib/cmn/path-canon.c | 16 ++++++ qse/lib/net/httpd-std.c | 106 +++++++++++++++++++++--------------- qse/lib/net/httpd.c | 7 +-- 7 files changed, 124 insertions(+), 68 deletions(-) diff --git a/qse/include/qse/cmn/mux.h b/qse/include/qse/cmn/mux.h index f0860e0d..1b38af09 100644 --- a/qse/include/qse/cmn/mux.h +++ b/qse/include/qse/cmn/mux.h @@ -102,6 +102,10 @@ QSE_EXPORT void* qse_mux_getxtn ( qse_mux_t* mux ); +QSE_EXPORT qse_mux_errnum_t qse_mux_geterrnum ( + qse_mux_t* mux +); + QSE_EXPORT int qse_mux_insert ( qse_mux_t* mux, const qse_mux_evt_t* evt diff --git a/qse/include/qse/cmn/path.h b/qse/include/qse/cmn/path.h index d6873dfa..fcb7296a 100644 --- a/qse/include/qse/cmn/path.h +++ b/qse/include/qse/cmn/path.h @@ -99,6 +99,14 @@ QSE_EXPORT int qse_ismbsdrivepath ( const qse_mchar_t* path ); +/** + * The qse_ismbsdriveabspath() function determines if a path name is in the form + * of a drive letter followed by a colon like A: and a path separator. + */ +QSE_EXPORT int qse_ismbsdriveabspath ( + const qse_mchar_t* path +); + /** * The qse_ismbsdrivecurpath() function determines if a path name is in the form * of a drive letter followed by a colon like A:, without any trailing path. @@ -165,6 +173,14 @@ QSE_EXPORT int qse_iswcsdrivepath ( const qse_wchar_t* path ); +/** + * The qse_iswcsdriveabspath() function determines if a path name is in the form + * of a drive letter followed by a colon like A: and a path separtor. + */ +QSE_EXPORT int qse_iswcsdriveabspath ( + const qse_wchar_t* path +); + /** * The qse_iswcsdrivecurpath() function determines if a path name is in the form * of a drive letter followed by a colon like A:, without any trailing path. @@ -215,11 +231,13 @@ QSE_EXPORT qse_size_t qse_canonwcspath ( #if defined(QSE_CHAR_IS_MCHAR) # define qse_isabspath(p) qse_ismbsabspath(p) # define qse_isdrivepath(p) qse_ismbsdrivepath(p) +# define qse_isdriveabspath(p) qse_ismbsdriveabspath(p) # define qse_isdrivecurpath(p) qse_ismbsdrivecurpath(p) # define qse_canonpath(p,c,f) qse_canonmbspath(p,c,f) #else # define qse_isabspath(p) qse_iswcsabspath(p) # define qse_isdrivepath(p) qse_iswcsdrivepath(p) +# define qse_isdriveabspath(p) qse_iswcsdriveabspath(p) # define qse_isdrivecurpath(p) qse_iswcsdrivecurpath(p) # define qse_canonpath(p,c,f) qse_canonwcspath(p,c,f) #endif diff --git a/qse/include/qse/net/httpd.h b/qse/include/qse/net/httpd.h index e0d1f965..ac454e48 100644 --- a/qse/include/qse/net/httpd.h +++ b/qse/include/qse/net/httpd.h @@ -49,7 +49,6 @@ enum qse_httpd_errnum_t QSE_HTTPD_EAGAIN, QSE_HTTPD_ENOBUF, - QSE_HTTPD_EIOMUX, QSE_HTTPD_EDISCON, /* client disconnnected */ QSE_HTTPD_EBADREQ, /* bad request */ QSE_HTTPD_ETASK diff --git a/qse/lib/cmn/mux.c b/qse/lib/cmn/mux.c index e7ac875d..c692c7c6 100644 --- a/qse/lib/cmn/mux.c +++ b/qse/lib/cmn/mux.c @@ -363,14 +363,17 @@ void* qse_mux_getxtn (qse_mux_t* mux) return QSE_XTN (mux); } +qse_mux_errnum_t qse_mux_geterrnum (qse_mux_t* mux) +{ + return mux->errnum; +} + #define ALIGN_TO(num,align) ((((num) + (align) - 1) / (align)) * (align)) int qse_mux_insert (qse_mux_t* mux, const qse_mux_evt_t* evt) { #if defined(__OS2__) -if (evt) qse_printf (QSE_T("INSERTING HANDLE %d\n"), (int)evt->hnd); -else qse_printf (QSE_T("WHAT..... NULL\n")); if (evt->hnd >= mux->me.ubound) { qse_mux_evt_t** tmp; @@ -564,6 +567,7 @@ int qse_mux_delete (qse_mux_t* mux, const qse_mux_evt_t* evt) } mevt->hnd = -1; + mevt->mask = 0; mux->size--; return 0; @@ -608,6 +612,7 @@ int qse_mux_delete (qse_mux_t* mux, const qse_mux_evt_t* evt) done: mevt->hnd = -1; + mevt->mask = 0; mux->size--; return 0; @@ -652,15 +657,13 @@ int qse_mux_poll (qse_mux_t* mux, const qse_ntime_t* tmout) for (i = 0; i < mux->me.ubound; i++) { evt = mux->me.ptr[i]; - if (evt && (evt->mask & QSE_MUX_IN)) - mux->fdarr[count++] = evt->hnd; + if (evt && (evt->mask & QSE_MUX_IN)) mux->fdarr[count++] = evt->hnd; } rcount = count; for (i = 0; i < mux->me.ubound; i++) { evt = mux->me.ptr[i]; - if (evt && (evt->mask & QSE_MUX_OUT)) - mux->fdarr[count++] = evt->hnd; + if (evt && (evt->mask & QSE_MUX_OUT)) mux->fdarr[count++] = evt->hnd; } wcount = count - rcount; @@ -677,22 +680,21 @@ int qse_mux_poll (qse_mux_t* mux, const qse_ntime_t* tmout) for (i = 0; i < count; i++) { - evt = mux->me.ptr[i]; - if (!evt || evt->hnd != i || mux->fdarr[i] == -1) continue; + if (mux->fdarr[i] == -1) continue; - QSE_MEMCPY (&xevt, evt, QSE_SIZEOF(xevt)); + evt = mux->me.ptr[mux->fdarr[i]]; + if (!evt || evt->hnd != mux->fdarr[i]) continue; - xevt.mask = 0; - if ((evt->mask & QSE_MUX_IN) && i < rcount) - xevt.mask |= QSE_MUX_IN; - if ((evt->mask & QSE_MUX_OUT) && i >= rcount) - xevt.mask |= QSE_MUX_OUT; + xevt = *evt; - if (xevt.mask > 0) mux->evtfun (mux, &xevt); + /* due to the way i check 'fdarr' , it can't have + * both IN and OUT at the same time. they are + * triggered separately */ + xevt.mask = (i < rcount)? QSE_MUX_IN: QSE_MUX_OUT; + mux->evtfun (mux, &xevt); } } - return n; #elif defined(USE_SELECT) @@ -728,8 +730,7 @@ int qse_mux_poll (qse_mux_t* mux, const qse_ntime_t* tmout) evt = mux->me.ptr[i]; if (!evt || evt->hnd != i) continue; - QSE_MEMCPY (&xevt, evt, QSE_SIZEOF(xevt)); - + xevt = *evt; xevt.mask = 0; if ((evt->mask & QSE_MUX_IN) && FD_ISSET(evt->hnd, &mux->tmprset)) xevt.mask |= QSE_MUX_IN; @@ -764,8 +765,7 @@ int qse_mux_poll (qse_mux_t* mux, const qse_ntime_t* tmout) evt = mux->ee.ptr[i].data.ptr; - QSE_MEMCPY (&xevt, evt, QSE_SIZEOF(xevt)); - + xevt = *evt; xevt.mask = 0; if (mux->ee.ptr[i].events & EPOLLIN) xevt.mask |= QSE_MUX_IN; if (mux->ee.ptr[i].events & EPOLLOUT) xevt.mask |= QSE_MUX_OUT; diff --git a/qse/lib/cmn/path-canon.c b/qse/lib/cmn/path-canon.c index a2d0be74..34f02859 100644 --- a/qse/lib/cmn/path-canon.c +++ b/qse/lib/cmn/path-canon.c @@ -53,6 +53,14 @@ int qse_ismbsdrivepath (const qse_mchar_t* path) return 0; } +int qse_ismbsdriveabspath (const qse_mchar_t* path) +{ +#if defined(_WIN32) || defined(__OS2__) || defined(__DOS__) + if (IS_MDRIVE(path) && IS_MSEP(path[2])) return 1; +#endif + return 0; +} + int qse_ismbsdrivecurpath (const qse_mchar_t* path) { #if defined(_WIN32) || defined(__OS2__) || defined(__DOS__) @@ -360,6 +368,14 @@ int qse_iswcsdrivepath (const qse_wchar_t* path) return 0; } +int qse_iswcsdriveabspath (const qse_wchar_t* path) +{ +#if defined(_WIN32) || defined(__OS2__) || defined(__DOS__) + if (IS_WDRIVE(path) && IS_WSEP(path[2])) return 1; +#endif + return 0; +} + int qse_iswcsdrivecurpath (const qse_wchar_t* path) { #if defined(_WIN32) || defined(__OS2__) || defined(__DOS__) diff --git a/qse/lib/net/httpd-std.c b/qse/lib/net/httpd-std.c index d61be466..715bfd03 100644 --- a/qse/lib/net/httpd-std.c +++ b/qse/lib/net/httpd-std.c @@ -241,6 +241,35 @@ static qse_httpd_errnum_t syserr_to_errnum (int e) } #endif + +static qse_httpd_errnum_t muxerr_to_errnum (qse_mux_errnum_t e) +{ + switch (e) + { + case QSE_MUX_ENOMEM: + return QSE_HTTPD_ENOMEM; + + case QSE_MUX_EINVAL: + return QSE_HTTPD_EINVAL; + + case QSE_MUX_EACCES: + return QSE_HTTPD_EACCES; + + case QSE_MUX_ENOENT: + return QSE_HTTPD_ENOENT; + + case QSE_MUX_EEXIST: + return QSE_HTTPD_EEXIST; + + case QSE_MUX_EINTR: + return QSE_HTTPD_EINTR; + + default: + return QSE_HTTPD_ESYSERR; + } +} + + /* ------------------------------------------------------------------- */ #define MAX_SEND_SIZE 4096 @@ -891,9 +920,7 @@ static void* mux_open (qse_httpd_t* httpd, qse_httpd_muxcb_t cbfun) mux = qse_mux_open (httpd->mmgr, QSE_SIZEOF(*xtn), dispatch_muxcb, 256); if (!mux) { -/* TODO - qse_httpd_seterrnum (httpd, muxerr_to_errnum(mux)); -*/ + qse_httpd_seterrnum (httpd, QSE_HTTPD_ESYSERR); return QSE_NULL; } @@ -921,9 +948,7 @@ static int mux_addhnd ( if (qse_mux_insert ((qse_mux_t*)vmux, &evt) <= -1) { -/* TODO - qse_httpd_seterrnum (httpd, muxerr_to_errnum(mux)); -*/ + qse_httpd_seterrnum (httpd, muxerr_to_errnum(qse_mux_geterrnum((qse_mux_t*)vmux))); return -1; } @@ -936,9 +961,7 @@ static int mux_delhnd (qse_httpd_t* httpd, void* vmux, qse_ubi_t handle) evt.hnd = handle.i; if (qse_mux_delete ((qse_mux_t*)vmux, &evt) <= -1) { -/* TODO - qse_httpd_seterrnum (httpd, muxerr_to_errnum(mux)); -*/ + qse_httpd_seterrnum (httpd, muxerr_to_errnum(qse_mux_geterrnum((qse_mux_t*)vmux))); return -1; } return 0; @@ -948,9 +971,7 @@ static int mux_poll (qse_httpd_t* httpd, void* vmux, const qse_ntime_t* tmout) { if (qse_mux_poll ((qse_mux_t*)vmux, tmout) <= -1) { -/* TODO - qse_httpd_seterrnum (httpd, muxerr_to_errnum(mux)); -*/ + qse_httpd_seterrnum (httpd, muxerr_to_errnum(qse_mux_geterrnum((qse_mux_t*)vmux))); return -1; } @@ -1021,9 +1042,6 @@ static int stat_file ( WIN32_FIND_DATAA fdata; ULARGE_INTEGER li; - /* fail if the path name contains a wilecard letter */ - if (qse_mbspbrk (path, QSE_MT("?*")) != QSE_NULL) return -1; - if (path[0] == QSE_MT('/') && path[1] == QSE_MT('\0')) { /* the root directory won't work well with FindFirstFile().*/ @@ -1035,6 +1053,9 @@ static int stat_file ( { /* TODO: hst->dev can be set to the drive letter's index. */ + /* fail if the path name contains a wilecard letter */ + if (qse_mbspbrk (path, QSE_MT("?*")) != QSE_NULL) return -1; + fh = FindFirstFileA (path, &fdata); if (fh == INVALID_HANDLE_VALUE) return -1; @@ -1056,29 +1077,10 @@ static int stat_file ( #elif defined(__OS2__) APIRET rc; - FILEFINDBUF3L ffb; qse_btime_t bt; qse_ntime_t nt; - #if 0 - HDIR h; - ULONG count; - - /* fail if the path name contains a wilecard letter */ - if (qse_mbspbrk (path, QSE_MT("?*")) != QSE_NULL) return -1; - - rc = DosFindFirst ( - path, - &h, - FILE_DIRECTORY | FILE_READONLY, - &ffb, - QSE_SIZEOF(ffb), - &count, - FIL_STANDARDL); - if (rc != NO_ERROR) return -1; - - DosFindClose (h); - #endif + FILESTATUS3L ffb; rc = DosQueryPathInfo (path, FIL_STANDARDL, &ffb, QSE_SIZEOF(ffb)); if (rc != NO_ERROR) return -1; @@ -1987,7 +1989,7 @@ static int make_resource ( qse_mchar_t* xpath; qse_httpd_stat_t st; qse_size_t i; - int n; + int n, stx; qpath = qse_htre_getqpath(req); @@ -2022,10 +2024,23 @@ auth_ok: xpath = merge_paths (httpd, server_xtn->cfg[SERVER_XTN_CFG_DOCROOT], qpath); if (xpath == QSE_NULL) return -1; -qse_printf (QSE_T(">>> check if [%hs] is a directory\n"), xpath); - if (stat_file (httpd, xpath, &st, 0) >= 0 && st.isdir) + stx = stat_file (httpd, xpath, &st, 0); +#if defined(_WIN32) || defined(__OS2__) || defined(__DOS__) + if (stx <= -1) + { + /* these OS may fail if the path contains the trailing separator. + * i work around it here */ + qse_size_t pl = qse_mbslen(xpath); + if (pl > 1 && xpath[pl - 1] == QSE_MT('/')) + { + xpath[pl-1] = QSE_MT('\0'); + stx = stat_file (httpd, xpath, &st, 0); + xpath[pl-1] = QSE_MT('/'); + } + } +#endif + if (stx >= 0 && st.isdir) { -qse_printf (QSE_T(">>> [%hs] is a directory\n"), xpath); /* it is a directory */ if (server_xtn->cfg2.s.idxstd) { @@ -2056,11 +2071,9 @@ qse_printf (QSE_T(">>> [%hs] is a directory\n"), xpath); target->type = QSE_HTTPD_RSRC_DIR; target->u.dir.path = xpath; -qse_printf (QSE_T(">>> MADE DIREcTORY RESOURCE [%hs]\n"), xpath); } else { -qse_printf (QSE_T(">>> [%hs] is a file\n"), xpath); attempt_file: if (server_xtn->cfg2.s.cgistd) { @@ -2216,6 +2229,7 @@ qse_httpd_server_t* qse_httpd_attachserverstd ( if (!xuri.path.ptr) { + /* the path part is not specified */ #if defined(QSE_CHAR_IS_MCHAR) xuri.path.ptr = QSE_MT("/"); #else @@ -2236,12 +2250,18 @@ qse_httpd_server_t* qse_httpd_attachserverstd ( } #if defined(QSE_CHAR_IS_MCHAR) - server_xtn->cfg[SERVER_XTN_CFG_DOCROOT] = qse_mbsxdup (xuri.path.ptr, xuri.path.len, httpd->mmgr); + if (qse_ismbsdriveabspath((const qse_mchar_t*)xuri.path.ptr + 1)) + server_xtn->cfg[SERVER_XTN_CFG_DOCROOT] = qse_mbsxdup ((const qse_mchar_t*)xuri.path.ptr + 1, xuri.path.len - 1, httpd->mmgr); + else + server_xtn->cfg[SERVER_XTN_CFG_DOCROOT] = qse_mbsxdup (xuri.path.ptr, xuri.path.len, httpd->mmgr); if (xuri.frag.ptr) server_xtn->cfg[SERVER_XTN_CFG_REALM] = qse_mbsxdup (xuri.frag.ptr, xuri.frag.len, httpd->mmgr); ba.ptr = qse_mcstradup (tmp, &ba.len, httpd->mmgr); #else - server_xtn->cfg[SERVER_XTN_CFG_DOCROOT] = qse_wcsntombsdup (xuri.path.ptr, xuri.path.len, QSE_NULL, httpd->mmgr); + if (qse_iswcsdriveabspath((const qse_wchar_t*)xuri.path.ptr + 1)) + server_xtn->cfg[SERVER_XTN_CFG_DOCROOT] = qse_wcsntombsdup ((const qse_wchar_t*)xuri.path.ptr + 1, xuri.path.len - 1, QSE_NULL, httpd->mmgr); + else + server_xtn->cfg[SERVER_XTN_CFG_DOCROOT] = qse_wcsntombsdup (xuri.path.ptr, xuri.path.len, QSE_NULL, httpd->mmgr); if (xuri.frag.ptr) server_xtn->cfg[SERVER_XTN_CFG_REALM] = qse_wcsntombsdup (xuri.frag.ptr, xuri.frag.len, QSE_NULL, httpd->mmgr); ba.ptr = qse_wcsnatombsdup (tmp, &ba.len, httpd->mmgr); #endif diff --git a/qse/lib/net/httpd.c b/qse/lib/net/httpd.c index e304f57a..c5c40ff4 100644 --- a/qse/lib/net/httpd.c +++ b/qse/lib/net/httpd.c @@ -647,10 +647,12 @@ qse_printf (QSE_T(">>>>> Returning failure for client %d\n"), client->handle.i); } qse_printf (QSE_T("!!!!!FEEDING %d from %d ["), (int)m, (int)client->handle.i); +#if !defined(__OS2__) { int i; for (i = 0; i < m; i++) qse_printf (QSE_T("%hc"), buf[i]); } +#endif qse_printf (QSE_T("]\n")); /* qse_htrd_feed() may call the request callback @@ -1134,15 +1136,12 @@ qse_printf (QSE_T("no servers are active....\n")); { int count; -qse_printf (QSE_T("POLLING %d tmout ..\n"), tmout->sec); count = httpd->scb->mux.poll (httpd, httpd->mux, tmout); -qse_printf (QSE_T("POLLING %d return ..\n"), count); if (count <= -1) { - httpd->errnum = QSE_HTTPD_EIOMUX; /* TODO: call user callback for this multiplexer error */ /*if (errno == EINTR) continue;*/ -qse_fprintf (QSE_STDERR, QSE_T("Error: mux returned failure\n")); +qse_fprintf (QSE_STDERR, QSE_T("Error: mux returned failure %d\n"), (int)httpd->errnum); /* break; */ }