enhanced httpd directory listing

This commit is contained in:
2012-01-26 14:19:48 +00:00
parent 246dc4f5b7
commit e7b5bfaf4b
59 changed files with 7083 additions and 4247 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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