enhanced httpd directory listing
This commit is contained in:
@ -110,6 +110,7 @@ CXXFLAGS = @CXXFLAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
DLLTOOL = @DLLTOOL@
|
||||
DSYMUTIL = @DSYMUTIL@
|
||||
DUMPBIN = @DUMPBIN@
|
||||
ECHO = @ECHO@
|
||||
@ -137,6 +138,7 @@ LIPO = @LIPO@
|
||||
LN_S = @LN_S@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
MANIFEST_TOOL = @MANIFEST_TOOL@
|
||||
MKDIR_P = @MKDIR_P@
|
||||
NM = @NM@
|
||||
NMEDIT = @NMEDIT@
|
||||
@ -182,6 +184,7 @@ abs_builddir = @abs_builddir@
|
||||
abs_srcdir = @abs_srcdir@
|
||||
abs_top_builddir = @abs_top_builddir@
|
||||
abs_top_srcdir = @abs_top_srcdir@
|
||||
ac_ct_AR = @ac_ct_AR@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_CXX = @ac_ct_CXX@
|
||||
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
|
||||
@ -216,7 +219,6 @@ libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
localedir = @localedir@
|
||||
localstatedir = @localstatedir@
|
||||
lt_ECHO = @lt_ECHO@
|
||||
mandir = @mandir@
|
||||
mkdir_p = @mkdir_p@
|
||||
oldincludedir = @oldincludedir@
|
||||
|
@ -1077,6 +1077,7 @@ int Awk::open ()
|
||||
prm.math.atan = atan;
|
||||
prm.math.atan2 = atan2;
|
||||
prm.math.log = log;
|
||||
prm.math.log10 = log10;
|
||||
prm.math.exp = exp;
|
||||
prm.math.sqrt = sqrt;
|
||||
|
||||
@ -1792,6 +1793,12 @@ Awk::flt_t Awk::log (awk_t* awk, flt_t x)
|
||||
return xtn->awk->log (x);
|
||||
}
|
||||
|
||||
Awk::flt_t Awk::log10 (awk_t* awk, flt_t x)
|
||||
{
|
||||
xtn_t* xtn = (xtn_t*) QSE_XTN (awk);
|
||||
return xtn->awk->log10 (x);
|
||||
}
|
||||
|
||||
Awk::flt_t Awk::exp (awk_t* awk, flt_t x)
|
||||
{
|
||||
xtn_t* xtn = (xtn_t*) QSE_XTN (awk);
|
||||
|
@ -137,6 +137,7 @@ CXXFLAGS = @CXXFLAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
DLLTOOL = @DLLTOOL@
|
||||
DSYMUTIL = @DSYMUTIL@
|
||||
DUMPBIN = @DUMPBIN@
|
||||
ECHO = @ECHO@
|
||||
@ -164,6 +165,7 @@ LIPO = @LIPO@
|
||||
LN_S = @LN_S@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
MANIFEST_TOOL = @MANIFEST_TOOL@
|
||||
MKDIR_P = @MKDIR_P@
|
||||
NM = @NM@
|
||||
NMEDIT = @NMEDIT@
|
||||
@ -209,6 +211,7 @@ abs_builddir = @abs_builddir@
|
||||
abs_srcdir = @abs_srcdir@
|
||||
abs_top_builddir = @abs_top_builddir@
|
||||
abs_top_srcdir = @abs_top_srcdir@
|
||||
ac_ct_AR = @ac_ct_AR@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_CXX = @ac_ct_CXX@
|
||||
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
|
||||
@ -243,7 +246,6 @@ libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
localedir = @localedir@
|
||||
localstatedir = @localstatedir@
|
||||
lt_ECHO = @lt_ECHO@
|
||||
mandir = @mandir@
|
||||
mkdir_p = @mkdir_p@
|
||||
oldincludedir = @oldincludedir@
|
||||
|
@ -833,6 +833,7 @@ StdAwk::flt_t StdAwk::atan2 (flt_t x, flt_t y)
|
||||
|
||||
StdAwk::flt_t StdAwk::log (flt_t x)
|
||||
{
|
||||
/* natural logarithm */
|
||||
#if defined(HAVE_LOGL) && (QSE_SIZEOF_LONG_DOUBLE > QSE_SIZEOF_DOUBLE)
|
||||
return ::logl (x);
|
||||
#elif defined(HAVE_LOG)
|
||||
@ -844,6 +845,20 @@ StdAwk::flt_t StdAwk::log (flt_t x)
|
||||
#endif
|
||||
}
|
||||
|
||||
StdAwk::flt_t StdAwk::log10 (flt_t x)
|
||||
{
|
||||
/* common logarithm */
|
||||
#if defined(HAVE_LOG10L) && (QSE_SIZEOF_LONG_DOUBLE > QSE_SIZEOF_DOUBLE)
|
||||
return ::log10l (x);
|
||||
#elif defined(HAVE_LOG10)
|
||||
return ::log10 (x);
|
||||
#elif defined(HAVE_LOG10F)
|
||||
return ::log10f (x);
|
||||
#else
|
||||
#error ### no log10 function available ###
|
||||
#endif
|
||||
}
|
||||
|
||||
StdAwk::flt_t StdAwk::exp (flt_t x)
|
||||
{
|
||||
#if defined(HAVE_EXPL) && (QSE_SIZEOF_LONG_DOUBLE > QSE_SIZEOF_DOUBLE)
|
||||
|
@ -128,6 +128,7 @@ qse_awk_t* qse_awk_open (qse_mmgr_t* mmgr, qse_size_t xtn, qse_awk_prm_t* prm)
|
||||
QSE_ASSERT (prm->math.atan != QSE_NULL);
|
||||
QSE_ASSERT (prm->math.atan2 != QSE_NULL);
|
||||
QSE_ASSERT (prm->math.log != QSE_NULL);
|
||||
QSE_ASSERT (prm->math.log10 != QSE_NULL);
|
||||
QSE_ASSERT (prm->math.exp != QSE_NULL);
|
||||
QSE_ASSERT (prm->math.sqrt != QSE_NULL);
|
||||
if (prm == QSE_NULL ||
|
||||
@ -139,6 +140,7 @@ qse_awk_t* qse_awk_open (qse_mmgr_t* mmgr, qse_size_t xtn, qse_awk_prm_t* prm)
|
||||
prm->math.atan == QSE_NULL ||
|
||||
prm->math.atan2 == QSE_NULL ||
|
||||
prm->math.log == QSE_NULL ||
|
||||
prm->math.log10 == QSE_NULL ||
|
||||
prm->math.exp == QSE_NULL ||
|
||||
prm->math.sqrt == QSE_NULL)
|
||||
{
|
||||
|
@ -39,6 +39,7 @@ static int fnc_tan (qse_awk_rtx_t* rtx, const qse_cstr_t* fnm);
|
||||
static int fnc_atan (qse_awk_rtx_t* rtx, const qse_cstr_t* fnm);
|
||||
static int fnc_atan2 (qse_awk_rtx_t* rtx, const qse_cstr_t* fnm);
|
||||
static int fnc_log (qse_awk_rtx_t* rtx, const qse_cstr_t* fnm);
|
||||
static int fnc_log10 (qse_awk_rtx_t* rtx, const qse_cstr_t* fnm);
|
||||
static int fnc_exp (qse_awk_rtx_t* rtx, const qse_cstr_t* fnm);
|
||||
static int fnc_sqrt (qse_awk_rtx_t* rtx, const qse_cstr_t* fnm);
|
||||
static int fnc_int (qse_awk_rtx_t* rtx, const qse_cstr_t* fnm);
|
||||
@ -84,6 +85,7 @@ static qse_awk_fnc_t sys_fnc[] =
|
||||
{ {QSE_T("atan"), 4}, 0, 0, {1, 1, QSE_NULL}, fnc_atan},
|
||||
{ {QSE_T("atan2"), 5}, 0, 0, {2, 2, QSE_NULL}, fnc_atan2},
|
||||
{ {QSE_T("log"), 3}, 0, 0, {1, 1, QSE_NULL}, fnc_log},
|
||||
{ {QSE_T("log10"), 5}, 0, 0, {1, 1, QSE_NULL}, fnc_log10},
|
||||
{ {QSE_T("exp"), 3}, 0, 0, {1, 1, QSE_NULL}, fnc_exp},
|
||||
{ {QSE_T("sqrt"), 4}, 0, 0, {1, 1, QSE_NULL}, fnc_sqrt},
|
||||
{ {QSE_T("int"), 3}, 0, 0, {1, 1, QSE_NULL}, fnc_int},
|
||||
@ -1473,6 +1475,10 @@ static int fnc_log (qse_awk_rtx_t* rtx, const qse_cstr_t* fnm)
|
||||
{
|
||||
return fnc_math_1 (rtx, fnm, rtx->awk->prm.math.log);
|
||||
}
|
||||
static int fnc_log10 (qse_awk_rtx_t* rtx, const qse_cstr_t* fnm)
|
||||
{
|
||||
return fnc_math_1 (rtx, fnm, rtx->awk->prm.math.log10);
|
||||
}
|
||||
static int fnc_exp (qse_awk_rtx_t* rtx, const qse_cstr_t* fnm)
|
||||
{
|
||||
return fnc_math_1 (rtx, fnm, rtx->awk->prm.math.exp);
|
||||
|
@ -231,6 +231,19 @@ static qse_flt_t custom_awk_log (qse_awk_t* awk, qse_flt_t x)
|
||||
#endif
|
||||
}
|
||||
|
||||
static qse_flt_t custom_awk_log10 (qse_awk_t* awk, qse_flt_t x)
|
||||
{
|
||||
#if defined(HAVE_LOG10L) && (QSE_SIZEOF_LONG_DOUBLE > QSE_SIZEOF_DOUBLE)
|
||||
return log10l (x);
|
||||
#elif defined(HAVE_LOG10)
|
||||
return log10 (x);
|
||||
#elif defined(HAVE_LOG10F)
|
||||
return log10f (x);
|
||||
#else
|
||||
#error ### no log10 function available ###
|
||||
#endif
|
||||
}
|
||||
|
||||
static qse_flt_t custom_awk_exp (qse_awk_t* awk, qse_flt_t x)
|
||||
{
|
||||
#if defined(HAVE_EXPL) && (QSE_SIZEOF_LONG_DOUBLE > QSE_SIZEOF_DOUBLE)
|
||||
@ -294,6 +307,7 @@ qse_awk_t* qse_awk_openstdwithmmgr (qse_mmgr_t* mmgr, qse_size_t xtnsize)
|
||||
prm.math.atan = custom_awk_atan;
|
||||
prm.math.atan2 = custom_awk_atan2;
|
||||
prm.math.log = custom_awk_log;
|
||||
prm.math.log10 = custom_awk_log10;
|
||||
prm.math.exp = custom_awk_exp;
|
||||
prm.math.sqrt = custom_awk_sqrt;
|
||||
|
||||
|
@ -151,6 +151,7 @@ CXXFLAGS = @CXXFLAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
DLLTOOL = @DLLTOOL@
|
||||
DSYMUTIL = @DSYMUTIL@
|
||||
DUMPBIN = @DUMPBIN@
|
||||
ECHO = @ECHO@
|
||||
@ -178,6 +179,7 @@ LIPO = @LIPO@
|
||||
LN_S = @LN_S@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
MANIFEST_TOOL = @MANIFEST_TOOL@
|
||||
MKDIR_P = @MKDIR_P@
|
||||
NM = @NM@
|
||||
NMEDIT = @NMEDIT@
|
||||
@ -223,6 +225,7 @@ abs_builddir = @abs_builddir@
|
||||
abs_srcdir = @abs_srcdir@
|
||||
abs_top_builddir = @abs_top_builddir@
|
||||
abs_top_srcdir = @abs_top_srcdir@
|
||||
ac_ct_AR = @ac_ct_AR@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_CXX = @ac_ct_CXX@
|
||||
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
|
||||
@ -257,7 +260,6 @@ libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
localedir = @localedir@
|
||||
localstatedir = @localstatedir@
|
||||
lt_ECHO = @lt_ECHO@
|
||||
mandir = @mandir@
|
||||
mkdir_p = @mkdir_p@
|
||||
oldincludedir = @oldincludedir@
|
||||
|
@ -135,6 +135,7 @@ CXXFLAGS = @CXXFLAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
DLLTOOL = @DLLTOOL@
|
||||
DSYMUTIL = @DSYMUTIL@
|
||||
DUMPBIN = @DUMPBIN@
|
||||
ECHO = @ECHO@
|
||||
@ -162,6 +163,7 @@ LIPO = @LIPO@
|
||||
LN_S = @LN_S@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
MANIFEST_TOOL = @MANIFEST_TOOL@
|
||||
MKDIR_P = @MKDIR_P@
|
||||
NM = @NM@
|
||||
NMEDIT = @NMEDIT@
|
||||
@ -207,6 +209,7 @@ abs_builddir = @abs_builddir@
|
||||
abs_srcdir = @abs_srcdir@
|
||||
abs_top_builddir = @abs_top_builddir@
|
||||
abs_top_srcdir = @abs_top_srcdir@
|
||||
ac_ct_AR = @ac_ct_AR@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_CXX = @ac_ct_CXX@
|
||||
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
|
||||
@ -241,7 +244,6 @@ libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
localedir = @localedir@
|
||||
localstatedir = @localstatedir@
|
||||
lt_ECHO = @lt_ECHO@
|
||||
mandir = @mandir@
|
||||
mkdir_p = @mkdir_p@
|
||||
oldincludedir = @oldincludedir@
|
||||
|
@ -117,6 +117,7 @@ CXXFLAGS = @CXXFLAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
DLLTOOL = @DLLTOOL@
|
||||
DSYMUTIL = @DSYMUTIL@
|
||||
DUMPBIN = @DUMPBIN@
|
||||
ECHO = @ECHO@
|
||||
@ -144,6 +145,7 @@ LIPO = @LIPO@
|
||||
LN_S = @LN_S@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
MANIFEST_TOOL = @MANIFEST_TOOL@
|
||||
MKDIR_P = @MKDIR_P@
|
||||
NM = @NM@
|
||||
NMEDIT = @NMEDIT@
|
||||
@ -189,6 +191,7 @@ abs_builddir = @abs_builddir@
|
||||
abs_srcdir = @abs_srcdir@
|
||||
abs_top_builddir = @abs_top_builddir@
|
||||
abs_top_srcdir = @abs_top_srcdir@
|
||||
ac_ct_AR = @ac_ct_AR@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_CXX = @ac_ct_CXX@
|
||||
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
|
||||
@ -223,7 +226,6 @@ libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
localedir = @localedir@
|
||||
localstatedir = @localstatedir@
|
||||
lt_ECHO = @lt_ECHO@
|
||||
mandir = @mandir@
|
||||
mkdir_p = @mkdir_p@
|
||||
oldincludedir = @oldincludedir@
|
||||
|
@ -442,7 +442,7 @@ static int capture_connection (qse_htrd_t* htrd, qse_htb_pair_t* pair)
|
||||
|
||||
n = qse_mbsxncasecmp (
|
||||
QSE_HTB_VPTR(pair), QSE_HTB_VLEN(pair),
|
||||
"Keep-Alive", 10);
|
||||
"keep-alive", 10);
|
||||
if (n == 0)
|
||||
{
|
||||
htrd->re.attr.keepalive = 1;
|
||||
|
@ -501,13 +501,16 @@ typedef struct task_dir_t task_dir_t;
|
||||
struct task_dir_t
|
||||
{
|
||||
qse_ubi_t handle;
|
||||
qse_size_t count;
|
||||
int eod;
|
||||
|
||||
qse_mchar_t buf[4096];
|
||||
int header_added;
|
||||
int footer_pending;
|
||||
struct dirent* dent;
|
||||
|
||||
qse_mchar_t buf[512];
|
||||
qse_size_t bufpos;
|
||||
qse_size_t buflen;
|
||||
qse_size_t bufsent;
|
||||
|
||||
qse_size_t bufrem;
|
||||
qse_size_t chunklen;
|
||||
};
|
||||
|
||||
static int task_init_dir (
|
||||
@ -517,7 +520,6 @@ static int task_init_dir (
|
||||
|
||||
QSE_MEMSET (xtn, 0, QSE_SIZEOF(*xtn));
|
||||
xtn->handle = *(qse_ubi_t*)task->ctx;
|
||||
qse_printf (QSE_T(">>>> handle %p\n"), xtn->handle.ptr);
|
||||
task->ctx = xtn;
|
||||
return 0;
|
||||
}
|
||||
@ -525,7 +527,7 @@ qse_printf (QSE_T(">>>> handle %p\n"), xtn->handle.ptr);
|
||||
static void task_fini_dir (
|
||||
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task)
|
||||
{
|
||||
task_dir_t* ctx = (task_file_t*)task->ctx;
|
||||
task_dir_t* ctx = (task_dir_t*)task->ctx;
|
||||
closedir (ctx->handle.ptr);
|
||||
}
|
||||
|
||||
@ -534,81 +536,282 @@ static int task_main_dir (
|
||||
{
|
||||
task_dir_t* ctx = (task_dir_t*)task->ctx;
|
||||
qse_ssize_t n;
|
||||
char buf[100];
|
||||
int x;
|
||||
|
||||
if (ctx->bufsent < ctx->buflen) goto send_dirlist;
|
||||
if (ctx->bufpos < ctx->buflen) goto send_dirlist;
|
||||
|
||||
ctx->buflen = 0;
|
||||
ctx->bufsent = 0;
|
||||
/* the buffer size is fixed to QSE_COUNTOF(ctx->buf).
|
||||
* the number of digits need to hold the the size converted to
|
||||
* a hexadecimal notation is roughly (log16(QSE_COUNTOF(ctx->buf) + 1).
|
||||
* it should be safter to use ceil(log16(QSE_COUNTOF(ctx->buf)) + 1
|
||||
* for precision issues.
|
||||
*
|
||||
* 16**X = QSE_COUNTOF(ctx->buf).
|
||||
* X = log16(QSE_COUNTOF(ctx->buf).
|
||||
* X + 1 is a required number of digits.
|
||||
*
|
||||
* Since log16 is not provided, we should use a natural log function
|
||||
* whose base is the constant e (2.718).
|
||||
*
|
||||
* log16(n) = log(n) / log(16)
|
||||
*
|
||||
* The final fomula is here.
|
||||
*
|
||||
* X = ceil((log(QSE_COUNTOF(ctx->buf)) / log(16))) + 1;
|
||||
*
|
||||
* However, i won't use these floating-point opertions.
|
||||
* instead i'll reserve a hardcoded size. so when you change
|
||||
* the size of the buffer arrray, you should check this size.
|
||||
*/
|
||||
|
||||
/* reserve space to fill with the chunk length
|
||||
* 4 for the actual chunk length and +2 for \r\n */
|
||||
ctx->buflen = 4 + 2;
|
||||
|
||||
if (ctx->count == 0)
|
||||
/* free space remaing in the buffer for the chunk data */
|
||||
ctx->bufrem = QSE_COUNTOF(ctx->buf) - ctx->buflen - 2;
|
||||
|
||||
if (ctx->footer_pending)
|
||||
{
|
||||
ctx->buflen += snprintf (
|
||||
x = snprintf (
|
||||
&ctx->buf[ctx->buflen],
|
||||
QSE_COUNTOF(ctx->buf) - ctx->buflen,
|
||||
ctx->bufrem,
|
||||
"</ul></body></html>\r\n0\r\n");
|
||||
if (x == -1 || x >= ctx->bufrem)
|
||||
{
|
||||
/* return an error if the buffer is too small to hold the
|
||||
* trailing footer. you need to increate the buffer size */
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx->buflen += x;
|
||||
ctx->chunklen = ctx->buflen - 5;
|
||||
ctx->buf[ctx->buflen++] = '\r';
|
||||
ctx->buf[ctx->buflen++] = '\n';
|
||||
goto set_chunklen;
|
||||
}
|
||||
|
||||
if (!ctx->header_added)
|
||||
{
|
||||
/* compose the header since this is the first time. */
|
||||
|
||||
/* TODO: get the actual path ... and use it in the body or title. */
|
||||
x = snprintf (
|
||||
&ctx->buf[ctx->buflen],
|
||||
ctx->bufrem,
|
||||
"<html><head><title>Directory Listing</title></head><body>index of xxxx<ul>"
|
||||
);
|
||||
if (x == -1 || x >= ctx->bufrem)
|
||||
{
|
||||
/* return an error if the buffer is too small to hold the header.
|
||||
* you need to increate the buffer size */
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx->buflen += x;
|
||||
ctx->bufrem -= x;
|
||||
|
||||
ctx->header_added = 1;
|
||||
}
|
||||
|
||||
if (ctx->dent == QSE_NULL)
|
||||
ctx->dent = readdir (ctx->handle.ptr);
|
||||
|
||||
do
|
||||
{
|
||||
struct dirent* ent;
|
||||
|
||||
ent = readdir (ctx->handle.ptr);
|
||||
if (ent == QSE_NULL)
|
||||
if (ctx->dent == QSE_NULL)
|
||||
{
|
||||
// TODO: check if errno has changed from before readdir().
|
||||
// and return -1 if so.
|
||||
ctx->eod = 1;
|
||||
ctx->buflen += snprintf (
|
||||
x = snprintf (
|
||||
&ctx->buf[ctx->buflen],
|
||||
QSE_COUNTOF(ctx->buf) - ctx->buflen,
|
||||
"</ul></body></html>");
|
||||
break;
|
||||
ctx->bufrem,
|
||||
"</ul></body></html>\r\n0\r\n");
|
||||
if (x == -1 || x >= ctx->bufrem)
|
||||
{
|
||||
ctx->footer_pending = 1;
|
||||
ctx->chunklen = ctx->buflen;
|
||||
ctx->buf[ctx->buflen++] = '\r';
|
||||
ctx->buf[ctx->buflen++] = '\n';
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx->buflen += x;
|
||||
ctx->chunklen = ctx->buflen - 5;
|
||||
ctx->buf[ctx->buflen++] = '\r';
|
||||
ctx->buf[ctx->buflen++] = '\n';
|
||||
}
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: check if snprintf has truncated....
|
||||
ctx->buflen += snprintf (
|
||||
x = snprintf (
|
||||
&ctx->buf[ctx->buflen],
|
||||
QSE_COUNTOF(ctx->buf) - ctx->buflen,
|
||||
ctx->bufrem,
|
||||
"<li><a href='%s%s'>%s%s</a></li>",
|
||||
ent->d_name,
|
||||
(ent->d_type == DT_DIR? "/": ""),
|
||||
ent->d_name,
|
||||
(ent->d_type == DT_DIR? "/": "")
|
||||
ctx->dent->d_name,
|
||||
(ctx->dent->d_type == DT_DIR? "/": ""),
|
||||
ctx->dent->d_name,
|
||||
(ctx->dent->d_type == DT_DIR? "/": "")
|
||||
);
|
||||
if (x == -1 || x >= ctx->bufrem)
|
||||
{
|
||||
/* buffer not large enough to hold this entry */
|
||||
ctx->chunklen = ctx->buflen;
|
||||
ctx->buf[ctx->buflen++] = '\r';
|
||||
ctx->buf[ctx->buflen++] = '\n';
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx->buflen += x;
|
||||
ctx->bufrem -= x;
|
||||
}
|
||||
}
|
||||
|
||||
ctx->count++;
|
||||
ctx->dent = readdir (ctx->handle.ptr);
|
||||
}
|
||||
while (1);
|
||||
|
||||
set_chunklen:
|
||||
x = snprintf (
|
||||
ctx->buf, (4 + 2) - 1,
|
||||
"%*lX", (int)(4 + 2 - 2),
|
||||
(unsigned long)(ctx->chunklen - (4 + 2)));
|
||||
ctx->buf[x] = '\r';
|
||||
ctx->buf[x+1] = '\n';
|
||||
for (x = 0; ctx->buf[x] == ' '; x++) ctx->buflen--;
|
||||
ctx->bufpos = x;
|
||||
|
||||
send_dirlist:
|
||||
n = send (client->handle.i, &ctx->buf[ctx->bufpos], ctx->buflen, 0);
|
||||
if (n <= -1) return -1;
|
||||
|
||||
ctx->bufpos += n;
|
||||
ctx->buflen -= n;
|
||||
return (ctx->bufpos < ctx->buflen || ctx->footer_pending || ctx->dent)? 1: 0;
|
||||
}
|
||||
|
||||
static int task_main_dir_nochunk (
|
||||
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task)
|
||||
{
|
||||
task_dir_t* ctx = (task_dir_t*)task->ctx;
|
||||
qse_ssize_t n;
|
||||
int x;
|
||||
|
||||
if (ctx->bufpos < ctx->buflen) goto send_dirlist;
|
||||
|
||||
ctx->bufpos = 0;
|
||||
ctx->buflen = 0;
|
||||
ctx->bufrem = QSE_COUNTOF(ctx->buf);
|
||||
|
||||
if (ctx->footer_pending)
|
||||
{
|
||||
x = snprintf (
|
||||
&ctx->buf[ctx->buflen],
|
||||
ctx->bufrem,
|
||||
"</ul></body></html>");
|
||||
if (x == -1 || x >= ctx->bufrem)
|
||||
{
|
||||
/* return an error if the buffer is too small to hold the
|
||||
* trailing footer. you need to increate the buffer size */
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx->buflen += x;
|
||||
goto send_dirlist;
|
||||
}
|
||||
|
||||
if (!ctx->header_added)
|
||||
{
|
||||
/* compose the header since this is the first time. */
|
||||
x = snprintf (
|
||||
&ctx->buf[ctx->buflen],
|
||||
ctx->bufrem,
|
||||
"<html><head><title>Directory Listing</title></head><body>index of xxxx<ul>"
|
||||
);
|
||||
if (x == -1 || x >= ctx->bufrem)
|
||||
{
|
||||
/* return an error if the buffer is too small to hold the header.
|
||||
* you need to increate the buffer size */
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx->buflen += x;
|
||||
ctx->bufrem -= x;
|
||||
ctx->header_added = 1;
|
||||
}
|
||||
|
||||
if (ctx->dent == QSE_NULL)
|
||||
ctx->dent = readdir (ctx->handle.ptr);
|
||||
|
||||
do
|
||||
{
|
||||
if (ctx->dent == QSE_NULL)
|
||||
{
|
||||
// TODO: check if errno has changed from before readdir().
|
||||
// and return -1 if so.
|
||||
x = snprintf (
|
||||
&ctx->buf[ctx->buflen],
|
||||
ctx->bufrem,
|
||||
"</ul></body></html>");
|
||||
if (x == -1 || x >= ctx->bufrem)
|
||||
{
|
||||
ctx->footer_pending = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx->buflen += x;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
x = snprintf (
|
||||
&ctx->buf[ctx->buflen],
|
||||
ctx->bufrem,
|
||||
"<li><a href='%s%s'>%s%s</a></li>",
|
||||
ctx->dent->d_name,
|
||||
(ctx->dent->d_type == DT_DIR? "/": ""),
|
||||
ctx->dent->d_name,
|
||||
(ctx->dent->d_type == DT_DIR? "/": "")
|
||||
);
|
||||
if (x == -1 || x >= ctx->bufrem)
|
||||
{
|
||||
/* buffer not large enough to hold this entry */
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx->buflen += x;
|
||||
ctx->bufrem -= x;
|
||||
}
|
||||
}
|
||||
|
||||
ctx->dent = readdir (ctx->handle.ptr);
|
||||
}
|
||||
while (1);
|
||||
|
||||
send_dirlist:
|
||||
|
||||
snprintf (buf, QSE_COUNTOF(buf), "%lX\r\n", (unsigned long)(ctx->buflen - ctx->bufsent));
|
||||
send (client->handle.i, buf, strlen(buf), 0);
|
||||
|
||||
n = send (client->handle.i, ctx->buf, ctx->buflen, 0);
|
||||
n = send (client->handle.i, &ctx->buf[ctx->bufpos], ctx->buflen, 0);
|
||||
if (n <= -1) return -1;
|
||||
|
||||
send (client->handle.i, "0\r\n", 3, 0);
|
||||
|
||||
ctx->bufsent += n;
|
||||
return (ctx->bufsent < ctx->buflen || !ctx->eod)? 1: 0;
|
||||
ctx->bufpos += n;
|
||||
ctx->buflen -= n;
|
||||
return (ctx->bufpos < ctx->buflen || ctx->footer_pending || ctx->dent)? 1: 0;
|
||||
}
|
||||
|
||||
qse_httpd_task_t* qse_httpd_entaskdir (
|
||||
qse_httpd_t* httpd,
|
||||
qse_httpd_client_t* client,
|
||||
const qse_httpd_task_t* pred,
|
||||
qse_ubi_t handle)
|
||||
qse_ubi_t handle, int chunked)
|
||||
{
|
||||
qse_httpd_task_t task;
|
||||
|
||||
QSE_MEMSET (&task, 0, QSE_SIZEOF(task));
|
||||
task.init = task_init_dir;
|
||||
task.main = task_main_dir;
|
||||
task.main = chunked? task_main_dir: task_main_dir_nochunk;
|
||||
task.fini = task_fini_dir;
|
||||
task.ctx = &handle;
|
||||
|
||||
@ -674,9 +877,9 @@ static qse_httpd_task_t* entask_path_error (
|
||||
|
||||
return qse_httpd_entaskformat (
|
||||
httpd, client, task,
|
||||
QSE_MT("HTTP/%d.%d %d %s\r\nConnection: %s\r\nContent-Type: text/html\r\nContent-Length: %d\r\n\r\n%s\r\n\r\n"),
|
||||
QSE_MT("HTTP/%d.%d %d %s\r\nConnection: %s\r\nContent-Type: text/html;charset=utf-8\r\nContent-Length: %d\r\n\r\n%s\r\n\r\n"),
|
||||
data->version.major, data->version.minor, code, smsg,
|
||||
(data->keepalive? QSE_MT("Keep-Alive"): QSE_MT("Close")),
|
||||
(data->keepalive? QSE_MT("keep-alive"): QSE_MT("close")),
|
||||
(int)qse_mbslen(lmsg) + 4, lmsg
|
||||
);
|
||||
}
|
||||
@ -706,30 +909,60 @@ qse_printf (QSE_T("opening file %hs\n"), data->name);
|
||||
|
||||
if (S_ISDIR(st.st_mode))
|
||||
{
|
||||
qse_ubi_t dir;
|
||||
|
||||
/*#if defined(HAVE_FDOPENDIR)
|
||||
dir.ptr = fdopendir (handle.i);
|
||||
#else */
|
||||
dir.ptr = opendir (data->name);
|
||||
/*#endif */
|
||||
if (dir.ptr)
|
||||
if (qse_mbsend (data->name, QSE_MT("/")))
|
||||
{
|
||||
qse_printf (QSE_T(">>>> entask dir handle %p\n"), dir.ptr);
|
||||
x = qse_httpd_entaskformat (
|
||||
httpd, client, x,
|
||||
QSE_MT("HTTP/%d.%d 200 OK\r\nConnection: %s\r\nContent-Type: text/html\r\nContent-Location: %s\r\nTransfer-Encoding: chunked\r\n\r\n"),
|
||||
data->version.major, data->version.minor,
|
||||
(data->keepalive? QSE_MT("Keep-Alive"): QSE_MT("Close")),
|
||||
data->name
|
||||
);
|
||||
qse_ubi_t dir;
|
||||
|
||||
x = qse_httpd_entaskdir (httpd, client, x, dir);
|
||||
if (x == QSE_NULL) closedir (dir.ptr);
|
||||
/*#if defined(HAVE_FDOPENDIR)
|
||||
dir.ptr = fdopendir (handle.i);
|
||||
#else */
|
||||
dir.ptr = opendir (data->name);
|
||||
/*#endif */
|
||||
if (dir.ptr)
|
||||
{
|
||||
if (data->version.major < 1 ||
|
||||
(data->version.major == 1 && data->version.minor == 0))
|
||||
{
|
||||
data->keepalive = 0;
|
||||
}
|
||||
|
||||
if (data->keepalive)
|
||||
{
|
||||
x = qse_httpd_entaskformat (
|
||||
httpd, client, x,
|
||||
QSE_MT("HTTP/%d.%d 200 OK\r\nConnection: keep-alive\r\nContent-Type: text/html;charset=utf-8\r\nTransfer-Encoding: chunked\r\n\r\n"),
|
||||
data->version.major, data->version.minor
|
||||
);
|
||||
if (x) x = qse_httpd_entaskdir (httpd, client, x, dir, data->keepalive);
|
||||
}
|
||||
else
|
||||
{
|
||||
x = qse_httpd_entaskformat (
|
||||
httpd, client, x,
|
||||
QSE_MT("HTTP/%d.%d 200 OK\r\nConnection: close\r\nContent-Type: text/html;charset=utf-8\r\n\r\n"),
|
||||
data->version.major, data->version.minor
|
||||
);
|
||||
|
||||
if (x) x = qse_httpd_entaskdir (httpd, client, x, dir, data->keepalive);
|
||||
if (x) x = qse_httpd_entaskdisconnect (httpd, client, x);
|
||||
}
|
||||
|
||||
if (!x) closedir (dir.ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
x = entask_path_error (httpd, client, x, 403);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
x = entask_path_error (httpd, client, x, 403);
|
||||
x = qse_httpd_entaskformat (
|
||||
httpd, client, x,
|
||||
QSE_MT("HTTP/%d.%d 301 Moved Permanently\r\nContent-Length: 0\r\nConnection: %s\r\nLocation: %s/\r\n\r\n"),
|
||||
data->version.major, data->version.minor,
|
||||
(data->keepalive? QSE_MT("keep-alive"): QSE_MT("close")),
|
||||
data->name
|
||||
);
|
||||
}
|
||||
goto no_file_send;
|
||||
}
|
||||
@ -766,15 +999,14 @@ qse_printf (QSE_T(">>>> entask dir handle %p\n"), dir.ptr);
|
||||
#if (QSE_SIZEOF_LONG_LONG > 0)
|
||||
x = qse_httpd_entaskformat (
|
||||
httpd, client, x,
|
||||
QSE_MT("HTTP/%d.%d 206 Partial Content\r\nConnection: %s\r\n%s%s%sContent-Length: %llu\r\nContent-Location: %s\r\nContent-Range: bytes %llu-%llu/%llu\r\n\r\n"),
|
||||
QSE_MT("HTTP/%d.%d 206 Partial Content\r\nConnection: %s\r\n%s%s%sContent-Length: %llu\r\nContent-Range: bytes %llu-%llu/%llu\r\n\r\n"),
|
||||
data->version.major,
|
||||
data->version.minor,
|
||||
(data->keepalive? QSE_MT("Keep-Alive"): QSE_MT("Close")),
|
||||
(data->keepalive? QSE_MT("keep-alive"): QSE_MT("close")),
|
||||
(mime_type? QSE_MT("Content-Type: "): QSE_MT("")),
|
||||
(mime_type? mime_type: QSE_MT("")),
|
||||
(mime_type? QSE_MT("\r\n"): QSE_MT("")),
|
||||
(unsigned long long)(data->range.to - data->range.from + 1),
|
||||
data->name,
|
||||
(unsigned long long)data->range.from,
|
||||
(unsigned long long)data->range.to,
|
||||
(unsigned long long)st.st_size
|
||||
@ -782,15 +1014,14 @@ qse_printf (QSE_T(">>>> entask dir handle %p\n"), dir.ptr);
|
||||
#else
|
||||
x = qse_httpd_entaskformat (
|
||||
httpd, client, x,
|
||||
QSE_MT("HTTP/%d.%d 206 Partial Content\r\nConnection: %s\r\n%s%s%sContent-Length: %lu\r\nContent-Location: %s\r\nContent-Range: bytes %lu-%lu/%lu\r\n\r\n"),
|
||||
QSE_MT("HTTP/%d.%d 206 Partial Content\r\nConnection: %s\r\n%s%s%sContent-Length: %lu\r\nContent-Range: bytes %lu-%lu/%lu\r\n\r\n"),
|
||||
data->version.major,
|
||||
data->version.minor,
|
||||
(data->keepalive? QSE_MT("Keep-Alive"): QSE_MT("Close")),
|
||||
(data->keepalive? QSE_MT("keep-alive"): QSE_MT("close")),
|
||||
(mime_type? QSE_MT("Content-Type: "): QSE_MT("")),
|
||||
(mime_type? mime_type: QSE_MT("")),
|
||||
(mime_type? QSE_MT("\r\n"): QSE_MT("")),
|
||||
(unsigned long)(data->range.to - data->range.from + 1),
|
||||
data->name,
|
||||
(unsigned long)data->range.from,
|
||||
(unsigned long)data->range.to,
|
||||
(unsigned long)st.st_size
|
||||
@ -818,33 +1049,31 @@ qse_printf (QSE_T(">>>> entask dir handle %p\n"), dir.ptr);
|
||||
/*TODO: how to handle an error... */
|
||||
}
|
||||
|
||||
/* wget 1.8.2 set 'Connection: Keep-Alive' in the http 1.0 header.
|
||||
* if the reply doesn't contain 'Connection: Keep-Alive', it didn't
|
||||
/* wget 1.8.2 set 'Connection: keep-alive' in the http 1.0 header.
|
||||
* if the reply doesn't contain 'Connection: keep-alive', it didn't
|
||||
* close connection.*/
|
||||
#if (QSE_SIZEOF_LONG_LONG > 0)
|
||||
x = qse_httpd_entaskformat (
|
||||
httpd, client, x,
|
||||
QSE_MT("HTTP/%d.%d 200 OK\r\nConnection: %s\r\n%s%s%sContent-Length: %llu\r\nContent-Location: %s\r\n\r\n"),
|
||||
QSE_MT("HTTP/%d.%d 200 OK\r\nConnection: %s\r\n%s%s%sContent-Length: %llu\r\n\r\n"),
|
||||
data->version.major, data->version.minor,
|
||||
(data->keepalive? QSE_MT("Keep-Alive"): QSE_MT("Close")),
|
||||
(data->keepalive? QSE_MT("keep-alive"): QSE_MT("close")),
|
||||
(mime_type? QSE_MT("Content-Type: "): QSE_MT("")),
|
||||
(mime_type? mime_type: QSE_MT("")),
|
||||
(mime_type? QSE_MT("\r\n"): QSE_MT("")),
|
||||
(unsigned long long)st.st_size,
|
||||
data->name
|
||||
(unsigned long long)st.st_size
|
||||
);
|
||||
#else
|
||||
x = qse_httpd_entaskformat (
|
||||
httpd, client, x,
|
||||
QSE_MT("HTTP/%d.%d 200 OK\r\nConnection: %s\r\n%s%s%sContent-Length: %lu\r\nContent-Location: %s\r\n\r\n"),
|
||||
QSE_MT("HTTP/%d.%d 200 OK\r\nConnection: %s\r\n%s%s%sContent-Length: %lu\r\n\r\n"),
|
||||
data->version.major,
|
||||
data->version.minor,
|
||||
(data->keepalive? QSE_MT("Keep-Alive"): QSE_MT("Close")),
|
||||
(data->keepalive? QSE_MT("keep-alive"): QSE_MT("close")),
|
||||
(mime_type? QSE_MT("Content-Type: "): QSE_MT("")),
|
||||
(mime_type? mime_type: QSE_MT("")),
|
||||
(mime_type? QSE_MT("\r\n"): QSE_MT("")),
|
||||
(unsigned long)st.st_size,
|
||||
data->name
|
||||
(unsigned long)st.st_size
|
||||
);
|
||||
#endif
|
||||
if (x)
|
||||
|
@ -135,6 +135,7 @@ CXXFLAGS = @CXXFLAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
DLLTOOL = @DLLTOOL@
|
||||
DSYMUTIL = @DSYMUTIL@
|
||||
DUMPBIN = @DUMPBIN@
|
||||
ECHO = @ECHO@
|
||||
@ -162,6 +163,7 @@ LIPO = @LIPO@
|
||||
LN_S = @LN_S@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
MANIFEST_TOOL = @MANIFEST_TOOL@
|
||||
MKDIR_P = @MKDIR_P@
|
||||
NM = @NM@
|
||||
NMEDIT = @NMEDIT@
|
||||
@ -207,6 +209,7 @@ abs_builddir = @abs_builddir@
|
||||
abs_srcdir = @abs_srcdir@
|
||||
abs_top_builddir = @abs_top_builddir@
|
||||
abs_top_srcdir = @abs_top_srcdir@
|
||||
ac_ct_AR = @ac_ct_AR@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_CXX = @ac_ct_CXX@
|
||||
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
|
||||
@ -241,7 +244,6 @@ libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
localedir = @localedir@
|
||||
localstatedir = @localstatedir@
|
||||
lt_ECHO = @lt_ECHO@
|
||||
mandir = @mandir@
|
||||
mkdir_p = @mkdir_p@
|
||||
oldincludedir = @oldincludedir@
|
||||
|
@ -117,6 +117,7 @@ CXXFLAGS = @CXXFLAGS@
|
||||
CYGPATH_W = @CYGPATH_W@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
DLLTOOL = @DLLTOOL@
|
||||
DSYMUTIL = @DSYMUTIL@
|
||||
DUMPBIN = @DUMPBIN@
|
||||
ECHO = @ECHO@
|
||||
@ -144,6 +145,7 @@ LIPO = @LIPO@
|
||||
LN_S = @LN_S@
|
||||
LTLIBOBJS = @LTLIBOBJS@
|
||||
MAKEINFO = @MAKEINFO@
|
||||
MANIFEST_TOOL = @MANIFEST_TOOL@
|
||||
MKDIR_P = @MKDIR_P@
|
||||
NM = @NM@
|
||||
NMEDIT = @NMEDIT@
|
||||
@ -189,6 +191,7 @@ abs_builddir = @abs_builddir@
|
||||
abs_srcdir = @abs_srcdir@
|
||||
abs_top_builddir = @abs_top_builddir@
|
||||
abs_top_srcdir = @abs_top_srcdir@
|
||||
ac_ct_AR = @ac_ct_AR@
|
||||
ac_ct_CC = @ac_ct_CC@
|
||||
ac_ct_CXX = @ac_ct_CXX@
|
||||
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
|
||||
@ -223,7 +226,6 @@ libdir = @libdir@
|
||||
libexecdir = @libexecdir@
|
||||
localedir = @localedir@
|
||||
localstatedir = @localstatedir@
|
||||
lt_ECHO = @lt_ECHO@
|
||||
mandir = @mandir@
|
||||
mkdir_p = @mkdir_p@
|
||||
oldincludedir = @oldincludedir@
|
||||
|
Reference in New Issue
Block a user