added qse_isdriveabspath().

enhanced httpd to accept drive path as a doc root for win/os2
This commit is contained in:
hyung-hwan 2012-12-10 03:10:44 +00:00
parent 5936aea85f
commit a523f1443b
7 changed files with 124 additions and 68 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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__)

View File

@ -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,11 +2250,17 @@ qse_httpd_server_t* qse_httpd_attachserverstd (
}
#if defined(QSE_CHAR_IS_MCHAR)
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
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);

View File

@ -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; */
}