fixed of not setting cmgr properly in awk/std.c
added encoding options to the awk command. added directory functions to httpd
This commit is contained in:
parent
b903f8ebb5
commit
246dc4f5b7
@ -75,6 +75,8 @@ struct arg_t
|
|||||||
qse_htb_t* gvm; /* global variable map */
|
qse_htb_t* gvm; /* global variable map */
|
||||||
qse_char_t* fs; /* field separator */
|
qse_char_t* fs; /* field separator */
|
||||||
qse_char_t* call; /* function to call */
|
qse_char_t* call; /* function to call */
|
||||||
|
qse_cmgr_t* script_cmgr;
|
||||||
|
qse_cmgr_t* console_cmgr;
|
||||||
|
|
||||||
int opton;
|
int opton;
|
||||||
int optoff;
|
int optoff;
|
||||||
@ -429,13 +431,19 @@ static void print_usage (QSE_FILE* out, const qse_char_t* argv0)
|
|||||||
qse_fprintf (out, QSE_T(" -F/--field-separator string set a field separator(FS)\n"));
|
qse_fprintf (out, QSE_T(" -F/--field-separator string set a field separator(FS)\n"));
|
||||||
qse_fprintf (out, QSE_T(" -v/--assign var=value add a global variable with a value\n"));
|
qse_fprintf (out, QSE_T(" -v/--assign var=value add a global variable with a value\n"));
|
||||||
qse_fprintf (out, QSE_T(" -m/--memory-limit number limit the memory usage (bytes)\n"));
|
qse_fprintf (out, QSE_T(" -m/--memory-limit number limit the memory usage (bytes)\n"));
|
||||||
|
#if defined(QSE_CHAR_IS_WCHAR)
|
||||||
|
qse_fprintf (out, QSE_T(" --script-encoding string specify script encoding name\n"));
|
||||||
|
qse_fprintf (out, QSE_T(" --console-encoding string specify console encoding name\n"));
|
||||||
|
#endif
|
||||||
#if defined(QSE_BUILD_DEBUG)
|
#if defined(QSE_BUILD_DEBUG)
|
||||||
qse_fprintf (out, QSE_T(" -X number fail the number'th memory allocation\n"));
|
qse_fprintf (out, QSE_T(" -X number fail the number'th memory allocation\n"));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (j = 0; opttab[j].name != QSE_NULL; j++)
|
for (j = 0; opttab[j].name; j++)
|
||||||
{
|
{
|
||||||
qse_fprintf (out, QSE_T(" --%-18s on/off %s\n"), opttab[j].name, opttab[j].desc);
|
qse_fprintf (out,
|
||||||
|
QSE_T(" --%-18s on/off %s\n"),
|
||||||
|
opttab[j].name, opttab[j].desc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -468,6 +476,9 @@ static int comparg (int argc, qse_char_t* argv[], struct arg_t* arg)
|
|||||||
{ QSE_T(":assign"), QSE_T('v') },
|
{ QSE_T(":assign"), QSE_T('v') },
|
||||||
{ QSE_T(":memory-limit"), QSE_T('m') },
|
{ QSE_T(":memory-limit"), QSE_T('m') },
|
||||||
|
|
||||||
|
{ QSE_T(":script-encoding"), QSE_T('\0') },
|
||||||
|
{ QSE_T(":console-encoding"), QSE_T('\0') },
|
||||||
|
|
||||||
{ QSE_T("help"), QSE_T('h') },
|
{ QSE_T("help"), QSE_T('h') },
|
||||||
{ QSE_NULL, QSE_T('\0') }
|
{ QSE_NULL, QSE_T('\0') }
|
||||||
};
|
};
|
||||||
@ -621,7 +632,7 @@ static int comparg (int argc, qse_char_t* argv[], struct arg_t* arg)
|
|||||||
{
|
{
|
||||||
/* a long option with no corresponding short option */
|
/* a long option with no corresponding short option */
|
||||||
qse_size_t i;
|
qse_size_t i;
|
||||||
for (i = 0; opttab[i].name != QSE_NULL; i++)
|
for (i = 0; opttab[i].name; i++)
|
||||||
{
|
{
|
||||||
if (qse_strcmp (opt.lngopt, opttab[i].name) == 0)
|
if (qse_strcmp (opt.lngopt, opttab[i].name) == 0)
|
||||||
{
|
{
|
||||||
@ -637,6 +648,25 @@ static int comparg (int argc, qse_char_t* argv[], struct arg_t* arg)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (qse_strcmp(opt.lngopt, QSE_T("script-encoding")) == 0)
|
||||||
|
{
|
||||||
|
arg->script_cmgr = qse_getcmgrbyname (opt.arg);
|
||||||
|
if (arg->script_cmgr == QSE_NULL)
|
||||||
|
{
|
||||||
|
print_err (QSE_T("unknown script encoding - %s\n"), opt.arg);
|
||||||
|
goto oops;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (qse_strcmp(opt.lngopt, QSE_T("console-encoding")) == 0)
|
||||||
|
{
|
||||||
|
arg->console_cmgr = qse_getcmgrbyname (opt.arg);
|
||||||
|
if (arg->console_cmgr == QSE_NULL)
|
||||||
|
{
|
||||||
|
print_err (QSE_T("unknown console encoding - %s\n"), opt.arg);
|
||||||
|
goto oops;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -874,14 +904,14 @@ static int awk_main (int argc, qse_char_t* argv[])
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
psin.u.file.path = arg.isp.files[0];
|
psin.u.file.path = arg.isp.files[0];
|
||||||
psin.u.file.cmgr = QSE_NULL;
|
psin.u.file.cmgr = arg.script_cmgr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arg.osf != QSE_NULL)
|
if (arg.osf != QSE_NULL)
|
||||||
{
|
{
|
||||||
psout.type = QSE_AWK_PARSESTD_FILE;
|
psout.type = QSE_AWK_PARSESTD_FILE;
|
||||||
psout.u.file.path = arg.osf;
|
psout.u.file.path = arg.osf;
|
||||||
psout.u.file.cmgr = QSE_NULL;
|
psout.u.file.cmgr = arg.script_cmgr;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(QSE_BUILD_DEBUG)
|
#if defined(QSE_BUILD_DEBUG)
|
||||||
@ -954,7 +984,7 @@ static int awk_main (int argc, qse_char_t* argv[])
|
|||||||
|
|
||||||
rtx = qse_awk_rtx_openstd (
|
rtx = qse_awk_rtx_openstd (
|
||||||
awk, 0, QSE_T("qseawk"),
|
awk, 0, QSE_T("qseawk"),
|
||||||
(const qse_char_t*const*)arg.icf, QSE_NULL, QSE_NULL);
|
(const qse_char_t*const*)arg.icf, QSE_NULL, arg.console_cmgr);
|
||||||
if (rtx == QSE_NULL)
|
if (rtx == QSE_NULL)
|
||||||
{
|
{
|
||||||
print_awkerr (awk);
|
print_awkerr (awk);
|
||||||
|
11
qse/configure
vendored
11
qse/configure
vendored
@ -15518,6 +15518,17 @@ _ACEOF
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
|
for ac_func in fdopendir
|
||||||
|
do :
|
||||||
|
ac_fn_c_check_func "$LINENO" "fdopendir" "ac_cv_func_fdopendir"
|
||||||
|
if test "x$ac_cv_func_fdopendir" = x""yes; then :
|
||||||
|
cat >>confdefs.h <<_ACEOF
|
||||||
|
#define HAVE_FDOPENDIR 1
|
||||||
|
_ACEOF
|
||||||
|
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
|
||||||
OLDLIBS="$LIBS"
|
OLDLIBS="$LIBS"
|
||||||
LIBS="$LIBM $LIBS"
|
LIBS="$LIBM $LIBS"
|
||||||
|
@ -100,6 +100,7 @@ AC_CHECK_FUNCS([timegm timelocal])
|
|||||||
AC_CHECK_FUNCS([utime utimes])
|
AC_CHECK_FUNCS([utime utimes])
|
||||||
AC_CHECK_FUNCS([sysconf])
|
AC_CHECK_FUNCS([sysconf])
|
||||||
AC_CHECK_FUNCS([backtrace backtrace_symbols])
|
AC_CHECK_FUNCS([backtrace backtrace_symbols])
|
||||||
|
AC_CHECK_FUNCS([fdopendir])
|
||||||
|
|
||||||
OLDLIBS="$LIBS"
|
OLDLIBS="$LIBS"
|
||||||
LIBS="$LIBM $LIBS"
|
LIBS="$LIBM $LIBS"
|
||||||
|
@ -84,9 +84,13 @@ enum qse_tre_cflag_t
|
|||||||
|
|
||||||
enum qse_tre_eflag_t
|
enum qse_tre_eflag_t
|
||||||
{
|
{
|
||||||
QSE_TRE_NOTBOL = (1 << 0),
|
QSE_TRE_BACKTRACKING = (1 << 0),
|
||||||
QSE_TRE_NOTEOL = (1 << 1),
|
|
||||||
QSE_TRE_BACKTRACKING = (1 << 2)
|
/* you can use QSE_TRE_IGNORECASE for execution */
|
||||||
|
/*QSE_TRE_IGNORECASE = (1 << 1),*/
|
||||||
|
|
||||||
|
QSE_TRE_NOTBOL = (1 << 2),
|
||||||
|
QSE_TRE_NOTEOL = (1 << 3)
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct qse_tre_strsrc_t qse_tre_strsrc_t;
|
typedef struct qse_tre_strsrc_t qse_tre_strsrc_t;
|
||||||
|
@ -61,6 +61,9 @@
|
|||||||
/* Define to 1 if you have the `expl' function. */
|
/* Define to 1 if you have the `expl' function. */
|
||||||
#undef HAVE_EXPL
|
#undef HAVE_EXPL
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `fdopendir' function. */
|
||||||
|
#undef HAVE_FDOPENDIR
|
||||||
|
|
||||||
/* Define to 1 if you have the `fmod' function. */
|
/* Define to 1 if you have the `fmod' function. */
|
||||||
#undef HAVE_FMOD
|
#undef HAVE_FMOD
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ struct qse_htre_t
|
|||||||
int chunked;
|
int chunked;
|
||||||
int content_length_set;
|
int content_length_set;
|
||||||
qse_size_t content_length;
|
qse_size_t content_length;
|
||||||
int connection_close;
|
int keepalive;
|
||||||
int expect_continue;
|
int expect_continue;
|
||||||
|
|
||||||
/* indicates if the content has been filled */
|
/* indicates if the content has been filled */
|
||||||
|
@ -46,19 +46,13 @@ typedef enum qse_httpd_errnum_t qse_httpd_errnum_t;
|
|||||||
typedef struct qse_httpd_cbs_t qse_httpd_cbs_t;
|
typedef struct qse_httpd_cbs_t qse_httpd_cbs_t;
|
||||||
struct qse_httpd_cbs_t
|
struct qse_httpd_cbs_t
|
||||||
{
|
{
|
||||||
struct
|
|
||||||
{
|
|
||||||
const qse_mchar_t* (*getmimetype) (qse_httpd_t* httpd, const qse_mchar_t* path);
|
|
||||||
|
|
||||||
qse_ubi_t (*open) (qse_httpd_t* httpd, const qse_mchar_t* path);
|
|
||||||
void (*close) (qse_httpd_t* httpd, qse_ubi_t handle);
|
|
||||||
int (*getsize) (qse_httpd_t* httpd, qse_ubi_t handle, qse_foff_t* size);
|
|
||||||
} file;
|
|
||||||
|
|
||||||
int (*handle_request) (
|
int (*handle_request) (
|
||||||
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_htre_t* req);
|
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_htre_t* req);
|
||||||
int (*handle_expect_continue) (
|
int (*handle_expect_continue) (
|
||||||
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_htre_t* req);
|
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_htre_t* req);
|
||||||
|
|
||||||
|
const qse_mchar_t* (*getmimetype) (qse_httpd_t* httpd, const qse_mchar_t* path);
|
||||||
|
int (*listdir) (qse_httpd_t* httpd, const qse_mchar_t* path);
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct qse_httpd_task_t qse_httpd_task_t;
|
typedef struct qse_httpd_task_t qse_httpd_task_t;
|
||||||
@ -142,7 +136,7 @@ void qse_httpd_stop (
|
|||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
int qse_httpd_addlisteners (
|
int qse_httpd_addlistener (
|
||||||
qse_httpd_t* httpd,
|
qse_httpd_t* httpd,
|
||||||
const qse_char_t* uri
|
const qse_char_t* uri
|
||||||
);
|
);
|
||||||
@ -200,13 +194,21 @@ qse_httpd_task_t* qse_httpd_entaskfile (
|
|||||||
qse_foff_t size
|
qse_foff_t size
|
||||||
);
|
);
|
||||||
|
|
||||||
|
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_httpd_task_t* qse_httpd_entaskpath (
|
qse_httpd_task_t* qse_httpd_entaskpath (
|
||||||
qse_httpd_t* httpd,
|
qse_httpd_t* httpd,
|
||||||
qse_httpd_client_t* client,
|
qse_httpd_client_t* client,
|
||||||
const qse_httpd_task_t* pred,
|
const qse_httpd_task_t* pred,
|
||||||
const qse_mchar_t* name,
|
const qse_mchar_t* name,
|
||||||
const qse_http_range_t* range,
|
const qse_http_range_t* range,
|
||||||
const qse_http_version_t* version
|
const qse_http_version_t* version,
|
||||||
|
int keepalive
|
||||||
);
|
);
|
||||||
|
|
||||||
qse_httpd_task_t* qse_httpd_entaskcgi (
|
qse_httpd_task_t* qse_httpd_entaskcgi (
|
||||||
|
@ -1089,7 +1089,7 @@ int qse_awk_matchrex (
|
|||||||
x = qse_matchrex (
|
x = qse_matchrex (
|
||||||
awk->mmgr, awk->rex.depth.max.match,
|
awk->mmgr, awk->rex.depth.max.match,
|
||||||
code, option, str, substr, match, &err);
|
code, option, str, substr, match, &err);
|
||||||
if (x < 0) *errnum = QSE_AWK_REXERRTOERR(err);
|
if (x <= -1) *errnum = QSE_AWK_REXERRTOERR(err);
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -997,6 +997,7 @@ static int open_rio_console (qse_awk_rtx_t* rtx, qse_awk_rio_arg_t* riod)
|
|||||||
if (sio == QSE_NULL) return -1;
|
if (sio == QSE_NULL) return -1;
|
||||||
|
|
||||||
if (rxtn->c.cmgr) qse_sio_setcmgr (sio, rxtn->c.cmgr);
|
if (rxtn->c.cmgr) qse_sio_setcmgr (sio, rxtn->c.cmgr);
|
||||||
|
|
||||||
riod->handle = sio;
|
riod->handle = sio;
|
||||||
rxtn->c.in.count++;
|
rxtn->c.in.count++;
|
||||||
return 1;
|
return 1;
|
||||||
@ -1114,6 +1115,8 @@ static int open_rio_console (qse_awk_rtx_t* rtx, qse_awk_rio_arg_t* riod)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rxtn->c.cmgr) qse_sio_setcmgr (sio, rxtn->c.cmgr);
|
||||||
|
|
||||||
if (qse_awk_rtx_setfilename (
|
if (qse_awk_rtx_setfilename (
|
||||||
rtx, file, qse_strlen(file)) <= -1)
|
rtx, file, qse_strlen(file)) <= -1)
|
||||||
{
|
{
|
||||||
@ -1146,6 +1149,8 @@ static int open_rio_console (qse_awk_rtx_t* rtx, qse_awk_rio_arg_t* riod)
|
|||||||
);
|
);
|
||||||
if (sio == QSE_NULL) return -1;
|
if (sio == QSE_NULL) return -1;
|
||||||
|
|
||||||
|
if (rxtn->c.cmgr) qse_sio_setcmgr (sio, rxtn->c.cmgr);
|
||||||
|
|
||||||
riod->handle = sio;
|
riod->handle = sio;
|
||||||
rxtn->c.out.count++;
|
rxtn->c.out.count++;
|
||||||
return 1;
|
return 1;
|
||||||
@ -1178,6 +1183,8 @@ static int open_rio_console (qse_awk_rtx_t* rtx, qse_awk_rio_arg_t* riod)
|
|||||||
QSE_SIO_TRUNCATE | QSE_SIO_IGNOREMBWCERR);
|
QSE_SIO_TRUNCATE | QSE_SIO_IGNOREMBWCERR);
|
||||||
if (sio == QSE_NULL) return -1;
|
if (sio == QSE_NULL) return -1;
|
||||||
|
|
||||||
|
if (rxtn->c.cmgr) qse_sio_setcmgr (sio, rxtn->c.cmgr);
|
||||||
|
|
||||||
if (qse_awk_rtx_setofilename (
|
if (qse_awk_rtx_setofilename (
|
||||||
rtx, file, qse_strlen(file)) <= -1)
|
rtx, file, qse_strlen(file)) <= -1)
|
||||||
{
|
{
|
||||||
|
@ -58,6 +58,11 @@ void qse_setdflcmgr (qse_cmgr_t* cmgr)
|
|||||||
dfl_cmgr = (cmgr? cmgr: &builtin_cmgr[0]);
|
dfl_cmgr = (cmgr? cmgr: &builtin_cmgr[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* TODO:
|
||||||
|
qse_addcmgr (const qse_char_t* name, qse_cmgr_t* cmgr);
|
||||||
|
qse_delcmgr (const qse_char_t* name);
|
||||||
|
*/
|
||||||
|
|
||||||
qse_cmgr_t* qse_getcmgrbyname (const qse_char_t* name)
|
qse_cmgr_t* qse_getcmgrbyname (const qse_char_t* name)
|
||||||
{
|
{
|
||||||
if (name)
|
if (name)
|
||||||
@ -66,7 +71,7 @@ qse_cmgr_t* qse_getcmgrbyname (const qse_char_t* name)
|
|||||||
if (qse_strcmp(name, QSE_T("")) == 0) return dfl_cmgr;
|
if (qse_strcmp(name, QSE_T("")) == 0) return dfl_cmgr;
|
||||||
if (qse_strcmp(name, QSE_T("utf8")) == 0) return qse_utf8cmgr;
|
if (qse_strcmp(name, QSE_T("utf8")) == 0) return qse_utf8cmgr;
|
||||||
if (qse_strcmp(name, QSE_T("slmb")) == 0) return qse_slmbcmgr;
|
if (qse_strcmp(name, QSE_T("slmb")) == 0) return qse_slmbcmgr;
|
||||||
/* TODO: add more */
|
/* TODO: add more - handle those added with qse_addcmgr() */
|
||||||
}
|
}
|
||||||
return QSE_NULL;
|
return QSE_NULL;
|
||||||
}
|
}
|
||||||
|
@ -132,28 +132,22 @@ typedef struct tre_backtrack_struct
|
|||||||
s = tre_bt_mem_alloc(mem, sizeof(*s)); \
|
s = tre_bt_mem_alloc(mem, sizeof(*s)); \
|
||||||
if (!s) \
|
if (!s) \
|
||||||
{ \
|
{ \
|
||||||
tre_bt_mem_destroy(mem); \
|
tre_bt_mem_destroy(mem); \
|
||||||
if (tags) \
|
if (tags) xfree(_mmgr,tags); \
|
||||||
xfree(_mmgr,tags); \
|
if (pmatch) xfree(_mmgr,pmatch); \
|
||||||
if (pmatch) \
|
if (states_seen) xfree(_mmgr,states_seen); \
|
||||||
xfree(_mmgr,pmatch); \
|
|
||||||
if (states_seen) \
|
|
||||||
xfree(_mmgr,states_seen); \
|
|
||||||
return REG_ESPACE; \
|
return REG_ESPACE; \
|
||||||
} \
|
} \
|
||||||
s->prev = stack; \
|
s->prev = stack; \
|
||||||
s->next = NULL; \
|
s->next = NULL; \
|
||||||
s->item.tags = tre_bt_mem_alloc(mem, \
|
s->item.tags = tre_bt_mem_alloc(mem, \
|
||||||
sizeof(*tags) * tnfa->num_tags); \
|
sizeof(*tags) * tnfa->num_tags); \
|
||||||
if (!s->item.tags) \
|
if (!s->item.tags) \
|
||||||
{ \
|
{ \
|
||||||
tre_bt_mem_destroy(mem); \
|
tre_bt_mem_destroy(mem); \
|
||||||
if (tags) \
|
if (tags) xfree(_mmgr,tags); \
|
||||||
xfree(_mmgr,tags); \
|
if (pmatch) xfree(_mmgr,pmatch); \
|
||||||
if (pmatch) \
|
if (states_seen) xfree(_mmgr,states_seen); \
|
||||||
xfree(_mmgr,pmatch); \
|
|
||||||
if (states_seen) \
|
|
||||||
xfree(_mmgr,states_seen); \
|
|
||||||
return REG_ESPACE; \
|
return REG_ESPACE; \
|
||||||
} \
|
} \
|
||||||
stack->next = s; \
|
stack->next = s; \
|
||||||
@ -539,8 +533,8 @@ retry:
|
|||||||
trans_i->code_min, trans_i->code_max,
|
trans_i->code_min, trans_i->code_max,
|
||||||
trans_i->code_min, trans_i->code_max,
|
trans_i->code_min, trans_i->code_max,
|
||||||
trans_i->assertions, trans_i->state_id));
|
trans_i->assertions, trans_i->state_id));
|
||||||
if (trans_i->code_min <= (tre_cint_t)prev_c
|
if (trans_i->code_min <= (tre_cint_t)prev_c &&
|
||||||
&& trans_i->code_max >= (tre_cint_t)prev_c)
|
trans_i->code_max >= (tre_cint_t)prev_c)
|
||||||
{
|
{
|
||||||
if (trans_i->assertions
|
if (trans_i->assertions
|
||||||
&& (CHECK_ASSERTIONS(trans_i->assertions)
|
&& (CHECK_ASSERTIONS(trans_i->assertions)
|
||||||
|
@ -409,7 +409,7 @@ tre_tnfa_run_parallel(qse_mmgr_t* mmgr, const tre_tnfa_t *tnfa, const void *stri
|
|||||||
{
|
{
|
||||||
/* Does this transition match the input symbol? */
|
/* Does this transition match the input symbol? */
|
||||||
if (trans_i->code_min <= (tre_cint_t)prev_c &&
|
if (trans_i->code_min <= (tre_cint_t)prev_c &&
|
||||||
trans_i->code_max >= (tre_cint_t)prev_c)
|
trans_i->code_max >= (tre_cint_t)prev_c)
|
||||||
{
|
{
|
||||||
if (trans_i->assertions
|
if (trans_i->assertions
|
||||||
&& (CHECK_ASSERTIONS(trans_i->assertions)
|
&& (CHECK_ASSERTIONS(trans_i->assertions)
|
||||||
|
@ -275,11 +275,11 @@ static qse_mchar_t* parse_initial_line (
|
|||||||
|
|
||||||
if (qse_htre_setsmessagefromcstr (&htrd->re, &tmp) <= -1) goto outofmem;
|
if (qse_htre_setsmessagefromcstr (&htrd->re, &tmp) <= -1) goto outofmem;
|
||||||
|
|
||||||
/* adjust Connection: close for HTTP 1.0 or eariler */
|
/* adjust Connection: Keep-Alive for HTTP 1.1 or later */
|
||||||
if (htrd->re.version.major < 1 ||
|
if (htrd->re.version.major > 1 ||
|
||||||
(htrd->re.version.major == 1 && htrd->re.version.minor == 0))
|
(htrd->re.version.major == 1 && htrd->re.version.minor >= 1))
|
||||||
{
|
{
|
||||||
htrd->re.attr.connection_close = 1;
|
htrd->re.attr.keepalive = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -379,11 +379,11 @@ static qse_mchar_t* parse_initial_line (
|
|||||||
/* skip trailing spaces on the line */
|
/* skip trailing spaces on the line */
|
||||||
while (is_space_octet(*p)) p++;
|
while (is_space_octet(*p)) p++;
|
||||||
|
|
||||||
/* adjust Connection: close for HTTP 1.0 or eariler */
|
/* adjust Connection: Keep-Alive for HTTP 1.1 or later */
|
||||||
if (htrd->re.version.major < 1 ||
|
if (htrd->re.version.major > 1 ||
|
||||||
(htrd->re.version.major == 1 && htrd->re.version.minor == 0))
|
(htrd->re.version.major == 1 && htrd->re.version.minor >= 1))
|
||||||
{
|
{
|
||||||
htrd->re.attr.connection_close = 1;
|
htrd->re.attr.keepalive = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -427,58 +427,46 @@ void qse_htrd_setrecbs (qse_htrd_t* htrd, const qse_htrd_recbs_t* recbs)
|
|||||||
htrd->recbs = recbs;
|
htrd->recbs = recbs;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define octet_tolower(c) (((c) >= 'A' && (c) <= 'Z') ? ((c) | 0x20) : (c))
|
static int capture_connection (qse_htrd_t* htrd, qse_htb_pair_t* pair)
|
||||||
#define octet_toupper(c) (((c) >= 'a' && (c) <= 'z') ? ((c) & ~0x20) : (c))
|
|
||||||
|
|
||||||
static QSE_INLINE int compare_octets (
|
|
||||||
const qse_mchar_t* s1, qse_size_t len1,
|
|
||||||
const qse_mchar_t* s2, qse_size_t len2)
|
|
||||||
{
|
|
||||||
qse_char_t c1, c2;
|
|
||||||
const qse_mchar_t* end1 = s1 + len1;
|
|
||||||
const qse_mchar_t* end2 = s2 + len2;
|
|
||||||
|
|
||||||
while (s1 < end1)
|
|
||||||
{
|
|
||||||
c1 = octet_toupper (*s1);
|
|
||||||
if (s2 < end2)
|
|
||||||
{
|
|
||||||
c2 = octet_toupper (*s2);
|
|
||||||
if (c1 > c2) return 1;
|
|
||||||
if (c1 < c2) return -1;
|
|
||||||
}
|
|
||||||
else return 1;
|
|
||||||
s1++; s2++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (s2 < end2)? -1: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static QSE_INLINE int capture_connection (
|
|
||||||
qse_htrd_t* htrd, qse_htb_pair_t* pair)
|
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
n = compare_octets (QSE_HTB_VPTR(pair), QSE_HTB_VLEN(pair), "close", 5);
|
n = qse_mbsxncasecmp (
|
||||||
|
QSE_HTB_VPTR(pair), QSE_HTB_VLEN(pair),
|
||||||
|
"close", 5);
|
||||||
if (n == 0)
|
if (n == 0)
|
||||||
{
|
{
|
||||||
htrd->re.attr.connection_close = 1;
|
htrd->re.attr.keepalive = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
n = compare_octets (QSE_HTB_VPTR(pair), QSE_HTB_VLEN(pair), "Keep-Alive", 10);
|
n = qse_mbsxncasecmp (
|
||||||
|
QSE_HTB_VPTR(pair), QSE_HTB_VLEN(pair),
|
||||||
|
"Keep-Alive", 10);
|
||||||
if (n == 0)
|
if (n == 0)
|
||||||
{
|
{
|
||||||
htrd->re.attr.connection_close = 0;
|
htrd->re.attr.keepalive = 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* don't care about other values */
|
/* Basically i don't care about other values.
|
||||||
|
* but for HTTP 1.0, other values will set connection to 'close'.
|
||||||
|
*
|
||||||
|
* Other values include even Keep-Alive specified multiple times.
|
||||||
|
* Connection: Keep-Alive
|
||||||
|
* Connection: Keep-Alive
|
||||||
|
* For the second Keep-Alive, this function sees 'Keep-Alive,Keep-Alive'
|
||||||
|
* That's because values of the same keys are concatenated.
|
||||||
|
*/
|
||||||
|
if (htrd->re.version.major < 1 ||
|
||||||
|
(htrd->re.version.major == 1 && htrd->re.version.minor <= 0))
|
||||||
|
{
|
||||||
|
htrd->re.attr.keepalive = 0;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static QSE_INLINE int capture_content_length (
|
static int capture_content_length (qse_htrd_t* htrd, qse_htb_pair_t* pair)
|
||||||
qse_htrd_t* htrd, qse_htb_pair_t* pair)
|
|
||||||
{
|
{
|
||||||
qse_size_t len = 0, off = 0, tmp;
|
qse_size_t len = 0, off = 0, tmp;
|
||||||
const qse_mchar_t* ptr = QSE_HTB_VPTR(pair);
|
const qse_mchar_t* ptr = QSE_HTB_VPTR(pair);
|
||||||
@ -525,12 +513,12 @@ static QSE_INLINE int capture_content_length (
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static QSE_INLINE int capture_expect (
|
static int capture_expect (qse_htrd_t* htrd, qse_htb_pair_t* pair)
|
||||||
qse_htrd_t* htrd, qse_htb_pair_t* pair)
|
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
n = compare_octets (QSE_HTB_VPTR(pair), QSE_HTB_VLEN(pair), "100-continue", 12);
|
n = qse_mbsxncasecmp (
|
||||||
|
QSE_HTB_VPTR(pair), QSE_HTB_VLEN(pair), "100-continue", 12);
|
||||||
if (n == 0)
|
if (n == 0)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -542,12 +530,12 @@ static QSE_INLINE int capture_expect (
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static QSE_INLINE int capture_transfer_encoding (
|
static int capture_transfer_encoding (qse_htrd_t* htrd, qse_htb_pair_t* pair)
|
||||||
qse_htrd_t* htrd, qse_htb_pair_t* pair)
|
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
n = compare_octets (QSE_HTB_VPTR(pair), QSE_HTB_VLEN(pair), "chunked", 7);
|
n = qse_mbsxncasecmp (
|
||||||
|
QSE_HTB_VPTR(pair), QSE_HTB_VLEN(pair), "chunked", 7);
|
||||||
if (n == 0)
|
if (n == 0)
|
||||||
{
|
{
|
||||||
/* if (htrd->re.attr.content_length > 0) */
|
/* if (htrd->re.attr.content_length > 0) */
|
||||||
@ -591,7 +579,7 @@ static QSE_INLINE int capture_key_header (
|
|||||||
{
|
{
|
||||||
mid = base + count / 2;
|
mid = base + count / 2;
|
||||||
|
|
||||||
n = compare_octets (
|
n = qse_mbsxncasecmp (
|
||||||
QSE_HTB_KPTR(pair), QSE_HTB_KLEN(pair),
|
QSE_HTB_KPTR(pair), QSE_HTB_KLEN(pair),
|
||||||
hdrtab[mid].ptr, hdrtab[mid].len
|
hdrtab[mid].ptr, hdrtab[mid].len
|
||||||
);
|
);
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include "../cmn/mem.h"
|
#include "../cmn/mem.h"
|
||||||
#include <qse/cmn/chr.h>
|
#include <qse/cmn/chr.h>
|
||||||
#include <qse/cmn/str.h>
|
#include <qse/cmn/str.h>
|
||||||
|
#include <qse/cmn/mbwc.h>
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@ -451,7 +452,8 @@ static void delete_from_client_array (qse_httpd_t* httpd, int fd)
|
|||||||
{
|
{
|
||||||
purge_tasks_locked (httpd, &array->data[fd]);
|
purge_tasks_locked (httpd, &array->data[fd]);
|
||||||
#if defined(HAVE_PTHREAD)
|
#if defined(HAVE_PTHREAD)
|
||||||
if (httpd->threaded) pthread_mutex_destroy (&array->data[fd].task.mutex);
|
if (httpd->threaded)
|
||||||
|
pthread_mutex_destroy (&array->data[fd].task.mutex);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
qse_htrd_close (array->data[fd].htrd);
|
qse_htrd_close (array->data[fd].htrd);
|
||||||
@ -610,7 +612,6 @@ httpd->cbs.on_error (httpd, l).... */
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int make_fd_set_from_client_array (
|
static int make_fd_set_from_client_array (
|
||||||
qse_httpd_t* httpd, fd_set* r, fd_set* w)
|
qse_httpd_t* httpd, fd_set* r, fd_set* w)
|
||||||
{
|
{
|
||||||
@ -955,136 +956,123 @@ static void free_listener_list (qse_httpd_t* httpd, listener_t* l)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static listener_t* parse_listener_string (
|
static listener_t* parse_listener_uri (
|
||||||
qse_httpd_t* httpd, const qse_char_t* str, listener_t** ltail)
|
qse_httpd_t* httpd, const qse_char_t* uri)
|
||||||
{
|
{
|
||||||
const qse_char_t* p = str;
|
const qse_char_t* p = uri;
|
||||||
listener_t* lhead = QSE_NULL, * ltmp = QSE_NULL, * lend = QSE_NULL;
|
listener_t* ltmp = QSE_NULL;
|
||||||
|
qse_cstr_t tmp;
|
||||||
|
qse_mchar_t* host;
|
||||||
|
int x;
|
||||||
|
|
||||||
do
|
ltmp = qse_httpd_allocmem (httpd, QSE_SIZEOF(*ltmp));
|
||||||
|
if (ltmp == QSE_NULL) goto oops; /* alloc set error number. so goto oops */
|
||||||
|
|
||||||
|
QSE_MEMSET (ltmp, 0, QSE_SIZEOF(*ltmp));
|
||||||
|
ltmp->handle = -1;
|
||||||
|
|
||||||
|
/* check the protocol part */
|
||||||
|
tmp.ptr = p;
|
||||||
|
while (*p != QSE_T(':'))
|
||||||
{
|
{
|
||||||
qse_cstr_t tmp;
|
if (*p == QSE_T('\0')) goto oops_einval;
|
||||||
qse_mchar_t* host;
|
p++;
|
||||||
int x;
|
}
|
||||||
|
tmp.len = p - tmp.ptr;
|
||||||
|
if (qse_strxcmp (tmp.ptr, tmp.len, QSE_T("http")) == 0)
|
||||||
|
{
|
||||||
|
ltmp->secure = 0;
|
||||||
|
ltmp->port = DEFAULT_PORT;
|
||||||
|
}
|
||||||
|
else if (qse_strxcmp (tmp.ptr, tmp.len, QSE_T("https")) == 0)
|
||||||
|
{
|
||||||
|
ltmp->secure = 1;
|
||||||
|
ltmp->port = DEFAULT_SECURE_PORT;
|
||||||
|
}
|
||||||
|
else goto oops;
|
||||||
|
|
||||||
/* skip spaces */
|
p++; /* skip : */
|
||||||
while (QSE_ISSPACE(*p)) p++;
|
if (*p != QSE_T('/')) goto oops_einval;
|
||||||
|
p++; /* skip / */
|
||||||
|
if (*p != QSE_T('/')) goto oops_einval;
|
||||||
|
p++; /* skip / */
|
||||||
|
|
||||||
ltmp = qse_httpd_allocmem (httpd, QSE_SIZEOF(*ltmp));
|
#ifdef AF_INET6
|
||||||
if (ltmp == QSE_NULL) goto oops; /* alloc set error number. so goto oops */
|
if (*p == QSE_T('['))
|
||||||
|
{
|
||||||
|
/* IPv6 address */
|
||||||
|
p++; /* skip [ */
|
||||||
|
|
||||||
QSE_MEMSET (ltmp, 0, QSE_SIZEOF(*ltmp));
|
for (tmp.ptr = p; *p != QSE_T(']'); p++)
|
||||||
ltmp->handle = -1;
|
|
||||||
|
|
||||||
/* check the protocol part */
|
|
||||||
tmp.ptr = p;
|
|
||||||
while (*p != QSE_T(':'))
|
|
||||||
{
|
{
|
||||||
if (*p == QSE_T('\0')) goto oops_einval;
|
if (*p == QSE_T('\0')) goto oops_einval;
|
||||||
p++;
|
}
|
||||||
|
|
||||||
|
tmp.len = p - tmp.ptr;
|
||||||
|
ltmp->family = AF_INET6;
|
||||||
|
|
||||||
|
p++; /* skip ] */
|
||||||
|
if (*p != QSE_T(':') && *p != QSE_T('\0')) goto oops_einval;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
/* host name or IPv4 address */
|
||||||
|
for (tmp.ptr = p; ; p++)
|
||||||
|
{
|
||||||
|
if (*p == QSE_T(':') || *p == QSE_T('\0')) break;
|
||||||
}
|
}
|
||||||
tmp.len = p - tmp.ptr;
|
tmp.len = p - tmp.ptr;
|
||||||
if (qse_strxcmp (tmp.ptr, tmp.len, QSE_T("http")) == 0)
|
ltmp->family = AF_INET;
|
||||||
{
|
|
||||||
ltmp->secure = 0;
|
|
||||||
ltmp->port = DEFAULT_PORT;
|
|
||||||
}
|
|
||||||
else if (qse_strxcmp (tmp.ptr, tmp.len, QSE_T("https")) == 0)
|
|
||||||
{
|
|
||||||
ltmp->secure = 1;
|
|
||||||
ltmp->port = DEFAULT_SECURE_PORT;
|
|
||||||
}
|
|
||||||
else goto oops;
|
|
||||||
|
|
||||||
p++; /* skip : */
|
|
||||||
if (*p != QSE_T('/')) goto oops_einval;
|
|
||||||
p++; /* skip / */
|
|
||||||
if (*p != QSE_T('/')) goto oops_einval;
|
|
||||||
p++; /* skip / */
|
|
||||||
|
|
||||||
#ifdef AF_INET6
|
#ifdef AF_INET6
|
||||||
if (*p == QSE_T('['))
|
|
||||||
{
|
|
||||||
/* IPv6 address */
|
|
||||||
p++; /* skip [ */
|
|
||||||
tmp.ptr = p;
|
|
||||||
while (*p != QSE_T(']'))
|
|
||||||
{
|
|
||||||
if (*p == QSE_T('\0')) goto oops_einval;
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
tmp.len = p - tmp.ptr;
|
|
||||||
|
|
||||||
ltmp->family = AF_INET6;
|
|
||||||
p++; /* skip ] */
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
#endif
|
|
||||||
/* host name or IPv4 address */
|
|
||||||
tmp.ptr = p;
|
|
||||||
while (!QSE_ISSPACE(*p) &&
|
|
||||||
*p != QSE_T(':') &&
|
|
||||||
*p != QSE_T('\0')) p++;
|
|
||||||
tmp.len = p - tmp.ptr;
|
|
||||||
ltmp->family = AF_INET;
|
|
||||||
#ifdef AF_INET6
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ltmp->host = qse_strxdup (tmp.ptr, tmp.len, httpd->mmgr);
|
|
||||||
if (ltmp->host == QSE_NULL) goto oops_enomem;
|
|
||||||
|
|
||||||
#ifdef QSE_CHAR_IS_WCHAR
|
|
||||||
host = qse_wcstombsdup (ltmp->host, httpd->mmgr);
|
|
||||||
if (host == QSE_NULL) goto oops_enomem;
|
|
||||||
#else
|
|
||||||
host = ltmp->host;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
x = inet_pton (ltmp->family, host, <mp->addr);
|
|
||||||
#ifdef QSE_CHAR_IS_WCHAR
|
|
||||||
qse_httpd_freemem (httpd, host);
|
|
||||||
#endif
|
|
||||||
if (x != 1)
|
|
||||||
{
|
|
||||||
/* TODO: need to support host names???
|
|
||||||
if (getaddrinfo... )....
|
|
||||||
or CALL a user callback for name resolution?
|
|
||||||
if (httpd->cbs.resolve_hostname (httpd, ltmp->host) <= -1) must call this with host before freeing it up????
|
|
||||||
*/
|
|
||||||
goto oops_einval;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*p == QSE_T(':'))
|
|
||||||
{
|
|
||||||
unsigned int port = 0;
|
|
||||||
/* port number */
|
|
||||||
p++;
|
|
||||||
|
|
||||||
tmp.ptr = p;
|
|
||||||
while (QSE_ISDIGIT(*p))
|
|
||||||
{
|
|
||||||
port = port * 10 + (*p - QSE_T('0'));
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
tmp.len = p - tmp.ptr;
|
|
||||||
if (tmp.len > 5 || port > QSE_TYPE_MAX(unsigned short)) goto oops_einval;
|
|
||||||
ltmp->port = port;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* skip spaces */
|
|
||||||
while (QSE_ISSPACE(*p)) p++;
|
|
||||||
|
|
||||||
if (lhead == QSE_NULL) lend = ltmp;
|
|
||||||
ltmp->next = lhead;
|
|
||||||
lhead = ltmp;
|
|
||||||
ltmp = QSE_NULL;
|
|
||||||
}
|
}
|
||||||
while (*p != QSE_T('\0'));
|
#endif
|
||||||
|
|
||||||
if (ltail) *ltail = lend;
|
ltmp->host = qse_strxdup (tmp.ptr, tmp.len, httpd->mmgr);
|
||||||
return lhead;
|
if (ltmp->host == QSE_NULL) goto oops_enomem;
|
||||||
|
|
||||||
|
#ifdef QSE_CHAR_IS_WCHAR
|
||||||
|
host = qse_wcstombsdup (ltmp->host, httpd->mmgr);
|
||||||
|
if (host == QSE_NULL) goto oops_enomem;
|
||||||
|
#else
|
||||||
|
host = ltmp->host;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
x = inet_pton (ltmp->family, host, <mp->addr);
|
||||||
|
#ifdef QSE_CHAR_IS_WCHAR
|
||||||
|
qse_httpd_freemem (httpd, host);
|
||||||
|
#endif
|
||||||
|
if (x != 1)
|
||||||
|
{
|
||||||
|
/* TODO: need to support host names???
|
||||||
|
if (getaddrinfo... )....
|
||||||
|
or CALL a user callback for name resolution?
|
||||||
|
if (httpd->cbs.resolve_hostname (httpd, ltmp->host) <= -1) must call this with host before freeing it up????
|
||||||
|
*/
|
||||||
|
goto oops_einval;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*p == QSE_T(':'))
|
||||||
|
{
|
||||||
|
unsigned int port = 0;
|
||||||
|
|
||||||
|
/* port number */
|
||||||
|
p++;
|
||||||
|
|
||||||
|
for (tmp.ptr = p; QSE_ISDIGIT(*p); p++)
|
||||||
|
port = port * 10 + (*p - QSE_T('0'));
|
||||||
|
|
||||||
|
tmp.len = p - tmp.ptr;
|
||||||
|
if (tmp.len <= 0 ||
|
||||||
|
tmp.len >= 6 ||
|
||||||
|
port > QSE_TYPE_MAX(unsigned short)) goto oops_einval;
|
||||||
|
ltmp->port = port;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* skip spaces */
|
||||||
|
while (QSE_ISSPACE(*p)) p++;
|
||||||
|
|
||||||
|
return ltmp;
|
||||||
|
|
||||||
oops_einval:
|
oops_einval:
|
||||||
httpd->errnum = QSE_HTTPD_EINVAL;
|
httpd->errnum = QSE_HTTPD_EINVAL;
|
||||||
@ -1096,19 +1084,18 @@ oops_enomem:
|
|||||||
|
|
||||||
oops:
|
oops:
|
||||||
if (ltmp) free_listener (httpd, ltmp);
|
if (ltmp) free_listener (httpd, ltmp);
|
||||||
if (lhead) free_listener_list (httpd, lhead);
|
|
||||||
return QSE_NULL;
|
return QSE_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int add_listeners (qse_httpd_t* httpd, const qse_char_t* uri)
|
static int add_listener (qse_httpd_t* httpd, const qse_char_t* uri)
|
||||||
{
|
{
|
||||||
listener_t* lh, * lt;
|
listener_t* lsn;
|
||||||
|
|
||||||
lh = parse_listener_string (httpd, uri, <);
|
lsn = parse_listener_uri (httpd, uri);
|
||||||
if (lh == QSE_NULL) return -1;
|
if (lsn == QSE_NULL) return -1;
|
||||||
|
|
||||||
lt->next = httpd->listener.list;
|
lsn->next = httpd->listener.list;
|
||||||
httpd->listener.list = lh;
|
httpd->listener.list = lsn;
|
||||||
/*
|
/*
|
||||||
TODO: mutex protection...
|
TODO: mutex protection...
|
||||||
if in the activated state...
|
if in the activated state...
|
||||||
@ -1124,7 +1111,7 @@ static int delete_listeners (qse_httpd_t* httpd, const qse_char_t* uri)
|
|||||||
{
|
{
|
||||||
listener_t* lh, * li, * hl;
|
listener_t* lh, * li, * hl;
|
||||||
|
|
||||||
lh = parse_listener_string (httpd, uri, QSE_NULL);
|
lh = parse_listener_uri (httpd, uri, QSE_NULL);
|
||||||
if (lh == QSE_NULL) return -1;
|
if (lh == QSE_NULL) return -1;
|
||||||
|
|
||||||
for (li = lh; li; li = li->next)
|
for (li = lh; li; li = li->next)
|
||||||
@ -1142,21 +1129,21 @@ static int delete_listeners (qse_httpd_t* httpd, const qse_char_t* uri)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int qse_httpd_addlisteners (qse_httpd_t* httpd, const qse_char_t* uri)
|
int qse_httpd_addlistener (qse_httpd_t* httpd, const qse_char_t* uri)
|
||||||
{
|
{
|
||||||
#if defined(HAVE_PTHREAD)
|
#if defined(HAVE_PTHREAD)
|
||||||
int n;
|
int n;
|
||||||
pthread_mutex_lock (&httpd->listener.mutex);
|
pthread_mutex_lock (&httpd->listener.mutex);
|
||||||
n = add_listeners (httpd, uri);
|
n = add_listener (httpd, uri);
|
||||||
pthread_mutex_unlock (&httpd->listener.mutex);
|
pthread_mutex_unlock (&httpd->listener.mutex);
|
||||||
return n;
|
return n;
|
||||||
#else
|
#else
|
||||||
return add_listeners (httpd, uri);
|
return add_listener (httpd, uri);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
int qse_httpd_dellisteners (qse_httpd_t* httpd, const qse_char_t* uri)
|
int qse_httpd_dellistener (qse_httpd_t* httpd, const qse_char_t* uri)
|
||||||
{
|
{
|
||||||
int n;
|
int n;
|
||||||
pthread_mutex_lock (&httpd->listener.mutex);
|
pthread_mutex_lock (&httpd->listener.mutex);
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
|
||||||
#define MAX_SEND_SIZE 4096
|
#define MAX_SEND_SIZE 4096
|
||||||
|
|
||||||
@ -112,7 +113,6 @@ static qse_ssize_t xsendfile (
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
static int task_main_disconnect (
|
static int task_main_disconnect (
|
||||||
@ -496,6 +496,125 @@ qse_httpd_task_t* qse_httpd_entaskfile (
|
|||||||
return qse_httpd_entask (httpd, client, pred, &task, QSE_SIZEOF(data));
|
return qse_httpd_entask (httpd, client, pred, &task, QSE_SIZEOF(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
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];
|
||||||
|
qse_size_t buflen;
|
||||||
|
qse_size_t bufsent;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
static int task_init_dir (
|
||||||
|
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task)
|
||||||
|
{
|
||||||
|
task_dir_t* xtn = qse_httpd_gettaskxtn (httpd, task);
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
closedir (ctx->handle.ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int task_main_dir (
|
||||||
|
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;
|
||||||
|
char buf[100];
|
||||||
|
|
||||||
|
if (ctx->bufsent < ctx->buflen) goto send_dirlist;
|
||||||
|
|
||||||
|
ctx->buflen = 0;
|
||||||
|
ctx->bufsent = 0;
|
||||||
|
|
||||||
|
if (ctx->count == 0)
|
||||||
|
{
|
||||||
|
ctx->buflen += snprintf (
|
||||||
|
&ctx->buf[ctx->buflen],
|
||||||
|
QSE_COUNTOF(ctx->buf) - ctx->buflen,
|
||||||
|
"<html><head><title>Directory Listing</title></head><body>index of xxxx<ul>"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
struct dirent* ent;
|
||||||
|
|
||||||
|
ent = readdir (ctx->handle.ptr);
|
||||||
|
if (ent == QSE_NULL)
|
||||||
|
{
|
||||||
|
// TODO: check if errno has changed from before readdir().
|
||||||
|
// and return -1 if so.
|
||||||
|
ctx->eod = 1;
|
||||||
|
ctx->buflen += snprintf (
|
||||||
|
&ctx->buf[ctx->buflen],
|
||||||
|
QSE_COUNTOF(ctx->buf) - ctx->buflen,
|
||||||
|
"</ul></body></html>");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// TODO: check if snprintf has truncated....
|
||||||
|
ctx->buflen += snprintf (
|
||||||
|
&ctx->buf[ctx->buflen],
|
||||||
|
QSE_COUNTOF(ctx->buf) - ctx->buflen,
|
||||||
|
"<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->count++;
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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_httpd_task_t task;
|
||||||
|
|
||||||
|
QSE_MEMSET (&task, 0, QSE_SIZEOF(task));
|
||||||
|
task.init = task_init_dir;
|
||||||
|
task.main = task_main_dir;
|
||||||
|
task.fini = task_fini_dir;
|
||||||
|
task.ctx = &handle;
|
||||||
|
|
||||||
|
return qse_httpd_entask (httpd, client, pred, &task, QSE_SIZEOF(task_dir_t));
|
||||||
|
}
|
||||||
|
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@ -508,6 +627,7 @@ struct task_path_t
|
|||||||
const qse_mchar_t* name;
|
const qse_mchar_t* name;
|
||||||
qse_http_range_t range;
|
qse_http_range_t range;
|
||||||
qse_http_version_t version;
|
qse_http_version_t version;
|
||||||
|
int keepalive;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int task_init_path (
|
static int task_init_path (
|
||||||
@ -521,6 +641,46 @@ static int task_init_path (
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static qse_httpd_task_t* entask_path_error (
|
||||||
|
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task, int code)
|
||||||
|
{
|
||||||
|
task_path_t* data = (task_path_t*)task->ctx;
|
||||||
|
|
||||||
|
const qse_mchar_t* smsg;
|
||||||
|
const qse_mchar_t* lmsg;
|
||||||
|
|
||||||
|
switch (code)
|
||||||
|
{
|
||||||
|
case 403:
|
||||||
|
smsg = QSE_MT("Forbidden");
|
||||||
|
lmsg = QSE_MT("<html><head><title>Directory Listing Forbidden</title></head><body><b>DIRECTORY LISTING FORBIDDEN<b></body></html>");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 404:
|
||||||
|
smsg = QSE_MT("Not Found");
|
||||||
|
lmsg = QSE_MT("<html><head><title>Not Found</title></head><body><b>REQUESTED PATH NOT FOUND<b></body></html>");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 416:
|
||||||
|
smsg = QSE_MT("Requested Range Not Satisfiable");
|
||||||
|
lmsg = QSE_MT("<html><head><title>Requested Range Not Satsfiable</title></head><body><b>REQUESTED RANGE NOT SATISFIABLE<b></body></html>");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
smsg = QSE_MT("Unknown");
|
||||||
|
lmsg = QSE_MT("<html><head><title>Unknown Error</title></head><body><b>UNKNOWN ERROR<b></body></html>");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
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"),
|
||||||
|
data->version.major, data->version.minor, code, smsg,
|
||||||
|
(data->keepalive? QSE_MT("Keep-Alive"): QSE_MT("Close")),
|
||||||
|
(int)qse_mbslen(lmsg) + 4, lmsg
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
static int task_main_path (
|
static int task_main_path (
|
||||||
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task)
|
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task)
|
||||||
{
|
{
|
||||||
@ -529,45 +689,48 @@ static int task_main_path (
|
|||||||
struct stat st;
|
struct stat st;
|
||||||
qse_httpd_task_t* x = task;
|
qse_httpd_task_t* x = task;
|
||||||
|
|
||||||
qse_printf (QSE_T("opending file %hs\n"), data->name);
|
qse_printf (QSE_T("opening file %hs\n"), data->name);
|
||||||
handle.i = open (data->name, O_RDONLY);
|
handle.i = open (data->name, O_RDONLY);
|
||||||
if (handle.i <= -1)
|
if (handle.i <= -1)
|
||||||
{
|
{
|
||||||
const qse_mchar_t* msg = QSE_MT("<html><head><title>Not found</title></head><body><b>REQUESTED FILE NOT FOUND</b></body></html>");
|
x = entask_path_error (httpd, client, x, 404);
|
||||||
x = qse_httpd_entaskformat (
|
|
||||||
httpd, client, x,
|
|
||||||
QSE_MT("HTTP/%d.%d 404 Not found\r\nContent-Length: %d\r\n\r\n%s\r\n\r\n"),
|
|
||||||
data->version.major, data->version.minor,
|
|
||||||
(int)qse_mbslen(msg) + 4, msg
|
|
||||||
);
|
|
||||||
goto no_file_send;
|
goto no_file_send;
|
||||||
}
|
}
|
||||||
fcntl (handle.i, F_SETFD, FD_CLOEXEC);
|
fcntl (handle.i, F_SETFD, FD_CLOEXEC);
|
||||||
|
|
||||||
if (fstat (handle.i, &st) <= -1)
|
if (fstat (handle.i, &st) <= -1)
|
||||||
{
|
{
|
||||||
const qse_mchar_t* msg = QSE_MT("<html><head><title>Not found</title></head><body><b>REQUESTED FILE NOT FOUND</b></body></html>");
|
x = entask_path_error (httpd, client, x, 404);
|
||||||
|
|
||||||
x = qse_httpd_entaskformat (
|
|
||||||
httpd, client, x,
|
|
||||||
QSE_MT("HTTP/%d.%d 404 Not found\r\nContent-Length: %d\r\n\r\n%s\r\n\r\n"),
|
|
||||||
data->version.major, data->version.minor,
|
|
||||||
(int)qse_mbslen(msg) + 4, msg
|
|
||||||
);
|
|
||||||
goto no_file_send;
|
goto no_file_send;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (S_ISDIR(st.st_mode))
|
if (S_ISDIR(st.st_mode))
|
||||||
{
|
{
|
||||||
/* TODO: directory listing */
|
qse_ubi_t dir;
|
||||||
const qse_mchar_t* msg = QSE_MT("<html><head><title>Directory Listing</title></head><body><li>file1<li>file2<li>file3</body></html>");
|
|
||||||
|
|
||||||
x = qse_httpd_entaskformat (
|
/*#if defined(HAVE_FDOPENDIR)
|
||||||
httpd, client, x,
|
dir.ptr = fdopendir (handle.i);
|
||||||
QSE_MT("HTTP/%d.%d 200 OK\r\nContent-Type: text/html\r\nContent-Length: %d\r\n\r\n%s\r\n\r\n"),
|
#else */
|
||||||
data->version.major, data->version.minor,
|
dir.ptr = opendir (data->name);
|
||||||
(int)qse_mbslen(msg) + 4, msg
|
/*#endif */
|
||||||
);
|
if (dir.ptr)
|
||||||
|
{
|
||||||
|
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
|
||||||
|
);
|
||||||
|
|
||||||
|
x = qse_httpd_entaskdir (httpd, client, x, dir);
|
||||||
|
if (x == QSE_NULL) closedir (dir.ptr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x = entask_path_error (httpd, client, x, 403);
|
||||||
|
}
|
||||||
goto no_file_send;
|
goto no_file_send;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -587,33 +750,26 @@ qse_printf (QSE_T("opending file %hs\n"), data->name);
|
|||||||
|
|
||||||
if (data->range.from >= st.st_size)
|
if (data->range.from >= st.st_size)
|
||||||
{
|
{
|
||||||
const qse_mchar_t* msg;
|
x = entask_path_error (httpd, client, x, 416);
|
||||||
|
|
||||||
msg = QSE_MT("<html><head><title>Requested range not satisfiable</title></head><body><b>REQUESTED RANGE NOT SATISFIABLE</b></body></html>");
|
|
||||||
x = qse_httpd_entaskformat (
|
|
||||||
httpd, client, x,
|
|
||||||
QSE_MT("HTTP/%d.%d 416 Requested range not satisfiable\r\nContent-Length: %d\r\n\r\n%s\r\n\r\n"),
|
|
||||||
data->version.major, data->version.minor,
|
|
||||||
(int)qse_mbslen(msg) + 4, msg
|
|
||||||
);
|
|
||||||
goto no_file_send;
|
goto no_file_send;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data->range.to >= st.st_size) data->range.to = st.st_size - 1;
|
if (data->range.to >= st.st_size) data->range.to = st.st_size - 1;
|
||||||
|
|
||||||
if (httpd->cbs->file.getmimetype)
|
if (httpd->cbs->getmimetype)
|
||||||
{
|
{
|
||||||
httpd->errnum = QSE_HTTPD_ENOERR;
|
httpd->errnum = QSE_HTTPD_ENOERR;
|
||||||
mime_type = httpd->cbs->file.getmimetype (httpd, data->name);
|
mime_type = httpd->cbs->getmimetype (httpd, data->name);
|
||||||
/*TODO: how to handle an error... */
|
/*TODO: how to handle an error... */
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (QSE_SIZEOF_LONG_LONG > 0)
|
#if (QSE_SIZEOF_LONG_LONG > 0)
|
||||||
x = qse_httpd_entaskformat (
|
x = qse_httpd_entaskformat (
|
||||||
httpd, client, x,
|
httpd, client, x,
|
||||||
QSE_MT("HTTP/%d.%d 206 Partial content\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-Location: %s\r\nContent-Range: bytes %llu-%llu/%llu\r\n\r\n"),
|
||||||
data->version.major,
|
data->version.major,
|
||||||
data->version.minor,
|
data->version.minor,
|
||||||
|
(data->keepalive? QSE_MT("Keep-Alive"): QSE_MT("Close")),
|
||||||
(mime_type? QSE_MT("Content-Type: "): QSE_MT("")),
|
(mime_type? QSE_MT("Content-Type: "): QSE_MT("")),
|
||||||
(mime_type? mime_type: QSE_MT("")),
|
(mime_type? mime_type: QSE_MT("")),
|
||||||
(mime_type? QSE_MT("\r\n"): QSE_MT("")),
|
(mime_type? QSE_MT("\r\n"): QSE_MT("")),
|
||||||
@ -626,9 +782,10 @@ qse_printf (QSE_T("opending file %hs\n"), data->name);
|
|||||||
#else
|
#else
|
||||||
x = qse_httpd_entaskformat (
|
x = qse_httpd_entaskformat (
|
||||||
httpd, client, x,
|
httpd, client, x,
|
||||||
QSE_MT("HTTP/%d.%d 206 Partial content\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-Location: %s\r\nContent-Range: bytes %lu-%lu/%lu\r\n\r\n"),
|
||||||
data->version.major,
|
data->version.major,
|
||||||
data->version.minor,
|
data->version.minor,
|
||||||
|
(data->keepalive? QSE_MT("Keep-Alive"): QSE_MT("Close")),
|
||||||
(mime_type? QSE_MT("Content-Type: "): QSE_MT("")),
|
(mime_type? QSE_MT("Content-Type: "): QSE_MT("")),
|
||||||
(mime_type? mime_type: QSE_MT("")),
|
(mime_type? mime_type: QSE_MT("")),
|
||||||
(mime_type? QSE_MT("\r\n"): QSE_MT("")),
|
(mime_type? QSE_MT("\r\n"): QSE_MT("")),
|
||||||
@ -642,10 +799,10 @@ qse_printf (QSE_T("opending file %hs\n"), data->name);
|
|||||||
if (x)
|
if (x)
|
||||||
{
|
{
|
||||||
x = qse_httpd_entaskfile (
|
x = qse_httpd_entaskfile (
|
||||||
httpd, client, x,
|
httpd, client, x,
|
||||||
handle,
|
handle,
|
||||||
data->range.from,
|
data->range.from,
|
||||||
(data->range.to - data->range.from + 1)
|
(data->range.to - data->range.from + 1)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -654,19 +811,22 @@ qse_printf (QSE_T("opending file %hs\n"), data->name);
|
|||||||
/* TODO: int64 format.... don't hard code it llu */
|
/* TODO: int64 format.... don't hard code it llu */
|
||||||
const qse_mchar_t* mime_type = QSE_NULL;
|
const qse_mchar_t* mime_type = QSE_NULL;
|
||||||
|
|
||||||
if (httpd->cbs->file.getmimetype)
|
if (httpd->cbs->getmimetype)
|
||||||
{
|
{
|
||||||
httpd->errnum = QSE_HTTPD_ENOERR;
|
httpd->errnum = QSE_HTTPD_ENOERR;
|
||||||
mime_type = httpd->cbs->file.getmimetype (httpd, data->name);
|
mime_type = httpd->cbs->getmimetype (httpd, data->name);
|
||||||
/*TODO: how to handle an error... */
|
/*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
|
||||||
|
* close connection.*/
|
||||||
#if (QSE_SIZEOF_LONG_LONG > 0)
|
#if (QSE_SIZEOF_LONG_LONG > 0)
|
||||||
x = qse_httpd_entaskformat (
|
x = qse_httpd_entaskformat (
|
||||||
httpd, client, x,
|
httpd, client, x,
|
||||||
QSE_MT("HTTP/%d.%d 200 OK\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\nContent-Location: %s\r\n\r\n"),
|
||||||
data->version.major,
|
data->version.major, data->version.minor,
|
||||||
data->version.minor,
|
(data->keepalive? QSE_MT("Keep-Alive"): QSE_MT("Close")),
|
||||||
(mime_type? QSE_MT("Content-Type: "): QSE_MT("")),
|
(mime_type? QSE_MT("Content-Type: "): QSE_MT("")),
|
||||||
(mime_type? mime_type: QSE_MT("")),
|
(mime_type? mime_type: QSE_MT("")),
|
||||||
(mime_type? QSE_MT("\r\n"): QSE_MT("")),
|
(mime_type? QSE_MT("\r\n"): QSE_MT("")),
|
||||||
@ -676,9 +836,10 @@ qse_printf (QSE_T("opending file %hs\n"), data->name);
|
|||||||
#else
|
#else
|
||||||
x = qse_httpd_entaskformat (
|
x = qse_httpd_entaskformat (
|
||||||
httpd, client, x,
|
httpd, client, x,
|
||||||
QSE_MT("HTTP/%d.%d 200 OK\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\nContent-Location: %s\r\n\r\n"),
|
||||||
data->version.major,
|
data->version.major,
|
||||||
data->version.minor,
|
data->version.minor,
|
||||||
|
(data->keepalive? QSE_MT("Keep-Alive"): QSE_MT("Close")),
|
||||||
(mime_type? QSE_MT("Content-Type: "): QSE_MT("")),
|
(mime_type? QSE_MT("Content-Type: "): QSE_MT("")),
|
||||||
(mime_type? mime_type: QSE_MT("")),
|
(mime_type? mime_type: QSE_MT("")),
|
||||||
(mime_type? QSE_MT("\r\n"): QSE_MT("")),
|
(mime_type? QSE_MT("\r\n"): QSE_MT("")),
|
||||||
@ -706,7 +867,8 @@ qse_httpd_task_t* qse_httpd_entaskpath (
|
|||||||
const qse_httpd_task_t* pred,
|
const qse_httpd_task_t* pred,
|
||||||
const qse_mchar_t* name,
|
const qse_mchar_t* name,
|
||||||
const qse_http_range_t* range,
|
const qse_http_range_t* range,
|
||||||
const qse_http_version_t* verison)
|
const qse_http_version_t* verison,
|
||||||
|
int keepalive)
|
||||||
{
|
{
|
||||||
qse_httpd_task_t task;
|
qse_httpd_task_t task;
|
||||||
task_path_t data;
|
task_path_t data;
|
||||||
@ -716,6 +878,7 @@ qse_httpd_task_t* qse_httpd_entaskpath (
|
|||||||
if (range) data.range = *range;
|
if (range) data.range = *range;
|
||||||
else data.range.type = QSE_HTTP_RANGE_NONE;
|
else data.range.type = QSE_HTTP_RANGE_NONE;
|
||||||
data.version = *verison;
|
data.version = *verison;
|
||||||
|
data.keepalive = keepalive;
|
||||||
|
|
||||||
QSE_MEMSET (&task, 0, QSE_SIZEOF(task));
|
QSE_MEMSET (&task, 0, QSE_SIZEOF(task));
|
||||||
task.init = task_init_path;
|
task.init = task_init_path;
|
||||||
|
@ -30,8 +30,9 @@
|
|||||||
#else
|
#else
|
||||||
# if defined(QSE_CHAR_IS_MCHAR) && defined(USE_REGEX)
|
# if defined(QSE_CHAR_IS_MCHAR) && defined(USE_REGEX)
|
||||||
# include <regex.h>
|
# include <regex.h>
|
||||||
|
# else
|
||||||
|
# include <qse/cmn/tre.h>
|
||||||
# endif
|
# endif
|
||||||
# include <qse/cmn/tre.h>
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
QSE_IMPLEMENT_COMMON_FUNCTIONS (sed)
|
QSE_IMPLEMENT_COMMON_FUNCTIONS (sed)
|
||||||
|
@ -101,7 +101,8 @@ qse_httpd_entaskstatictext (httpd, client, QSE_NULL, QSE_MT("HTTP/1.1 416 Reques
|
|||||||
httpd, client, QSE_NULL,
|
httpd, client, QSE_NULL,
|
||||||
qse_htre_getqpathptr(req),
|
qse_htre_getqpathptr(req),
|
||||||
(rangestr? &range: QSE_NULL),
|
(rangestr? &range: QSE_NULL),
|
||||||
qse_htre_getversion(req)
|
qse_htre_getversion(req),
|
||||||
|
req->attr.keepalive
|
||||||
);
|
);
|
||||||
if (x == QSE_NULL) goto oops;
|
if (x == QSE_NULL) goto oops;
|
||||||
}
|
}
|
||||||
@ -120,7 +121,7 @@ qse_httpd_entaskstatictext (httpd, client, QSE_NULL, QSE_MT("HTTP/1.1 416 Reques
|
|||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
if (req->attr.connection_close)
|
if (!req->attr.keepalive)
|
||||||
{
|
{
|
||||||
x = qse_httpd_entaskdisconnect (httpd, client, QSE_NULL);
|
x = qse_httpd_entaskdisconnect (httpd, client, QSE_NULL);
|
||||||
if (x == QSE_NULL) goto oops;
|
if (x == QSE_NULL) goto oops;
|
||||||
@ -149,6 +150,11 @@ const qse_mchar_t* get_mime_type (qse_httpd_t* httpd, const qse_mchar_t* path)
|
|||||||
return QSE_NULL;
|
return QSE_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int list_directory (qse_httpd_t* httpd, const qse_mchar_t* path)
|
||||||
|
{
|
||||||
|
return 404;
|
||||||
|
}
|
||||||
|
|
||||||
static qse_httpd_t* httpd = NULL;
|
static qse_httpd_t* httpd = NULL;
|
||||||
|
|
||||||
static void sigint (int sig)
|
static void sigint (int sig)
|
||||||
@ -158,9 +164,10 @@ static void sigint (int sig)
|
|||||||
|
|
||||||
static qse_httpd_cbs_t httpd_cbs =
|
static qse_httpd_cbs_t httpd_cbs =
|
||||||
{
|
{
|
||||||
{ get_mime_type, QSE_NULL, },
|
|
||||||
handle_request,
|
handle_request,
|
||||||
handle_expect_continue
|
handle_expect_continue,
|
||||||
|
get_mime_type,
|
||||||
|
list_directory
|
||||||
};
|
};
|
||||||
|
|
||||||
int httpd_main (int argc, qse_char_t* argv[])
|
int httpd_main (int argc, qse_char_t* argv[])
|
||||||
@ -168,9 +175,9 @@ int httpd_main (int argc, qse_char_t* argv[])
|
|||||||
int n;
|
int n;
|
||||||
httpd_xtn_t* xtn;
|
httpd_xtn_t* xtn;
|
||||||
|
|
||||||
if (argc != 2)
|
if (argc <= 1)
|
||||||
{
|
{
|
||||||
qse_fprintf (QSE_STDERR, QSE_T("Usage: %s <listener_uri>\n"), argv[0]);
|
qse_fprintf (QSE_STDERR, QSE_T("Usage: %s <listener_uri> ...\n"), argv[0]);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,11 +191,15 @@ int httpd_main (int argc, qse_char_t* argv[])
|
|||||||
xtn = (httpd_xtn_t*)qse_httpd_getxtn (httpd);
|
xtn = (httpd_xtn_t*)qse_httpd_getxtn (httpd);
|
||||||
xtn->orgcbs = qse_httpd_getcbs (httpd);
|
xtn->orgcbs = qse_httpd_getcbs (httpd);
|
||||||
|
|
||||||
if (qse_httpd_addlisteners (httpd, argv[1]) <= -1)
|
for (n = 1; n < argc; n++)
|
||||||
{
|
{
|
||||||
qse_fprintf (QSE_STDERR, QSE_T("Failed to add httpd listeners\n"));
|
if (qse_httpd_addlistener (httpd, argv[n]) <= -1)
|
||||||
qse_httpd_close (httpd);
|
{
|
||||||
return -1;
|
qse_fprintf (QSE_STDERR,
|
||||||
|
QSE_T("Failed to add httpd listener - %s\n"), argv[n]);
|
||||||
|
qse_httpd_close (httpd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
qse_httpd_setcbs (httpd, &httpd_cbs);
|
qse_httpd_setcbs (httpd, &httpd_cbs);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user