added more cgi related code
This commit is contained in:
parent
3634d16aaf
commit
0998ae3b25
@ -45,8 +45,9 @@ enum qse_htrd_option_t
|
||||
{
|
||||
QSE_HTRD_SKIPEMPTYLINES = (1 << 0), /**< skip leading empty lines before the initial line */
|
||||
QSE_HTRD_SKIPINITIALLINE = (1 << 1), /**< skip processing an initial line */
|
||||
QSE_HTRD_REQUEST = (1 << 2), /**< parse input as a request */
|
||||
QSE_HTRD_RESPONSE = (1 << 3) /**< parse input as a response */
|
||||
QSE_HTRD_HURRIED = (1 << 2), /**< trigger a callback also after headers without processing contents */
|
||||
QSE_HTRD_REQUEST = (1 << 3), /**< parse input as a request */
|
||||
QSE_HTRD_RESPONSE = (1 << 4) /**< parse input as a response */
|
||||
};
|
||||
|
||||
typedef enum qse_htrd_option_t qse_htrd_option_t;
|
||||
@ -96,15 +97,6 @@ struct qse_htrd_t
|
||||
void* chl;
|
||||
} fed;
|
||||
|
||||
#if 0
|
||||
struct
|
||||
{
|
||||
/* temporary space to store a key and value pair
|
||||
* during the call to qse_http_scanqparamstr() */
|
||||
qse_htob_t qparam;
|
||||
} tmp;
|
||||
#endif
|
||||
|
||||
enum
|
||||
{
|
||||
QSE_HTRD_RETYPE_Q,
|
||||
|
@ -35,23 +35,27 @@ struct qse_htre_t
|
||||
qse_http_version_t version;
|
||||
|
||||
int qmethod_or_sstatus;
|
||||
qse_htob_t qpath_or_smesg;
|
||||
qse_htob_t qparam;
|
||||
qse_mbs_t qpath_or_smesg;
|
||||
qse_mbs_t qparam;
|
||||
|
||||
/* special attributes derived from the header */
|
||||
struct
|
||||
{
|
||||
int chunked;
|
||||
int content_length;
|
||||
int content_length_set;
|
||||
qse_size_t content_length;
|
||||
int connection_close;
|
||||
int expect_continue;
|
||||
|
||||
/* indicates if the content has been filled */
|
||||
int hurried;
|
||||
} attr;
|
||||
|
||||
/* header table */
|
||||
qse_htb_t hdrtab;
|
||||
|
||||
/* content octets */
|
||||
qse_htob_t content;
|
||||
qse_mbs_t content;
|
||||
|
||||
/* if set, the rest of the contents are discarded */
|
||||
int discard;
|
||||
@ -140,13 +144,13 @@ void qse_htre_clear (
|
||||
|
||||
int qse_htre_setstrfromcstr (
|
||||
qse_htre_t* re,
|
||||
qse_htob_t* str,
|
||||
qse_mbs_t* str,
|
||||
const qse_mcstr_t* cstr
|
||||
);
|
||||
|
||||
int qse_htre_setstrfromxstr (
|
||||
qse_htre_t* re,
|
||||
qse_htob_t* str,
|
||||
qse_mbs_t* str,
|
||||
const qse_mxstr_t* xstr
|
||||
);
|
||||
|
||||
|
@ -38,35 +38,35 @@ static QSE_INLINE int is_space_octet (qse_mchar_t c)
|
||||
|
||||
static QSE_INLINE int is_purespace_octet (qse_mchar_t c)
|
||||
{
|
||||
return c == ' ' || c == '\t';
|
||||
return c == QSE_MT(' ') || c == QSE_MT('\t');
|
||||
}
|
||||
|
||||
static QSE_INLINE int is_upalpha_octet (qse_mchar_t c)
|
||||
{
|
||||
return c >= 'A' && c <= 'Z';
|
||||
return c >= QSE_MT('A') && c <= QSE_MT('Z');
|
||||
}
|
||||
|
||||
static QSE_INLINE int is_loalpha_octet (qse_mchar_t c)
|
||||
{
|
||||
return c >= 'a' && c <= 'z';
|
||||
return c >= QSE_MT('a') && c <= QSE_MT('z');
|
||||
}
|
||||
|
||||
static QSE_INLINE int is_alpha_octet (qse_mchar_t c)
|
||||
{
|
||||
return (c >= 'A' && c <= 'Z') ||
|
||||
(c >= 'a' && c <= 'z');
|
||||
return (c >= QSE_MT('A') && c <= QSE_MT('Z')) ||
|
||||
(c >= QSE_MT('a') && c <= QSE_MT('z'));
|
||||
}
|
||||
|
||||
static QSE_INLINE int is_digit_octet (qse_mchar_t c)
|
||||
{
|
||||
return c >= '0' && c <= '9';
|
||||
return c >= QSE_MT('0') && c <= QSE_MT('9');
|
||||
}
|
||||
|
||||
static QSE_INLINE int is_xdigit_octet (qse_mchar_t c)
|
||||
{
|
||||
return (c >= '0' && c <= '9') ||
|
||||
(c >= 'A' && c <= 'F') ||
|
||||
(c >= 'a' && c <= 'f');
|
||||
return (c >= QSE_MT('0') && c <= QSE_MT('9')) ||
|
||||
(c >= QSE_MT('A') && c <= QSE_MT('F')) ||
|
||||
(c >= QSE_MT('a') && c <= QSE_MT('f'));
|
||||
}
|
||||
|
||||
static QSE_INLINE int digit_to_num (qse_mchar_t c)
|
||||
@ -534,6 +534,7 @@ static QSE_INLINE int capture_content_length (
|
||||
}
|
||||
|
||||
htrd->re.attr.content_length = len;
|
||||
htrd->re.attr.content_length_set = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -562,10 +563,10 @@ static QSE_INLINE int capture_transfer_encoding (
|
||||
n = compare_octets (QSE_HTB_VPTR(pair), QSE_HTB_VLEN(pair), "chunked", 7);
|
||||
if (n == 0)
|
||||
{
|
||||
if (htrd->re.attr.content_length > 0)
|
||||
/* if (htrd->re.attr.content_length > 0) */
|
||||
if (htrd->re.attr.content_length_set)
|
||||
{
|
||||
/* content-length is greater than 0
|
||||
* while transfer-encoding: chunked is specified. */
|
||||
/* both content-length and 'transfer-encoding: chunked' are specified. */
|
||||
goto badre;
|
||||
}
|
||||
|
||||
@ -881,7 +882,7 @@ static const qse_mchar_t* getchunklen (qse_htrd_t* htrd, const qse_mchar_t* ptr,
|
||||
/* this function must be called in the GET_CHUNK_LEN context */
|
||||
QSE_ASSERT (htrd->fed.s.chunk.phase == GET_CHUNK_LEN);
|
||||
|
||||
//qse_printf (QSE_T("CALLING getchunklen [%d]\n"), *ptr);
|
||||
/*qse_printf (QSE_T("CALLING getchunklen [%d]\n"), *ptr);*/
|
||||
if (htrd->fed.s.chunk.count <= 0)
|
||||
{
|
||||
/* skip leading spaces if the first character of
|
||||
@ -911,7 +912,7 @@ static const qse_mchar_t* getchunklen (qse_htrd_t* htrd, const qse_mchar_t* ptr,
|
||||
if (htrd->fed.s.chunk.count <= 0)
|
||||
{
|
||||
/* empty line - no more chunk */
|
||||
//qse_printf (QSE_T("empty line chunk done....\n"));
|
||||
/*qse_printf (QSE_T("empty line chunk done....\n"));*/
|
||||
htrd->fed.s.chunk.phase = GET_CHUNK_DONE;
|
||||
}
|
||||
else if (htrd->fed.s.chunk.len <= 0)
|
||||
@ -919,13 +920,13 @@ static const qse_mchar_t* getchunklen (qse_htrd_t* htrd, const qse_mchar_t* ptr,
|
||||
/* length explicity specified to 0
|
||||
get trailing headers .... */
|
||||
htrd->fed.s.chunk.phase = GET_CHUNK_TRAILERS;
|
||||
//qse_printf (QSE_T("SWITCH TO GET_CHUNK_TRAILERS....\n"));
|
||||
/*qse_printf (QSE_T("SWITCH TO GET_CHUNK_TRAILERS....\n"));*/
|
||||
}
|
||||
else
|
||||
{
|
||||
/* ready to read the chunk data... */
|
||||
htrd->fed.s.chunk.phase = GET_CHUNK_DATA;
|
||||
//qse_printf (QSE_T("SWITCH TO GET_CHUNK_DATA....\n"));
|
||||
/*qse_printf (QSE_T("SWITCH TO GET_CHUNK_DATA....\n"));*/
|
||||
}
|
||||
|
||||
htrd->fed.s.need = htrd->fed.s.chunk.len;
|
||||
@ -933,7 +934,7 @@ static const qse_mchar_t* getchunklen (qse_htrd_t* htrd, const qse_mchar_t* ptr,
|
||||
}
|
||||
else
|
||||
{
|
||||
//qse_printf (QSE_T("XXXXXXXXXXXXXXXXXxxx [%c]\n"), *ptr);
|
||||
/*qse_printf (QSE_T("XXXXXXXXXXXXXXXXXxxx [%c]\n"), *ptr);*/
|
||||
htrd->errnum = QSE_HTRD_EBADRE;
|
||||
return QSE_NULL;
|
||||
}
|
||||
@ -1102,6 +1103,53 @@ int qse_htrd_feed (qse_htrd_t* htrd, const qse_mchar_t* req, qse_size_t len)
|
||||
if (parse_initial_line_and_headers (htrd, req, ptr - req) <= -1)
|
||||
return -1;
|
||||
|
||||
if (htrd->option & QSE_HTRD_HURRIED)
|
||||
{
|
||||
int n;
|
||||
|
||||
/* it pushes any trailing data into the content in this mode.
|
||||
* so the handler knows if there is contents fed to this reader. */
|
||||
if (push_to_buffer (htrd, &htrd->re.content, ptr, end - ptr) <= -1)
|
||||
return -1;
|
||||
|
||||
|
||||
htrd->re.attr.hurried = 1;
|
||||
htrd->errnum = QSE_HTRD_ENOERR;
|
||||
if (htrd->retype == QSE_HTRD_RETYPE_S)
|
||||
{
|
||||
QSE_ASSERTX (
|
||||
htrd->recbs->response != QSE_NULL,
|
||||
"set response callback before feeding"
|
||||
);
|
||||
n = htrd->recbs->response (htrd, &htrd->re);
|
||||
}
|
||||
else
|
||||
{
|
||||
QSE_ASSERTX (
|
||||
htrd->recbs->request != QSE_NULL,
|
||||
"set request callback before feeding"
|
||||
);
|
||||
n = htrd->recbs->request (htrd, &htrd->re);
|
||||
}
|
||||
|
||||
/* qse_mbs_clear (&htrd->re.content); */
|
||||
|
||||
if (n <= -1)
|
||||
{
|
||||
if (htrd->errnum == QSE_HTRD_ENOERR)
|
||||
htrd->errnum = QSE_HTRD_ERECBS;
|
||||
|
||||
/* need to clear request on error?
|
||||
clear_feed (htrd); */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* if QSE_HTRD_HURRIED is set, we do not handle expect_continue */
|
||||
/* if QSE_HTRD_HURRIED is set, we handle a single request only */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (htrd->retype == QSE_HTRD_RETYPE_Q &&
|
||||
htrd->re.attr.expect_continue &&
|
||||
htrd->recbs->expect_continue && ptr >= end)
|
||||
@ -1115,6 +1163,8 @@ int qse_htrd_feed (qse_htrd_t* htrd, const qse_mchar_t* req, qse_size_t len)
|
||||
* not fed here?
|
||||
*/
|
||||
|
||||
htrd->re.attr.hurried = 0;
|
||||
htrd->errnum = QSE_HTRD_ENOERR;
|
||||
n = htrd->recbs->expect_continue (htrd, &htrd->re);
|
||||
|
||||
if (n <= -1)
|
||||
@ -1136,7 +1186,7 @@ int qse_htrd_feed (qse_htrd_t* htrd, const qse_mchar_t* req, qse_size_t len)
|
||||
if (htrd->re.attr.chunked)
|
||||
{
|
||||
/* transfer-encoding: chunked */
|
||||
QSE_ASSERT (htrd->re.attr.content_length <= 0);
|
||||
QSE_ASSERT (!htrd->re.attr.content_length_set);
|
||||
|
||||
dechunk_start:
|
||||
htrd->fed.s.chunk.phase = GET_CHUNK_LEN;
|
||||
@ -1251,6 +1301,7 @@ int qse_htrd_feed (qse_htrd_t* htrd, const qse_mchar_t* req, qse_size_t len)
|
||||
{
|
||||
int n;
|
||||
|
||||
htrd->re.attr.hurried = 0;
|
||||
htrd->errnum = QSE_HTRD_ENOERR;
|
||||
|
||||
if (htrd->retype == QSE_HTRD_RETYPE_S)
|
||||
|
@ -61,13 +61,13 @@ void qse_htre_clear (qse_htre_t* re)
|
||||
}
|
||||
|
||||
int qse_htre_setstrfromcstr (
|
||||
qse_htre_t* re, qse_htob_t* str, const qse_mcstr_t* cstr)
|
||||
qse_htre_t* re, qse_mbs_t* str, const qse_mcstr_t* cstr)
|
||||
{
|
||||
return (qse_mbs_ncpy (str, cstr->ptr, cstr->len) == (qse_size_t)-1)? -1: 0;
|
||||
}
|
||||
|
||||
int qse_htre_setstrfromxstr (
|
||||
qse_htre_t* re, qse_htob_t* str, const qse_mxstr_t* xstr)
|
||||
qse_htre_t* re, qse_mbs_t* str, const qse_mxstr_t* xstr)
|
||||
{
|
||||
return (qse_mbs_ncpy (str, xstr->ptr, xstr->len) == (qse_size_t)-1)? -1: 0;
|
||||
}
|
||||
|
@ -667,7 +667,11 @@ struct task_cgi_t
|
||||
const qse_char_t* path;
|
||||
|
||||
qse_htrd_t* htrd;
|
||||
|
||||
qse_mbs_t* res;
|
||||
qse_mchar_t* res_ptr;
|
||||
qse_size_t res_left;
|
||||
|
||||
qse_pio_t* pio;
|
||||
|
||||
qse_mchar_t buf[MAX_SEND_SIZE];
|
||||
@ -701,6 +705,8 @@ static int cgi_htrd_handle_request (qse_htrd_t* htrd, qse_htre_t* req)
|
||||
task_cgi_t* cgi = xtn->cgi;
|
||||
const qse_mchar_t* status;
|
||||
|
||||
QSE_ASSERT (req->attr.hurried);
|
||||
|
||||
status = qse_htre_getheaderval (req, QSE_MT("Status"));
|
||||
if (status)
|
||||
{
|
||||
@ -726,7 +732,24 @@ static int cgi_htrd_handle_request (qse_htrd_t* htrd, qse_htre_t* req)
|
||||
if (qse_mbs_cat (cgi->res, buf) == (qse_size_t)-1) return -1;
|
||||
}
|
||||
|
||||
if (!req->attr.content_length_set)
|
||||
{
|
||||
if (qse_mbs_cat (cgi->res, QSE_MT("Transfer-Encoding: chunked\r\n")) == (qse_size_t)-1) return -1;
|
||||
}
|
||||
|
||||
if (qse_htre_walkheaders (req, walk_cgi_headers, cgi) <= -1) return -1;
|
||||
|
||||
if (qse_htre_getcontentlen(req) > 0)
|
||||
{
|
||||
if (!req->attr.content_length_set)
|
||||
{
|
||||
qse_mchar_t buf[64];
|
||||
snprintf (buf, QSE_COUNTOF(buf), QSE_MT("%lX\r\n"), (unsigned long)qse_htre_getcontentlen(req));
|
||||
if (qse_mbs_cat (cgi->res, buf) == (qse_size_t)-1) return -1;
|
||||
}
|
||||
if (qse_mbs_ncat (cgi->res, qse_htre_getcontentptr(req), qse_htre_getcontentlen(req)) == (qse_size_t)-1) return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -755,9 +778,10 @@ static void task_fini_cgi (
|
||||
if (cgi->pio) qse_pio_close (cgi->pio);
|
||||
if (cgi->res) qse_mbs_close (cgi->res);
|
||||
if (cgi->htrd) qse_htrd_close (cgi->htrd);
|
||||
qse_printf (QSE_T("task_fini_cgi\n"));
|
||||
}
|
||||
|
||||
static int task_main_cgi_3 (
|
||||
static int task_main_cgi_5 (
|
||||
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task)
|
||||
{
|
||||
task_cgi_t* cgi = (task_cgi_t*)task->ctx;
|
||||
@ -765,6 +789,76 @@ static int task_main_cgi_3 (
|
||||
|
||||
QSE_ASSERT (cgi->pio != QSE_NULL);
|
||||
|
||||
qse_printf (QSE_T("task_main_cgi_5\n"));
|
||||
{
|
||||
char buf[64];
|
||||
snprintf (buf, sizeof(buf), "%lX\r\n", cgi->buflen);
|
||||
send (client->handle.i, buf, strlen(buf), 0);
|
||||
}
|
||||
/* TODO: check if cgi outputs more than content-length if it is set... */
|
||||
n = send (client->handle.i, cgi->buf, cgi->buflen, 0);
|
||||
if (n <= -1)
|
||||
{
|
||||
/* can't return internal server error any more... */
|
||||
/* TODO: logging ... */
|
||||
return -1;
|
||||
}
|
||||
send (client->handle.i, "\r\n", 2, 0);
|
||||
|
||||
QSE_MEMCPY (&cgi->buf[0], &cgi->buf[n], cgi->buflen - n);
|
||||
cgi->buflen -= n;
|
||||
|
||||
if (cgi->buflen > 0) return 1;
|
||||
|
||||
send (client->handle.i, "0\r\n\r\n", 5, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int task_main_cgi_4 (
|
||||
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task)
|
||||
{
|
||||
task_cgi_t* cgi = (task_cgi_t*)task->ctx;
|
||||
qse_ssize_t n;
|
||||
|
||||
QSE_ASSERT (cgi->pio != QSE_NULL);
|
||||
qse_printf (QSE_T("task_main_cgi_4\n"));
|
||||
|
||||
/* TODO: check if cgi outputs more than content-length if it is set... */
|
||||
/* <- can i make it non-block?? or use select??? pio_tryread()? */
|
||||
n = qse_pio_read (
|
||||
cgi->pio,
|
||||
&cgi->buf[cgi->buflen],
|
||||
QSE_SIZEOF(cgi->buf) - cgi->buflen,
|
||||
QSE_PIO_OUT
|
||||
);
|
||||
if (n <= -1)
|
||||
{
|
||||
/* can't return internal server error any more... */
|
||||
/* TODO: logging ... */
|
||||
return -1;
|
||||
}
|
||||
if (n == 0)
|
||||
{
|
||||
if (cgi->buflen > 0)
|
||||
{
|
||||
task->main = task_main_cgi_4;
|
||||
return task_main_cgi_5 (httpd, client, task);
|
||||
}
|
||||
else
|
||||
{
|
||||
send (client->handle.i, "0\r\n\r\n", 5, 0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
cgi->buflen += n;
|
||||
|
||||
{
|
||||
char buf[64];
|
||||
snprintf (buf, sizeof(buf), "%lX\r\n", cgi->buflen);
|
||||
send (client->handle.i, buf, strlen(buf), 0);
|
||||
}
|
||||
|
||||
n = send (client->handle.i, cgi->buf, cgi->buflen, 0);
|
||||
if (n <= -1)
|
||||
{
|
||||
@ -772,11 +866,43 @@ static int task_main_cgi_3 (
|
||||
/* TODO: logging ... */
|
||||
return -1;
|
||||
}
|
||||
send (client->handle.i, "\r\n", 2, 0);
|
||||
|
||||
QSE_MEMCPY (&cgi->buf[0], &cgi->buf[n], cgi->buflen - n);
|
||||
cgi->buflen -= n;
|
||||
|
||||
return (cgi->buflen > 0)? 1: 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int task_main_cgi_3 (
|
||||
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task)
|
||||
{
|
||||
task_cgi_t* cgi = (task_cgi_t*)task->ctx;
|
||||
qse_ssize_t n;
|
||||
qse_size_t count;
|
||||
|
||||
qse_printf (QSE_T("task_main_cgi_3\n"));
|
||||
count = MAX_SEND_SIZE;
|
||||
if (count >= cgi->res_left) count = cgi->res_left;
|
||||
|
||||
n = send (
|
||||
client->handle.i,
|
||||
cgi->res_ptr,
|
||||
count,
|
||||
0
|
||||
);
|
||||
|
||||
if (n <= -1) return -1;
|
||||
|
||||
cgi->res_left -= n;
|
||||
if (cgi->res_left <= 0)
|
||||
{
|
||||
task->main = task_main_cgi_4;
|
||||
return task_main_cgi_4 (httpd, client, task);
|
||||
}
|
||||
|
||||
cgi->res_ptr += n;
|
||||
return 1; /* more work to do */
|
||||
}
|
||||
|
||||
static int task_main_cgi_2 (
|
||||
@ -802,12 +928,11 @@ static int task_main_cgi_2 (
|
||||
}
|
||||
if (n == 0)
|
||||
{
|
||||
if (cgi->buflen > 0)
|
||||
{
|
||||
task->main = task_main_cgi_3;
|
||||
return task_main_cgi_3 (httpd, client, task);
|
||||
}
|
||||
else return 0;
|
||||
/* end of output from cgi before it has seen a header.
|
||||
* the cgi script must be crooked. */
|
||||
/* TODO: logging */
|
||||
qse_pio_kill (cgi->pio);
|
||||
return -1;
|
||||
}
|
||||
|
||||
cgi->buflen += n;
|
||||
@ -818,20 +943,19 @@ static int task_main_cgi_2 (
|
||||
return -1;
|
||||
}
|
||||
|
||||
cgi->buflen = 0;
|
||||
|
||||
#if 0
|
||||
n = send (client->handle.i, cgi->buf, cgi->buflen, 0);
|
||||
if (n <= -1)
|
||||
if (QSE_MBS_LEN(cgi->res) > 0)
|
||||
{
|
||||
/* can't return internal server error any more... */
|
||||
/* TODO: logging ... */
|
||||
return -1;
|
||||
/* the headers and probably some contents are ready */
|
||||
cgi->res_ptr = QSE_MBS_PTR(cgi->res);
|
||||
cgi->res_left = QSE_MBS_LEN(cgi->res);
|
||||
|
||||
task->main = task_main_cgi_3;
|
||||
return task_main_cgi_3 (httpd, client, task);
|
||||
}
|
||||
|
||||
QSE_MEMCPY (&cgi->buf[0], &cgi->buf[n], cgi->buflen - n);
|
||||
cgi->buflen -= n;
|
||||
#endif
|
||||
|
||||
/* complete headers not seen yet. i need to be called again */
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -850,7 +974,12 @@ return 0;
|
||||
xtn = (cgi_htrd_xtn_t*) qse_htrd_getxtn (cgi->htrd);
|
||||
xtn->cgi = cgi;
|
||||
qse_htrd_setrecbs (cgi->htrd, &cgi_htrd_cbs);
|
||||
qse_htrd_setoption (cgi->htrd, QSE_HTRD_SKIPINITIALLINE | QSE_HTRD_REQUEST);
|
||||
qse_htrd_setoption (
|
||||
cgi->htrd,
|
||||
QSE_HTRD_SKIPINITIALLINE |
|
||||
QSE_HTRD_HURRIED |
|
||||
QSE_HTRD_REQUEST
|
||||
);
|
||||
|
||||
cgi->res = qse_mbs_open (httpd->mmgr, 0, 256);
|
||||
if (cgi->res == QSE_NULL)
|
||||
|
@ -61,11 +61,11 @@ qse_printf (QSE_T("content = [%.*S]\n"),
|
||||
|
||||
if (dot && qse_mbscmp (dot, QSE_MT(".cgi")) == 0)
|
||||
{
|
||||
qse_httpd_entaskcgi (httpd, client, QSE_NULL, QSE_T("/bin/ls -l /etc"));
|
||||
qse_httpd_entaskcgi (httpd, client, QSE_NULL, QSE_T("/tmp/test.cgi"));
|
||||
goto done;
|
||||
}
|
||||
|
||||
rangestr = qse_htre_gethdrval (req, "Range");
|
||||
rangestr = qse_htre_getheaderval (req, "Range");
|
||||
if (rangestr && qse_parsehttprange (rangestr, &range) <= -1)
|
||||
{
|
||||
#if 0
|
||||
|
Loading…
Reference in New Issue
Block a user