added directory handler to qse_httpd_scb_t
This commit is contained in:
parent
d9b42ca785
commit
7940a758d0
@ -65,6 +65,7 @@ enum qse_httpd_option_t
|
||||
typedef struct qse_httpd_stat_t qse_httpd_stat_t;
|
||||
struct qse_httpd_stat_t
|
||||
{
|
||||
int isdir;
|
||||
qse_long_t dev;
|
||||
qse_long_t ino;
|
||||
qse_foff_t size;
|
||||
@ -123,6 +124,14 @@ typedef int (*qse_httpd_muxcb_t) (
|
||||
void* cbarg
|
||||
);
|
||||
|
||||
typedef struct qse_httpd_dirent_t qse_httpd_dirent_t;
|
||||
|
||||
struct qse_httpd_dirent_t
|
||||
{
|
||||
qse_mchar_t* name;
|
||||
qse_httpd_stat_t stat;
|
||||
};
|
||||
|
||||
typedef struct qse_httpd_scb_t qse_httpd_scb_t;
|
||||
struct qse_httpd_scb_t
|
||||
{
|
||||
@ -191,6 +200,17 @@ struct qse_httpd_scb_t
|
||||
const qse_mchar_t* buf, qse_size_t len);
|
||||
} file;
|
||||
|
||||
struct
|
||||
{
|
||||
int (*open) (
|
||||
qse_httpd_t* httpd, const qse_mchar_t* path,
|
||||
qse_ubi_t* handle);
|
||||
void (*close) (qse_httpd_t* httpd, qse_ubi_t handle);
|
||||
int (*read) (
|
||||
qse_httpd_t* httpd, qse_ubi_t handle,
|
||||
qse_httpd_dirent_t* ent);
|
||||
} dir;
|
||||
|
||||
struct
|
||||
{
|
||||
void (*close) (
|
||||
@ -225,6 +245,7 @@ struct qse_httpd_scb_t
|
||||
qse_httpd_t* httpd,
|
||||
qse_httpd_client_t* client); /* optional */
|
||||
} client;
|
||||
|
||||
};
|
||||
|
||||
typedef struct qse_httpd_rcb_t qse_httpd_rcb_t;
|
||||
@ -363,6 +384,7 @@ struct qse_httpd_rsrc_t
|
||||
struct
|
||||
{
|
||||
const qse_mchar_t* path;
|
||||
const qse_mchar_t* css;
|
||||
} dir;
|
||||
|
||||
struct
|
||||
@ -459,6 +481,8 @@ enum qse_httpd_server_xtn_cfg_idx_t
|
||||
QSE_HTTPD_SERVER_XTN_CFG_USERNAME,
|
||||
QSE_HTTPD_SERVER_XTN_CFG_PASSWORD,
|
||||
QSE_HTTPD_SERVER_XTN_CFG_BASICAUTH,
|
||||
QSE_HTTPD_SERVER_XTN_CFG_DIRCSS, /* can't be too long due to internal buffer size */
|
||||
QSE_HTTPD_SERVER_XTN_CFG_ERRORCSS,
|
||||
QSE_HTTPD_SERVER_XTN_CFG_MAX
|
||||
};
|
||||
|
||||
@ -680,6 +704,7 @@ qse_httpd_task_t* qse_httpd_entaskdir (
|
||||
qse_httpd_client_t* client,
|
||||
qse_httpd_task_t* pred,
|
||||
const qse_mchar_t* name,
|
||||
const qse_mchar_t* css,
|
||||
qse_htre_t* req
|
||||
);
|
||||
|
||||
|
@ -24,22 +24,13 @@
|
||||
#include <qse/cmn/fmt.h>
|
||||
#include <qse/cmn/path.h>
|
||||
|
||||
#if defined(_WIN32)
|
||||
/* TODO: */
|
||||
#elif defined(__OS2__)
|
||||
/* TODO: */
|
||||
#elif defined(__DOS__)
|
||||
/* TODO: */
|
||||
#else
|
||||
# include "../cmn/syscall.h"
|
||||
#endif
|
||||
|
||||
#include <qse/cmn/stdio.h> /* TODO: remove this */
|
||||
|
||||
typedef struct task_dir_t task_dir_t;
|
||||
struct task_dir_t
|
||||
{
|
||||
qse_mcstr_t path;
|
||||
qse_mcstr_t css;
|
||||
qse_mcstr_t qpath;
|
||||
qse_http_version_t version;
|
||||
int keepalive;
|
||||
@ -53,19 +44,24 @@ struct task_dseg_t
|
||||
int chunked;
|
||||
|
||||
qse_mcstr_t path;
|
||||
qse_mcstr_t css;
|
||||
qse_mcstr_t qpath;
|
||||
qse_dir_t* handle;
|
||||
qse_dirent_t* dent;
|
||||
qse_ubi_t handle;
|
||||
qse_httpd_dirent_t dent;
|
||||
|
||||
#define HEADER_ADDED (1 << 0)
|
||||
#define FOOTER_ADDED (1 << 1)
|
||||
#define FOOTER_PENDING (1 << 2)
|
||||
#define DIRENT_PENDING (1 << 3)
|
||||
#define DIRENT_NOMORE (1 << 4)
|
||||
int state;
|
||||
|
||||
qse_size_t tcount; /* total directory entries */
|
||||
qse_size_t dcount; /* the number of items in the buffer */
|
||||
|
||||
qse_mchar_t tmbuf[128];
|
||||
qse_mchar_t fszbuf[128];
|
||||
|
||||
qse_mchar_t buf[4096];
|
||||
qse_size_t bufpos;
|
||||
qse_size_t buflen;
|
||||
@ -83,7 +79,9 @@ static int task_init_dseg (
|
||||
|
||||
xtn->path.ptr = (qse_mchar_t*)(xtn + 1);
|
||||
qse_mbscpy ((qse_mchar_t*)xtn->path.ptr, arg->path.ptr);
|
||||
xtn->qpath.ptr = xtn->path.ptr + xtn->path.len + 1;
|
||||
xtn->css.ptr = xtn->path.ptr + xtn->path.len + 1;
|
||||
qse_mbscpy ((qse_mchar_t*)xtn->css.ptr, arg->css.ptr);
|
||||
xtn->qpath.ptr = xtn->css.ptr + xtn->css.len + 1;
|
||||
qse_mbscpy ((qse_mchar_t*)xtn->qpath.ptr, arg->qpath.ptr);
|
||||
|
||||
task->ctx = xtn;
|
||||
@ -95,7 +93,7 @@ static void task_fini_dseg (
|
||||
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task)
|
||||
{
|
||||
task_dseg_t* ctx = (task_dseg_t*)task->ctx;
|
||||
QSE_CLOSEDIR (ctx->handle);
|
||||
httpd->scb->dir.close (httpd, ctx->handle);
|
||||
}
|
||||
|
||||
#define SIZE_CHLEN 4 /* the space size to hold the hexadecimal chunk length */
|
||||
@ -145,13 +143,13 @@ static int add_footer (task_dseg_t* ctx)
|
||||
{
|
||||
x = snprintf (
|
||||
&ctx->buf[ctx->buflen], ctx->bufrem,
|
||||
QSE_MT("</ul>Total %lu entries</body></html>\r\n0\r\n"), (unsigned long)ctx->tcount);
|
||||
QSE_MT("</table></body></html>\r\n0\r\n"));
|
||||
}
|
||||
else
|
||||
{
|
||||
x = snprintf (
|
||||
&ctx->buf[ctx->buflen], ctx->bufrem,
|
||||
QSE_MT("</ul>Total %lu entries</body></html>"), (unsigned long)ctx->tcount);
|
||||
QSE_MT("</table></body></html>"));
|
||||
}
|
||||
|
||||
if (x == -1 || x >= ctx->bufrem)
|
||||
@ -254,8 +252,12 @@ static int task_main_dseg (
|
||||
/* TODO: html escaping of ctx->qpath.ptr */
|
||||
x = snprintf (
|
||||
&ctx->buf[ctx->buflen], ctx->bufrem,
|
||||
QSE_MT("<html><head></head><body><b>%s</b><ul>%s"),
|
||||
ctx->qpath.ptr, (is_root? QSE_MT(""): QSE_MT("<li><a href='../'>..</a></li>"))
|
||||
QSE_MT("<html><head>%s%s%s</head><body><b>%s</b><table>%s"),
|
||||
(ctx->css.len > 0? QSE_MT("<style type='text/css'>"): QSE_MT("")),
|
||||
(ctx->css.len > 0? ctx->css.ptr: QSE_MT("")),
|
||||
(ctx->css.len > 0? QSE_MT("</style>"): QSE_MT("")),
|
||||
ctx->qpath.ptr,
|
||||
(is_root? QSE_MT(""): QSE_MT("<tr><td><a href='../'>..</a></td><td></td><td></td></tr>"))
|
||||
);
|
||||
if (x == -1 || x >= ctx->bufrem)
|
||||
{
|
||||
@ -273,18 +275,22 @@ static int task_main_dseg (
|
||||
ctx->dcount++;
|
||||
}
|
||||
|
||||
/*if (!ctx->dent) ctx->dent = QSE_READDIR (ctx->handle); */
|
||||
if (ctx->state & DIRENT_PENDING)
|
||||
{
|
||||
ctx->state &= ~DIRENT_PENDING;
|
||||
}
|
||||
else
|
||||
ctx->dent = QSE_READDIR (ctx->handle);
|
||||
{
|
||||
if (httpd->scb->dir.read (httpd, ctx->handle, &ctx->dent) <= 0)
|
||||
ctx->state |= DIRENT_NOMORE;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
if (!ctx->dent)
|
||||
if (ctx->state & DIRENT_NOMORE)
|
||||
{
|
||||
/* TODO: check if errno has changed from before QSE_READDIR().
|
||||
and return -1 if so. */
|
||||
/* no more directory entry */
|
||||
|
||||
if (add_footer (ctx) <= -1)
|
||||
{
|
||||
/* failed to add the footer part */
|
||||
@ -298,31 +304,55 @@ static int task_main_dseg (
|
||||
else if (ctx->chunked) fill_chunk_length (ctx);
|
||||
break;
|
||||
}
|
||||
else if (qse_mbscmp (ctx->dent->d_name, QSE_MT(".")) != 0 &&
|
||||
qse_mbscmp (ctx->dent->d_name, QSE_MT("..")) != 0)
|
||||
|
||||
|
||||
if (qse_mbscmp (ctx->dent.name, QSE_MT(".")) != 0 &&
|
||||
qse_mbscmp (ctx->dent.name, QSE_MT("..")) != 0)
|
||||
{
|
||||
qse_mchar_t* encname;
|
||||
qse_btime_t bt;
|
||||
|
||||
/* TODO: better buffer management in case there are
|
||||
* a lot of file names to escape. */
|
||||
encname = qse_perenchttpstrdup (ctx->dent->d_name, httpd->mmgr);
|
||||
encname = qse_perenchttpstrdup (ctx->dent.name, httpd->mmgr);
|
||||
if (encname == QSE_NULL)
|
||||
{
|
||||
httpd->errnum = QSE_HTTPD_ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
qse_printf (QSE_T("ADDING [%hs]\n"), ctx->dent.name);
|
||||
|
||||
qse_localtime (ctx->dent.stat.mtime, &bt);
|
||||
snprintf (ctx->tmbuf, QSE_COUNTOF(ctx->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 (ctx->dent.stat.isdir)
|
||||
{
|
||||
ctx->fszbuf[0] = QSE_MT('\0');
|
||||
}
|
||||
else
|
||||
{
|
||||
qse_fmtuintmaxtombs (
|
||||
ctx->fszbuf, QSE_COUNTOF(ctx->fszbuf),
|
||||
ctx->dent.stat.size, 10, -1, QSE_MT('\0'), QSE_NULL
|
||||
);
|
||||
}
|
||||
|
||||
x = snprintf (
|
||||
&ctx->buf[ctx->buflen],
|
||||
ctx->bufrem,
|
||||
QSE_MT("<li><a href='%s%s'>%s%s</a></li>"),
|
||||
QSE_MT("<tr><td><a href='%s%s'>%s%s</a></td><td>%s</td><td align='right'>%s</td></tr>"),
|
||||
encname,
|
||||
(ctx->dent->d_type == DT_DIR? QSE_MT("/"): QSE_MT("")),
|
||||
ctx->dent->d_name, /* TODO: html escaping */
|
||||
(ctx->dent->d_type == DT_DIR? QSE_MT("/"): QSE_MT(""))
|
||||
(ctx->dent.stat.isdir? QSE_MT("/"): QSE_MT("")),
|
||||
ctx->dent.name, /* TODO: html escaping */
|
||||
(ctx->dent.stat.isdir? QSE_MT("/"): QSE_MT("")),
|
||||
ctx->tmbuf, ctx->fszbuf
|
||||
);
|
||||
|
||||
if (encname != ctx->dent->d_name) QSE_MMGR_FREE (httpd->mmgr, encname);
|
||||
if (encname != ctx->dent.name) QSE_MMGR_FREE (httpd->mmgr, encname);
|
||||
|
||||
if (x == -1 || x >= ctx->bufrem)
|
||||
{
|
||||
@ -355,7 +385,8 @@ static int task_main_dseg (
|
||||
}
|
||||
}
|
||||
|
||||
ctx->dent = QSE_READDIR (ctx->handle);
|
||||
if (httpd->scb->dir.read (httpd, ctx->handle, &ctx->dent) <= 0)
|
||||
ctx->state |= DIRENT_NOMORE;
|
||||
}
|
||||
while (1);
|
||||
|
||||
@ -369,12 +400,12 @@ send_dirlist:
|
||||
/* NOTE if (n == 0), it will enter an infinite loop */
|
||||
|
||||
ctx->bufpos += n;
|
||||
return (ctx->bufpos < ctx->buflen || (ctx->state & FOOTER_PENDING) || ctx->dent)? 1: 0;
|
||||
return (ctx->bufpos < ctx->buflen || (ctx->state & FOOTER_PENDING) || !(ctx->state & DIRENT_NOMORE))? 1: 0;
|
||||
}
|
||||
|
||||
static qse_httpd_task_t* entask_directory_segment (
|
||||
qse_httpd_t* httpd, qse_httpd_client_t* client,
|
||||
qse_httpd_task_t* pred, qse_dir_t* handle, task_dir_t* dir)
|
||||
qse_httpd_task_t* pred, qse_ubi_t handle, task_dir_t* dir)
|
||||
{
|
||||
qse_httpd_task_t task;
|
||||
task_dseg_t data;
|
||||
@ -385,6 +416,7 @@ static qse_httpd_task_t* entask_directory_segment (
|
||||
data.keepalive = dir->keepalive;
|
||||
data.chunked = dir->keepalive;
|
||||
data.path = dir->path;
|
||||
data.css = dir->css;
|
||||
data.qpath = dir->qpath;
|
||||
|
||||
QSE_MEMSET (&task, 0, QSE_SIZEOF(task));
|
||||
@ -393,7 +425,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.css.len + 1 + data.qpath.len + 1);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
@ -409,7 +441,9 @@ static int task_init_dir (
|
||||
|
||||
xtn->path.ptr = (qse_mchar_t*)(xtn + 1);
|
||||
qse_mbscpy ((qse_mchar_t*)xtn->path.ptr, arg->path.ptr);
|
||||
xtn->qpath.ptr = xtn->path.ptr + xtn->path.len + 1;
|
||||
xtn->css.ptr = xtn->path.ptr + xtn->path.len + 1;
|
||||
qse_mbscpy ((qse_mchar_t*)xtn->css.ptr, arg->css.ptr);
|
||||
xtn->qpath.ptr = xtn->css.ptr + xtn->css.len + 1;
|
||||
qse_mbscpy ((qse_mchar_t*)xtn->qpath.ptr, arg->qpath.ptr);
|
||||
|
||||
/* switch the context to the extension area */
|
||||
@ -423,15 +457,25 @@ static QSE_INLINE int task_main_dir (
|
||||
{
|
||||
task_dir_t* dir;
|
||||
qse_httpd_task_t* x;
|
||||
qse_dir_t* handle = QSE_NULL;
|
||||
qse_ubi_t handle;
|
||||
|
||||
dir = (task_dir_t*)task->ctx;
|
||||
x = task;
|
||||
|
||||
if (qse_mbsend (dir->path.ptr, QSE_MT("/")))
|
||||
{
|
||||
handle = QSE_OPENDIR (dir->path.ptr);
|
||||
if (handle)
|
||||
if (httpd->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_error (
|
||||
httpd, client, x, http_errnum,
|
||||
&dir->version, dir->keepalive);
|
||||
|
||||
return (x == QSE_NULL)? -1: 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
x = qse_httpd_entaskformat (
|
||||
httpd, client, x,
|
||||
@ -445,21 +489,9 @@ static QSE_INLINE int task_main_dir (
|
||||
if (x) x = entask_directory_segment (httpd, client, x, handle, dir);
|
||||
if (x) return 0;
|
||||
|
||||
QSE_CLOSEDIR (handle);
|
||||
httpd->scb->dir.close (httpd, handle);
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
int http_errnum;
|
||||
http_errnum = (errno == ENOENT)? 404:
|
||||
(errno == EACCES)? 403: 500;
|
||||
x = qse_httpd_entask_error (
|
||||
httpd, client, x, http_errnum,
|
||||
&dir->version, dir->keepalive);
|
||||
|
||||
QSE_CLOSEDIR (handle);
|
||||
return (x == QSE_NULL)? -1: 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -481,14 +513,19 @@ qse_httpd_task_t* qse_httpd_entaskdir (
|
||||
qse_httpd_client_t* client,
|
||||
qse_httpd_task_t* pred,
|
||||
const qse_mchar_t* path,
|
||||
const qse_mchar_t* css,
|
||||
qse_htre_t* req)
|
||||
{
|
||||
qse_httpd_task_t task;
|
||||
task_dir_t data;
|
||||
|
||||
if (css == QSE_NULL) css = QSE_MT("");
|
||||
|
||||
QSE_MEMSET (&data, 0, QSE_SIZEOF(data));
|
||||
data.path.ptr = path;
|
||||
data.path.len = qse_mbslen(data.path.ptr);
|
||||
data.css.ptr = css;
|
||||
data.css.len = qse_mbslen(data.css.ptr);
|
||||
data.qpath.ptr = qse_htre_getqpath(req);
|
||||
data.qpath.len = qse_mbslen(data.qpath.ptr);
|
||||
data.version = *qse_htre_getversion(req);
|
||||
@ -500,6 +537,6 @@ qse_httpd_task_t* qse_httpd_entaskdir (
|
||||
task.ctx = &data;
|
||||
|
||||
return qse_httpd_entask (httpd, client, pred, &task,
|
||||
QSE_SIZEOF(task_dir_t) + data.path.len + 1 + data.qpath.len + 1);
|
||||
QSE_SIZEOF(task_dir_t) + data.path.len + 1 + data.css.len + 1 + data.qpath.len + 1);
|
||||
}
|
||||
|
||||
|
@ -75,6 +75,7 @@
|
||||
#define SERVER_XTN_CFG_USERNAME QSE_HTTPD_SERVER_XTN_CFG_USERNAME
|
||||
#define SERVER_XTN_CFG_PASSWORD QSE_HTTPD_SERVER_XTN_CFG_PASSWORD
|
||||
#define SERVER_XTN_CFG_BASICAUTH QSE_HTTPD_SERVER_XTN_CFG_BASICAUTH
|
||||
#define SERVER_XTN_CFG_DIRCSS QSE_HTTPD_SERVER_XTN_CFG_DIRCSS
|
||||
/* ------------------------------------------------------------------- */
|
||||
|
||||
#if defined(_WIN32)
|
||||
@ -1042,20 +1043,14 @@ static int mux_writable (qse_httpd_t* httpd, qse_ubi_t handle, qse_ntoff_t msec)
|
||||
|
||||
/* ------------------------------------------------------------------- */
|
||||
|
||||
static int file_executable (qse_httpd_t* httpd, const qse_mchar_t* path)
|
||||
{
|
||||
if (access (path, X_OK) == -1)
|
||||
return (errno == EACCES)? 0 /*no*/: -1 /*error*/;
|
||||
return 1; /* yes */
|
||||
}
|
||||
|
||||
static int file_stat (
|
||||
qse_httpd_t* httpd, const qse_mchar_t* path, qse_httpd_stat_t* hst)
|
||||
static int stat_file (
|
||||
qse_httpd_t* httpd, const qse_mchar_t* path, qse_httpd_stat_t* hst, int regonly)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
/* TODO: lstat? or stat? */
|
||||
if (stat (path, &st) <= -1)
|
||||
if (QSE_STAT (path, &st) <= -1)
|
||||
{
|
||||
qse_httpd_seterrnum (httpd, syserr_to_errnum(errno));
|
||||
return -1;
|
||||
@ -1063,7 +1058,7 @@ static int file_stat (
|
||||
|
||||
/* stating for a file. it should be a regular file.
|
||||
* i don't allow other file types. */
|
||||
if (!S_ISREG(st.st_mode))
|
||||
if (regonly && !S_ISREG(st.st_mode))
|
||||
{
|
||||
qse_httpd_seterrnum (httpd, QSE_HTTPD_EACCES);
|
||||
return -1;
|
||||
@ -1071,6 +1066,7 @@ static int file_stat (
|
||||
|
||||
QSE_MEMSET (hst, 0, QSE_SIZEOF(*hst));
|
||||
|
||||
hst->isdir = S_ISDIR(st.st_mode);
|
||||
hst->dev = st.st_dev;
|
||||
hst->ino = st.st_ino;
|
||||
hst->size = st.st_size;
|
||||
@ -1085,6 +1081,21 @@ static int file_stat (
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------- */
|
||||
|
||||
static int file_executable (qse_httpd_t* httpd, const qse_mchar_t* path)
|
||||
{
|
||||
if (access (path, X_OK) == -1)
|
||||
return (errno == EACCES)? 0 /*no*/: -1 /*error*/;
|
||||
return 1; /* yes */
|
||||
}
|
||||
|
||||
static int file_stat (
|
||||
qse_httpd_t* httpd, const qse_mchar_t* path, qse_httpd_stat_t* hst)
|
||||
{
|
||||
return stat_file (httpd, path, hst, 1);
|
||||
}
|
||||
|
||||
static int file_ropen (
|
||||
qse_httpd_t* httpd, const qse_mchar_t* path, qse_ubi_t* handle)
|
||||
{
|
||||
@ -1156,6 +1167,93 @@ static qse_ssize_t file_write (
|
||||
return QSE_WRITE (handle.i, buf, len);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------- */
|
||||
|
||||
typedef struct dir_t dir_t;
|
||||
struct dir_t
|
||||
{
|
||||
qse_mchar_t* path;
|
||||
qse_dir_t* dp;
|
||||
};
|
||||
|
||||
static int dir_open (qse_httpd_t* httpd, const qse_mchar_t* path, qse_ubi_t* handle)
|
||||
{
|
||||
dir_t* d;
|
||||
|
||||
d = QSE_MMGR_ALLOC (httpd->mmgr, QSE_SIZEOF(*d));
|
||||
if (d == QSE_NULL)
|
||||
{
|
||||
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOMEM);
|
||||
return -1;
|
||||
}
|
||||
|
||||
d->path = qse_mbsdup (path, httpd->mmgr);
|
||||
if (d->path == QSE_NULL)
|
||||
{
|
||||
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOMEM);
|
||||
QSE_MMGR_FREE (httpd->mmgr, d);
|
||||
return -1;
|
||||
}
|
||||
|
||||
d->dp = QSE_OPENDIR (path);
|
||||
if (d->dp == QSE_NULL)
|
||||
{
|
||||
qse_httpd_seterrnum (httpd, syserr_to_errnum(errno));
|
||||
QSE_MMGR_FREE (httpd->mmgr, d->path);
|
||||
QSE_MMGR_FREE (httpd->mmgr, d);
|
||||
return -1;
|
||||
}
|
||||
|
||||
handle->ptr = d;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dir_close (qse_httpd_t* httpd, qse_ubi_t handle)
|
||||
{
|
||||
dir_t* d;
|
||||
|
||||
d = (dir_t*)handle.ptr;
|
||||
|
||||
QSE_CLOSEDIR (d->dp);
|
||||
|
||||
QSE_MMGR_FREE (httpd->mmgr, d->path);
|
||||
QSE_MMGR_FREE (httpd->mmgr, d);
|
||||
}
|
||||
|
||||
static int dir_read (qse_httpd_t* httpd, qse_ubi_t handle, qse_httpd_dirent_t* dirent)
|
||||
{
|
||||
dir_t* d;
|
||||
qse_dirent_t* de;
|
||||
qse_mchar_t* fpath;
|
||||
int n;
|
||||
|
||||
d = (dir_t*)handle.ptr;
|
||||
|
||||
errno = 0;
|
||||
de = QSE_READDIR (d->dp);
|
||||
if (de == QSE_NULL)
|
||||
{
|
||||
if (errno == 0) return 0;
|
||||
qse_httpd_seterrnum (httpd, syserr_to_errnum(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* i assume that d->path ends with a slash */
|
||||
fpath = qse_mbsdup2 (d->path, de->d_name, httpd->mmgr);
|
||||
if (fpath == QSE_NULL)
|
||||
{
|
||||
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOMEM);
|
||||
return -1;
|
||||
}
|
||||
|
||||
n = stat_file (httpd, fpath, &dirent->stat, 0);
|
||||
QSE_MMGR_FREE (httpd->mmgr, fpath);
|
||||
if (n <= -1) QSE_MEMSET (dirent, 0, QSE_SIZEOF(*dirent));
|
||||
|
||||
dirent->name = de->d_name;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------- */
|
||||
static void client_close (
|
||||
qse_httpd_t* httpd, qse_httpd_client_t* client)
|
||||
@ -1520,6 +1618,13 @@ static qse_httpd_scb_t httpd_system_callbacks =
|
||||
file_write
|
||||
},
|
||||
|
||||
/* directory operation */
|
||||
{ dir_open,
|
||||
dir_close,
|
||||
dir_read
|
||||
},
|
||||
|
||||
|
||||
/* client connection */
|
||||
{ client_close,
|
||||
client_shutdown,
|
||||
@ -1749,6 +1854,7 @@ auth_ok:
|
||||
|
||||
target->type = QSE_HTTPD_RSRC_DIR;
|
||||
target->u.dir.path = xpath;
|
||||
target->u.dir.css = server_xtn->cfg[SERVER_XTN_CFG_DIRCSS].ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -390,7 +390,7 @@ qse_httpd_task_t* qse_httpd_entaskrsrc (
|
||||
|
||||
case QSE_HTTPD_RSRC_DIR:
|
||||
qse_httpd_discardcontent (httpd, req);
|
||||
task = qse_httpd_entaskdir (httpd, client, QSE_NULL, rsrc->u.dir.path, req);
|
||||
task = qse_httpd_entaskdir (httpd, client, QSE_NULL, rsrc->u.dir.path, rsrc->u.dir.css, req);
|
||||
break;
|
||||
|
||||
case QSE_HTTPD_RSRC_ERROR:
|
||||
|
@ -59,12 +59,20 @@ static int httpd_main (int argc, qse_char_t* argv[])
|
||||
|
||||
for (i = 1; i < argc; i++)
|
||||
{
|
||||
if (qse_httpd_attachserverstd (httpd, argv[i], QSE_NULL, 0) == QSE_NULL)
|
||||
qse_httpd_server_t* server;
|
||||
qse_httpd_server_xtn_t* server_xtn;
|
||||
|
||||
server = qse_httpd_attachserverstd (httpd, argv[i], QSE_NULL, 0);
|
||||
if (server == QSE_NULL)
|
||||
{
|
||||
qse_fprintf (QSE_STDERR,
|
||||
QSE_T("Failed to add httpd listener - %s\n"), argv[i]);
|
||||
goto oops;
|
||||
}
|
||||
|
||||
server_xtn = qse_httpd_getserverxtn (httpd, server);
|
||||
server_xtn->cfg[QSE_HTTPD_SERVER_XTN_CFG_DIRCSS].ptr = QSE_MT("body { background-color:#d0e4fe; font-size: 0.9em; font-family: Ubuntu,'Trebuchet MS',sans-serif; }");
|
||||
server_xtn->cfg[QSE_HTTPD_SERVER_XTN_CFG_DIRCSS].len = qse_mbslen(server_xtn->cfg[QSE_HTTPD_SERVER_XTN_CFG_DIRCSS].ptr);
|
||||
}
|
||||
|
||||
g_httpd = httpd;
|
||||
|
Loading…
x
Reference in New Issue
Block a user