added file-access and dir-access to cmd/http/httpd.c

This commit is contained in:
2013-02-21 15:00:08 +00:00
parent b677b4a892
commit b420a7c0dc
10 changed files with 721 additions and 188 deletions

View File

@ -385,8 +385,13 @@ static int get_highest_fd (void)
#endif
}
else fd = rlim.rlim_max;
if (fd == -1) fd = 1024; /* fallback */
/* F_MAXFD is the highest fd. but RLIMIT_NOFILE and
* _SC_OPEN_MAX returnes the maximum number of file
* descriptors. make adjustment */
if (fd > 0) fd--;
}
if (fd == -1) fd = 1024; /* fallback */
return fd;
}

View File

@ -23,6 +23,7 @@
#include <qse/cmn/str.h>
#include <qse/cmn/pio.h>
#include <qse/cmn/fmt.h>
#include <qse/cmn/path.h>
#include <stdio.h> /* TODO: remove this */
@ -196,6 +197,17 @@ static int cgi_capture_script_header (qse_htre_t* req, const qse_mchar_t* key, c
return 0;
}
static void log_cgi_script_error (task_cgi_t* cgi, const qse_mchar_t* shortmsg)
{
qse_httpd_act_t msg;
qse_size_t pos = 0;
msg.code = QSE_HTTPD_CATCH_MERRMSG;
pos += qse_mbsxcpy (&msg.u.merrmsg[pos], QSE_COUNTOF(msg.u.merrmsg) - pos, shortmsg);
pos += qse_mbsxcpy (&msg.u.merrmsg[pos], QSE_COUNTOF(msg.u.merrmsg) - pos, cgi->script);
cgi->httpd->opt.rcb.logact (cgi->httpd, &msg);
}
static int cgi_htrd_peek_script_output (qse_htrd_t* htrd, qse_htre_t* req)
{
cgi_script_htrd_xtn_t* xtn;
@ -355,8 +367,9 @@ static int cgi_htrd_peek_script_output (qse_htrd_t* htrd, qse_htre_t* req)
if ((cgi->resflags & CGI_RES_SCRIPT_LENGTH) &&
cgi->script_output_received > cgi->script_output_length)
{
/* TODO: cgi returning too much data... something is wrong in CGI */
qse_printf (QSE_T("CGI SCRIPT FUCKED - RETURNING TOO MUCH...\n"));
/* cgi returning too much data... something is wrong in CGI */
if (cgi->httpd->opt.trait & QSE_HTTPD_LOGACT)
log_cgi_script_error (cgi, QSE_MT("cgi redundant output - "));
cgi->httpd->errnum = QSE_HTTPD_EINVAL; /* TODO: change it to a better error code */
return -1;
}
@ -501,8 +514,10 @@ static int cgi_snatch_client_input (
task = (qse_httpd_task_t*)ctx;
cgi = (task_cgi_t*)task->ctx;
#if 0
if (ptr) qse_printf (QSE_T("!!!CGI SNATCHING [%.*hs]\n"), len, ptr);
else qse_printf (QSE_T("!!!CGI SNATCHING DONE\n"));
#endif
QSE_ASSERT (cgi->req);
QSE_ASSERT (!(cgi->reqflags & CGI_REQ_GOTALL));
@ -587,7 +602,9 @@ else qse_printf (QSE_T("!!!CGI SNATCHING DONE\n"));
/* output pipe to child */
task->trigger[1].mask = QSE_HTTPD_TASK_TRIGGER_WRITE;
#if 0
qse_printf (QSE_T("!!!CGI SNATCHED [%.*hs]\n"), len, ptr);
#endif
}
return 0;
@ -608,7 +625,9 @@ static void cgi_forward_client_input_to_script (
{
/* a forwarding error has occurred previously.
* clear the forwarding buffer */
#if 0
qse_printf (QSE_T("FORWARD: CLEARING REQCON FOR ERROR\n"));
#endif
qse_mbs_clear (cgi->reqfwdbuf);
}
else
@ -624,9 +643,11 @@ qse_printf (QSE_T("FORWARD: CLEARING REQCON FOR ERROR\n"));
{
forward:
/* writable */
#if 0
qse_printf (QSE_T("FORWARD: @@@@@@@@@@WRITING[%.*hs]\n"),
(int)QSE_MBS_LEN(cgi->reqfwdbuf),
QSE_MBS_PTR(cgi->reqfwdbuf));
#endif
n = qse_pio_write (
&cgi->pio, QSE_PIO_IN,
QSE_MBS_PTR(cgi->reqfwdbuf),
@ -647,8 +668,9 @@ to the head all the time.. grow the buffer to a certain limit. */
if (n <= -1)
{
qse_printf (QSE_T("FORWARD: @@@@@@@@WRITE TO CGI FAILED\n"));
/* TODO: logging ... */
if (cgi->httpd->opt.trait & QSE_HTTPD_LOGACT)
log_cgi_script_error (cgi, QSE_MT("cgi pio write error - "));
cgi->reqflags |= CGI_REQ_FWDERR;
qse_mbs_clear (cgi->reqfwdbuf);
@ -679,7 +701,9 @@ qse_printf (QSE_T("FORWARD: @@@@@@@@WRITE TO CGI FAILED\n"));
* there is nothing more to forward in the forwarding buffer.
* clear the relay and write triggers for the time being.
*/
#if 0
qse_printf (QSE_T("FORWARD: @@@@@@@@NOTHING MORE TO WRITE TO CGI\n"));
#endif
QSE_ASSERT (cgi->req == QSE_NULL);
/* mark the end of input to the child explicitly. */
@ -919,8 +943,6 @@ static void task_fini_cgi (
QSE_ASSERT (!(cgi->reqflags & CGI_REQ_GOTALL));
qse_htre_unsetconcb (cgi->req);
}
qse_printf (QSE_T("task_fini_cgi\n"));
}
static QSE_INLINE qse_ssize_t cgi_read_script_output_to_buffer (
@ -934,6 +956,10 @@ static QSE_INLINE qse_ssize_t cgi_read_script_output_to_buffer (
QSE_SIZEOF(cgi->buf) - cgi->buflen
);
if (n > 0) cgi->buflen += n;
if (n <= -1 && cgi->httpd->opt.trait & QSE_HTTPD_LOGACT)
log_cgi_script_error (cgi, QSE_MT("cgi pio read error - "));
return n;
}
@ -942,13 +968,16 @@ static QSE_INLINE qse_ssize_t cgi_write_script_output_to_client (
{
qse_ssize_t n;
httpd->errnum = QSE_HTTPD_ENOERR;
n = httpd->opt.scb.client.send (httpd, client, cgi->buf, cgi->buflen);
if (n > 0)
{
QSE_MEMCPY (&cgi->buf[0], &cgi->buf[n], cgi->buflen - n);
cgi->buflen -= n;
}
if (n <= -1 && cgi->httpd->opt.trait & QSE_HTTPD_LOGACT)
log_cgi_script_error (cgi, QSE_MT("cgi write error to client - "));
return n;
}
@ -971,13 +1000,11 @@ static int task_main_cgi_5 (
if (!(task->trigger[2].mask & QSE_HTTPD_TASK_TRIGGER_WRITE) ||
(task->trigger[2].mask & QSE_HTTPD_TASK_TRIGGER_WRITABLE))
{
qse_printf (QSE_T("task_main_cgi_5 about to write %d bytes\n"), (int)cgi->buflen);
if (cgi->buflen > 0)
{
if (cgi_write_script_output_to_client (httpd, client, cgi) <= -1)
{
/* can't return internal server error any more... */
/* TODO: logging ... */
/* can't return internal server error any more... */
return -1;
}
}
@ -1024,11 +1051,7 @@ static int task_main_cgi_4_nph (
}
QSE_ASSERT (cgi->buflen > 0);
if (cgi_write_script_output_to_client (httpd, client, cgi) <= -1)
{
/* TODO: logging ... */
return -1;
}
if (cgi_write_script_output_to_client (httpd, client, cgi) <= -1) return -1;
}
return 1;
@ -1043,8 +1066,10 @@ static int task_main_cgi_4 (
QSE_ASSERT (!cgi->nph);
QSE_ASSERT (cgi->pio_inited);
#if 0
qse_printf (QSE_T("task_main_cgi_4 trigger[0].mask=%d trigger[1].mask=%d trigger[2].mask=%d\n"),
task->trigger[0].mask, task->trigger[1].mask, task->trigger[2].mask);
#endif
if (task->trigger[2].mask & QSE_HTTPD_TASK_TRIGGER_READABLE)
{
@ -1057,7 +1082,6 @@ qse_printf (QSE_T("task_main_cgi_4 trigger[0].mask=%d trigger[1].mask=%d trigger
if (task->trigger[0].mask & QSE_HTTPD_TASK_TRIGGER_READABLE)
{
qse_printf (QSE_T("TASK_MAIN_CGI_4\n"));
if (cgi->resflags & CGI_RES_CLIENT_CHUNK)
{
qse_size_t count, extra;
@ -1068,7 +1092,6 @@ qse_printf (QSE_T("TASK_MAIN_CGI_4\n"));
#define CHLEN_RESERVE 6
qse_printf (QSE_T("READING CHUNKED MODE...\n"));
extra = CHLEN_RESERVE + 2;
count = QSE_SIZEOF(cgi->buf) - cgi->buflen;
if (count > extra)
@ -1080,7 +1103,8 @@ qse_printf (QSE_T("TASK_MAIN_CGI_4\n"));
);
if (n <= -1)
{
/* TODO: logging ... */
if (cgi->httpd->opt.trait & QSE_HTTPD_LOGACT)
log_cgi_script_error (cgi, QSE_MT("cgi pio read error - "));
return -1;
}
if (n == 0)
@ -1121,15 +1145,15 @@ qse_printf (QSE_T("TASK_MAIN_CGI_4\n"));
if ((cgi->resflags & CGI_RES_SCRIPT_LENGTH) &&
cgi->script_output_received > cgi->script_output_length)
{
/* TODO: cgi returning too much data... something is wrong in CGI */
qse_printf (QSE_T("CGI FUCKED UP...RETURNING TOO MUCH DATA\n"));
/* cgi returning too much data... something is wrong in CGI */
if (cgi->httpd->opt.trait & QSE_HTTPD_LOGACT)
log_cgi_script_error (cgi, QSE_MT("cgi redundant output - "));
return -1;
}
}
}
else
{
qse_printf (QSE_T("READING IN NON-CHUNKED MODE...\n"));
if (cgi->buflen < QSE_SIZEOF(cgi->buf))
{
n = cgi_read_script_output_to_buffer (httpd, client, cgi);
@ -1147,9 +1171,9 @@ qse_printf (QSE_T("TASK_MAIN_CGI_4\n"));
if ((cgi->resflags & CGI_RES_SCRIPT_LENGTH) &&
cgi->script_output_received > cgi->script_output_length)
{
/* TODO: logging */
/* TODO: cgi returning too much data... something is wrong in CGI */
qse_printf (QSE_T("CGI FUCKED UP...RETURNING TOO MUCH DATA\n"));
/* cgi returning too much data... something is wrong in CGI */
if (cgi->httpd->opt.trait & QSE_HTTPD_LOGACT)
log_cgi_script_error (cgi, QSE_MT("cgi redundant output - "));
return -1;
}
}
@ -1159,11 +1183,7 @@ qse_printf (QSE_T("TASK_MAIN_CGI_4\n"));
* side is writable. it should be safe to write whenever
* this task function is called. */
QSE_ASSERT (cgi->buflen > 0);
if (cgi_write_script_output_to_client (httpd, client, cgi) <= -1)
{
/* TODO: logging ... */
return -1;
}
if (cgi_write_script_output_to_client (httpd, client, cgi) <= -1) return -1;
}
return 1;
@ -1181,8 +1201,10 @@ static int task_main_cgi_3 (
QSE_ASSERT (!cgi->nph);
#if 0
qse_printf (QSE_T("task_main_cgi_3 trigger[0].mask=%d trigger[1].mask=%d trigger[2].mask=%d\n"),
task->trigger[0].mask, task->trigger[1].mask, task->trigger[2].mask);
#endif
if (task->trigger[2].mask & QSE_HTTPD_TASK_TRIGGER_READABLE)
{
cgi_forward_client_input_to_script (httpd, task, 0);
@ -1200,15 +1222,13 @@ qse_printf (QSE_T("task_main_cgi_3 trigger[0].mask=%d trigger[1].mask=%d trigger
count = MAX_SEND_SIZE;
if (count >= cgi->res_left) count = cgi->res_left;
qse_printf (QSE_T("[cgi_3 sending %d bytes]\n"), (int)count);
if (count > 0)
{
httpd->errnum = QSE_HTTPD_ENOERR;
n = httpd->opt.scb.client.send (httpd, client, cgi->res_ptr, count);
if (n <= -1)
{
qse_printf (QSE_T("[cgi-3 send failure....\n"));
if (cgi->httpd->opt.trait & QSE_HTTPD_LOGACT)
log_cgi_script_error (cgi, QSE_MT("cgi initial write error to client - "));
return -1;
}
@ -1223,7 +1243,6 @@ qse_printf (QSE_T("[cgi-3 send failure....\n"));
if ((cgi->resflags & CGI_RES_SCRIPT_LENGTH) &&
cgi->script_output_received >= cgi->script_output_length)
{
qse_printf (QSE_T("[switching to cgi-5....\n"));
/* if a cgi script specified the content length
* and it has emitted as much as the length,
* i don't wait for the script to finish.
@ -1236,7 +1255,6 @@ qse_printf (QSE_T("[switching to cgi-5....\n"));
}
else
{
qse_printf (QSE_T("[switching to cgi-4....\n"));
task->main = task_main_cgi_4;
task->trigger[2].mask &= ~QSE_HTTPD_TASK_TRIGGER_WRITE;
}
@ -1262,12 +1280,13 @@ static int task_main_cgi_2 (
QSE_ASSERT (!cgi->nph);
QSE_ASSERT (cgi->pio_inited);
#if 0
qse_printf (QSE_T("task_main_cgi_2 trigger[0].mask=%d trigger[1].mask=%d trigger[2].mask=%d\n"),
task->trigger[0].mask, task->trigger[1].mask, task->trigger[2].mask);
#endif
if (task->trigger[2].mask & QSE_HTTPD_TASK_TRIGGER_READABLE)
{
qse_printf (QSE_T("[cgi_2 write]\n"));
cgi_forward_client_input_to_script (httpd, task, 0);
}
else if (task->trigger[1].mask & QSE_HTTPD_TASK_TRIGGER_WRITABLE)
@ -1277,7 +1296,6 @@ qse_printf (QSE_T("[cgi_2 write]\n"));
if (task->trigger[0].mask & QSE_HTTPD_TASK_TRIGGER_READABLE)
{
qse_printf (QSE_T("[cgi_2 read]\n"));
n = qse_pio_read (
&cgi->pio, QSE_PIO_OUT,
&cgi->buf[cgi->buflen],
@ -1286,25 +1304,24 @@ qse_printf (QSE_T("[cgi_2 read]\n"));
if (n <= -1)
{
/* can't return internal server error any more... */
/* TODO: logging ... */
if (cgi->httpd->opt.trait & QSE_HTTPD_LOGACT)
log_cgi_script_error (cgi, QSE_MT("cgi pio read error - "));
goto oops;
}
if (n == 0)
{
/* end of output from cgi before it has seen a header.
* the cgi script must be crooked. */
/* TODO: logging */
qse_printf (QSE_T("#####PREMATURE EOF FROM CHILD\n"));
if (cgi->httpd->opt.trait & QSE_HTTPD_LOGACT)
log_cgi_script_error (cgi, QSE_MT("cgi premature eof - "));
goto oops;
}
cgi->buflen += n;
qse_printf (QSE_T("#####CGI FEED [%.*hs]\n"), (int)cgi->buflen, cgi->buf);
if (qse_htrd_feed (cgi->script_htrd, cgi->buf, cgi->buflen) <= -1)
{
/* TODO: logging */
qse_printf (QSE_T("#####INVALID HEADER FROM FROM CHILD [%.*hs]\n"), (int)cgi->buflen, cgi->buf);
if (cgi->httpd->opt.trait & QSE_HTTPD_LOGACT)
log_cgi_script_error (cgi, QSE_MT("cgi feed error - "));
goto oops;
}
@ -1324,7 +1341,9 @@ qse_printf (QSE_T("#####INVALID HEADER FROM FROM CHILD [%.*hs]\n"), (int)cgi->bu
cgi->res_ptr = QSE_MBS_PTR(cgi->res);
cgi->res_left = QSE_MBS_LEN(cgi->res);
#if 0
qse_printf (QSE_T("TRAILING DATA=[%.*hs]\n"), (int)QSE_MBS_LEN(cgi->res), QSE_MBS_PTR(cgi->res));
#endif
task->main = task_main_cgi_3;
task->trigger[2].mask |= QSE_HTTPD_TASK_TRIGGER_WRITE;
return 1;
@ -1447,7 +1466,6 @@ static int task_main_cgi (
* this is possible because the main loop can still read
* between the initializer function (task_init_cgi()) and
* this function. so let's forward it initially. */
qse_printf (QSE_T("FORWARDING INITIAL PART OF CONTENT...\n"));
cgi_forward_client_input_to_script (httpd, task, 0);
/* if the initial forwarding clears the forwarding

View File

@ -29,8 +29,8 @@
typedef struct task_proxy_arg_t task_proxy_arg_t;
struct task_proxy_arg_t
{
qse_nwad_t* peer_nwad;
qse_nwad_t* peer_local;
const qse_nwad_t* peer_nwad;
const qse_nwad_t* peer_local;
qse_htre_t* req;
};

View File

@ -531,12 +531,15 @@ struct httpd_xtn_t
#if defined(HAVE_SSL)
static int init_xtn_ssl (
httpd_xtn_t* xtn,
qse_httpd_t* httpd,
const qse_mchar_t* pemfile,
const qse_mchar_t* keyfile/*,
const qse_mchar_t* chainfile*/)
{
SSL_CTX* ctx;
httpd_xtn_t* xtn;
xtn = (httpd_xtn_t*)qse_httpd_getxtn (httpd);
ctx = SSL_CTX_new (SSLv23_server_method());
if (ctx == QSE_NULL) return -1;
@ -548,10 +551,14 @@ static int init_xtn_ssl (
SSL_CTX_check_private_key (ctx) == 0 /*||
SSL_CTX_use_certificate_chain_file (ctx, chainfile) == 0*/)
{
qse_mchar_t buf[128];
ERR_error_string_n(ERR_get_error(), buf, QSE_COUNTOF(buf));
/* TODO: logging */
qse_fprintf (QSE_STDERR, QSE_T("Error: %hs\n"), buf);
if (httpd->opt.trait & QSE_HTTPD_LOGACT)
{
qse_httpd_act_t msg;
msg.code = QSE_HTTPD_CATCH_MERRMSG;
ERR_error_string_n (ERR_get_error(), msg.u.merrmsg, QSE_COUNTOF(msg.u.merrmsg));
httpd->opt.rcb.logact (httpd, &msg);
}
SSL_CTX_free (ctx);
return -1;
}
@ -600,7 +607,7 @@ qse_httpd_t* qse_httpd_openstdwithmmgr (qse_mmgr_t* mmgr, qse_size_t xtnsize)
xtn = (httpd_xtn_t*)qse_httpd_getxtn (httpd);
#if defined(HAVE_SSL)
/*init_xtn_ssl (xtn, "http01.pem", "http01.key");*/
/*init_xtn_ssl (httpd, "http01.pem", "http01.key");*/
#endif
set_httpd_callbacks (httpd);
@ -1409,7 +1416,16 @@ static int file_ropen (
}
handle->ptr = fio;
qse_printf (QSE_T("opened rfile [%hs][%p][%p]\n"), path, handle->ptr, fio->handle);
if (httpd->opt.trait & QSE_HTTPD_LOGACT)
{
qse_httpd_act_t msg;
qse_size_t pos;
msg.code = QSE_HTTPD_CATCH_MDBGMSG;
pos = qse_mbscpy (msg.u.mdbgmsg, QSE_MT("ropened file "));
qse_mbsxcpy (&msg.u.mdbgmsg[pos], QSE_COUNTOF(msg.u.mdbgmsg) - pos, path);
httpd->opt.rcb.logact (httpd, &msg);
}
return 0;
}
@ -1438,13 +1454,22 @@ static int file_wopen (
}
handle->ptr = fio;
qse_printf (QSE_T("opened wfile [%hs][%p][%p]\n"), path, handle->ptr, fio->handle);
if (httpd->opt.trait & QSE_HTTPD_LOGACT)
{
qse_httpd_act_t msg;
qse_size_t pos;
msg.code = QSE_HTTPD_CATCH_MDBGMSG;
pos = qse_mbscpy (msg.u.mdbgmsg, QSE_MT("wopened file "));
qse_mbsxcpy (&msg.u.mdbgmsg[pos], QSE_COUNTOF(msg.u.mdbgmsg) - pos, path);
httpd->opt.rcb.logact (httpd, &msg);
}
return 0;
}
static void file_close (qse_httpd_t* httpd, qse_ubi_t handle)
{
qse_printf (QSE_T("closed file....%p\n"), handle.ptr);
qse_fio_fini (handle.ptr);
QSE_MMGR_FREE (httpd->mmgr, handle.ptr);
}
@ -1512,7 +1537,16 @@ static int dir_open (qse_httpd_t* httpd, const qse_mchar_t* path, qse_ubi_t* han
return -1;
}
qse_printf (QSE_T("OPENED DIRECTORY [%hs]\n"), path);
if (httpd->opt.trait & QSE_HTTPD_LOGACT)
{
qse_httpd_act_t msg;
qse_size_t pos;
msg.code = QSE_HTTPD_CATCH_MDBGMSG;
pos = qse_mbscpy (msg.u.mdbgmsg, QSE_MT("opened dir "));
qse_mbsxcpy (&msg.u.mdbgmsg[pos], QSE_COUNTOF(msg.u.mdbgmsg) - pos, path);
httpd->opt.rcb.logact (httpd, &msg);
}
handle->ptr = d;
return 0;
}
@ -1693,7 +1727,7 @@ static int client_accepted (qse_httpd_t* httpd, qse_httpd_client_t* client)
{
/* delayed initialization of ssl */
/* TODO: certificate from options */
if (init_xtn_ssl (xtn, "http01.pem", "http01.key") <= -1)
if (init_xtn_ssl (httpd, "http01.pem", "http01.key") <= -1)
{
return -1;
}
@ -1711,9 +1745,6 @@ static int client_accepted (qse_httpd_t* httpd, qse_httpd_client_t* client)
if (ssl == QSE_NULL) return -1;
client->handle2.ptr = ssl;
qse_printf (QSE_T("SSL ACCEPTING %d\n"), client->handle.i);
qse_fflush (QSE_STDOUT);
if (SSL_set_fd (ssl, client->handle.i) == 0)
{
/* don't free ssl here since client_closed()
@ -1727,18 +1758,25 @@ qse_fflush (QSE_STDOUT);
ret = SSL_accept (ssl);
if (ret <= 0)
{
if (SSL_get_error(ssl,ret) == SSL_ERROR_WANT_READ)
int err;
if ((err = SSL_get_error(ssl,ret)) == SSL_ERROR_WANT_READ)
{
/* handshaking isn't complete. */
return 0;
}
qse_fprintf (QSE_STDERR, QSE_T("Error: SSL ACCEPT ERROR\n"));
if (httpd->opt.trait & QSE_HTTPD_LOGACT)
{
qse_httpd_act_t msg;
msg.code = QSE_HTTPD_CATCH_MERRMSG;
ERR_error_string_n (err, msg.u.merrmsg, QSE_COUNTOF(msg.u.merrmsg));
httpd->opt.rcb.logact (httpd, &msg);
}
/* SSL_free (ssl); */
return -1;
}
qse_printf (QSE_T("SSL ACCEPTED %d\n"), client->handle.i);
qse_fflush (QSE_STDOUT);
#else
qse_httpd_seterrnum (httpd, QSE_HTTPD_ENOIMPL);
return -1;
@ -1763,6 +1801,7 @@ static void client_closed (qse_httpd_t* httpd, qse_httpd_client_t* client)
}
/* ------------------------------------------------------------------- */
#if 0
static qse_htb_walk_t walk (qse_htb_t* htb, qse_htb_pair_t* pair, void* ctx)
{
qse_htre_hdrval_t* val;
@ -1775,6 +1814,7 @@ qse_printf (QSE_T("HEADER OK %d[%hs] %d[%hs]\n"), (int)QSE_HTB_KLEN(pair), QSE_
}
return QSE_HTB_WALK_FORWARD;
}
#endif
static int process_request (
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_htre_t* req, int peek)
@ -1796,6 +1836,7 @@ static int process_request (
* non-peek mode as well */
if (peek) qse_perdechttpstr (qse_htre_getqpath(req), qse_htre_getqpath(req));
#if 0
qse_printf (QSE_T("================================\n"));
qse_printf (QSE_T("[%lu] %hs REQUEST ==> [%hs] version[%d.%d %hs] method[%hs]\n"),
(unsigned long)time(NULL),
@ -1814,6 +1855,7 @@ if (qse_htre_getcontentlen(req) > 0)
{
qse_printf (QSE_T("CONTENT [%.*S]\n"), (int)qse_htre_getcontentlen(req), qse_htre_getcontentptr(req));
}
#endif
if (peek)
{
@ -2044,11 +2086,12 @@ static void impede_httpd (qse_httpd_t* httpd)
/* do nothing */
}
static void logact_httpd (qse_httpd_t* httpd, qse_httpd_act_t* act)
static void logact_httpd (qse_httpd_t* httpd, const qse_httpd_act_t* act)
{
/* do nothing */
}
static qse_httpd_scb_t httpd_system_callbacks =
{
/* server */
@ -2341,11 +2384,11 @@ static int make_resource (
QSE_MEMSET (target, 0, QSE_SIZEOF(*target));
qse_printf (QSE_T(">>> MAKING RESOURCE [%hs]\n"), tmp.qpath);
server_xtn = qse_httpd_getserverxtn (httpd, client->server);
if (server_xtn->query (httpd, client->server, req, tmp.xpath, QSE_HTTPD_SERVERSTD_DOCROOT, &tmp.docroot) <= -1 ||
server_xtn->query (httpd, client->server, req, tmp.xpath, QSE_HTTPD_SERVERSTD_REALM, &tmp.realm) <= -1 ||
if (server_xtn->query (httpd, client->server, req, tmp.xpath, QSE_HTTPD_SERVERSTD_DOCROOT, &tmp.docroot) <= -1) return -1;
if (server_xtn->query (httpd, client->server, req, tmp.xpath, QSE_HTTPD_SERVERSTD_REALM, &tmp.realm) <= -1 ||
server_xtn->query (httpd, client->server, req, tmp.xpath, QSE_HTTPD_SERVERSTD_AUTH, &tmp.auth) <= -1 ||
server_xtn->query (httpd, client->server, req, tmp.xpath, QSE_HTTPD_SERVERSTD_INDEX, &tmp.index) <= -1)
{
@ -2455,8 +2498,19 @@ auth_ok:
}
}
target->type = QSE_HTTPD_RSRC_DIR;
target->u.dir.path = tmp.xpath;
/* it is a directory - should i allow it? */
if (server_xtn->query (httpd, client->server, req, tmp.xpath, QSE_HTTPD_SERVERSTD_DIRACC, &target->u.err.code) <= -1) target->u.err.code = 500;
if (target->u.err.code != 200)
{
target->type = QSE_HTTPD_RSRC_ERR;
/* free xpath since it won't be used */
QSE_MMGR_FREE (httpd->mmgr, tmp.xpath);
}
else
{
target->type = QSE_HTTPD_RSRC_DIR;
target->u.dir.path = tmp.xpath;
}
}
else
{
@ -2478,14 +2532,25 @@ auth_ok:
}
if (n >= 1) return 0;
/* fall back to a normal file. */
target->type = QSE_HTTPD_RSRC_FILE;
target->u.file.path = tmp.xpath;
if (server_xtn->query (httpd, client->server, req, tmp.xpath, QSE_HTTPD_SERVERSTD_MIME, &target->u.file.mime) <= -1)
/* check file's access permission */
if (server_xtn->query (httpd, client->server, req, tmp.xpath, QSE_HTTPD_SERVERSTD_FILEACC, &target->u.err.code) <= -1) target->u.err.code = 500;
if (target->u.err.code != 200)
{
/* don't care about failure */
target->u.file.mime = QSE_NULL;
target->type = QSE_HTTPD_RSRC_ERR;
/* free xpath since it won't be used */
QSE_MMGR_FREE (httpd->mmgr, tmp.xpath);
}
else
{
/* fall back to a normal file. */
target->type = QSE_HTTPD_RSRC_FILE;
target->u.file.path = tmp.xpath;
if (server_xtn->query (httpd, client->server, req, tmp.xpath, QSE_HTTPD_SERVERSTD_MIME, &target->u.file.mime) <= -1)
{
/* don't care about failure */
target->u.file.mime = QSE_NULL;
}
}
}
@ -2581,6 +2646,12 @@ static int query_server (
*(const qse_mchar_t**)result = QSE_NULL;
return 0;
case QSE_HTTPD_SERVERSTD_DIRACC:
case QSE_HTTPD_SERVERSTD_FILEACC:
*(int*)result = 200;
return 0;
}
qse_httpd_seterrnum (httpd, QSE_HTTPD_EINVAL);

View File

@ -457,7 +457,7 @@ static void purge_client (qse_httpd_t* httpd, qse_httpd_client_t* client)
prev = client->prev;
next = client->next;
if (httpd->opt.trait & QSE_HTTPD_ENABLELOG)
if (httpd->opt.trait & QSE_HTTPD_LOGACT)
{
qse_httpd_act_t msg;
msg.code = QSE_HTTPD_PURGE_CLIENT;
@ -562,14 +562,13 @@ qse_printf (QSE_T("MUX ADDHND CLIENT READ %d\n"), client->handle.i);
httpd->client.list.tail = client;
}
{
/* TODO: proper logging */
qse_char_t tmp[128], tmp2[128], tmp3[128];
qse_nwadtostr (&client->local_addr, tmp, QSE_COUNTOF(tmp), QSE_NWADTOSTR_ALL);
qse_nwadtostr (&client->orgdst_addr, tmp2, QSE_COUNTOF(tmp2), QSE_NWADTOSTR_ALL);
qse_nwadtostr (&client->remote_addr, tmp3, QSE_COUNTOF(tmp3), QSE_NWADTOSTR_ALL);
qse_printf (QSE_T("connection %d accepted %s(%s from %s\n"), client->handle.i, tmp, tmp2, tmp3);
}
if (httpd->opt.trait & QSE_HTTPD_LOGACT)
{
qse_httpd_act_t msg;
msg.code = QSE_HTTPD_ACCEPT_CLIENT;
msg.u.client = client;
httpd->opt.rcb.logact (httpd, &msg);
}
}
return 0;
}
@ -733,7 +732,6 @@ reread:
if (httpd->errnum == QSE_HTTPD_EAGAIN)
{
/* nothing to read yet. */
qse_printf (QSE_T("Warning: Nothing to read from a client %d\n"), client->handle.i);
return 0; /* return ok */
}
else if (httpd->errnum == QSE_HTTPD_EINTR)
@ -743,14 +741,22 @@ qse_printf (QSE_T("Warning: Nothing to read from a client %d\n"), client->handle
else
{
/* TOOD: if (httpd->errnum == QSE_HTTPD_ENOERR) httpd->errnum = QSE_HTTPD_ECALLBACK; */
qse_printf (QSE_T("Error: failed to read from a client %d\n"), client->handle.i);
/* TODO: find a way to disconnect */
if (httpd->opt.trait & QSE_HTTPD_LOGACT)
{
qse_httpd_act_t msg;
msg.code = QSE_HTTPD_READERR_CLIENT;
msg.u.client = client;
httpd->opt.rcb.logact (httpd, &msg);
}
/* TODO: find a way to disconnect */
return -1;
}
}
else if (m == 0)
{
#if 0
qse_printf (QSE_T("Debug: connection closed %d\n"), client->handle.i);
#endif
/* reading from the client returned 0. this typically
* happens when the client closes the connection or
* shutdown the writing half of the socket. it's
@ -764,17 +770,22 @@ qse_printf (QSE_T("Debug: connection closed %d\n"), client->handle.i);
/* there is still more tasks to finish and
* http reader is not waiting for any more feeds. */
client->status |= CLIENT_MUTE;
#if 0
qse_printf (QSE_T(">>>>> Marking client %d as MUTE\n"), client->handle.i);
#endif
return 0;
}
else
{
#if 0
qse_printf (QSE_T(">>>>> Returning failure for client %d\n"), client->handle.i);
#endif
httpd->errnum = QSE_HTTPD_EDISCON;
return -1;
}
}
#if 0
qse_printf (QSE_T("!!!!!FEEDING %d from %d ["), (int)m, (int)client->handle.i);
#if !defined(__WATCOMC__)
{
@ -783,6 +794,7 @@ for (i = 0; i < m; i++) qse_printf (QSE_T("%hc"), buf[i]);
}
#endif
qse_printf (QSE_T("]\n"));
#endif
/* qse_htrd_feed() may call the request callback
* multiple times. that's because we don't know
@ -798,17 +810,21 @@ qse_printf (QSE_T("]\n"));
else httpd->errnum = QSE_HTTPD_ENOMEM; /* TODO: better translate error code */
}
#if 0
qse_printf (QSE_T("Error: http error while processing %d ["), (int)client->handle.i);
{
int i;
for (i = 0; i < m; i++) qse_printf (QSE_T("%hc"), buf[i]);
}
qse_printf (QSE_T("]\n"));
#endif
return -1;
}
#if 0
qse_printf (QSE_T("!!!!!FEEDING OK OK OK OK %d from %d\n"), (int)m, (int)client->handle.i);
#endif
if (client->status & CLIENT_PENDING)
{
@ -840,7 +856,6 @@ static int invoke_client_task (
int n, trigger_fired, client_handle_writable;
/* TODO: handle comparison callback ... */
qse_printf (QSE_T("INVOKE CLIENT TASK..........\n"));
if (handle.i == client->handle.i && (mask & QSE_HTTPD_MUX_READ)) /* TODO: no direct comparision */
{
if (!(client->status & CLIENT_MUTE) &&
@ -850,7 +865,6 @@ qse_printf (QSE_T("INVOKE CLIENT TASK..........\n"));
* purge the client in perform_client_task().
* thus the following line isn't necessary.
*if (httpd->errnum == QSE_HTTPD_EDISCON) return 0;*/
qse_printf (QSE_T("ERROR: read from client [%d] failed...\n"), (int)handle.i);
return -1;
}
}
@ -862,7 +876,6 @@ qse_printf (QSE_T("ERROR: read from client [%d] failed...\n"), (int)handle.i);
if (client->status & CLIENT_MUTE)
{
/* handle this delayed client disconnection */
qse_printf (QSE_T("ERROR: mute client got no more task [%d] failed...\n"), (int)client->handle.i);
return -1;
}
@ -908,7 +921,6 @@ qse_printf (QSE_T("ERROR: mute client got no more task [%d] failed...\n"), (int)
}
n = task->main (httpd, client, task);
qse_printf (QSE_T("task returend %d\n"), n);
if (n <= -1) return -1;
else if (n == 0)
{
@ -1118,17 +1130,12 @@ static int perform_client_task (
qse_gettime (&client->last_active); /* TODO: error check??? */
move_client_to_tail (httpd, client);
if (invoke_client_task (httpd, client, handle, mask) <= -1)
{
qse_printf (QSE_T("OOPS AFTER CLIENT TASK BAD XXXXXXXXXXXXXX [%d]\n"), (int)handle.i);
goto oops;
}
if (invoke_client_task (httpd, client, handle, mask) <= -1) goto oops;
}
return 0;
oops:
qse_printf (QSE_T("MARKING BAD XXXXXXXXXXXXXX [%d]\n"), (int)handle.i);
/*purge_client (httpd, client);*/
client->status |= CLIENT_BAD;
client->bad_next = httpd->client.bad;
@ -1336,3 +1343,8 @@ const qse_mchar_t* qse_httpd_fmtgmtimetobb (
qse_fmthttptime (nt, httpd->gtbuf[idx], QSE_COUNTOF(httpd->gtbuf[idx]));
return httpd->gtbuf[idx];
}
/* --------------------------------------------------- */

View File

@ -235,13 +235,16 @@ qse_xli_pair_t* qse_xli_insertpair (
if (pair == QSE_NULL) return QSE_NULL;
kptr = (qse_char_t*)(pair + 1);
nptr = kptr + klen + 1;
qse_strcpy (kptr, key);
if (name) qse_strcpy (nptr, name);
pair->type = QSE_XLI_PAIR;
pair->key = kptr;
pair->name = nptr;
if (name)
{
nptr = kptr + klen + 1;
qse_strcpy (nptr, name);
pair->name = nptr;
}
pair->val = value; /* this assumes it points to a dynamically allocated atom */
insert_atom (xli, parent, peer, (qse_xli_atom_t*)pair);