added qse_httpd_setname(), qse_httpd_getname(), qse_httpd_fmtgmtimetobb()

added qse_fmthttptime()
added Date and Server to httpd tasks
This commit is contained in:
hyung-hwan 2012-09-13 12:31:01 +00:00
parent adb9f387f9
commit 7466287f93
13 changed files with 214 additions and 71 deletions

View File

@ -63,6 +63,7 @@
#define QSE_SECNSEC_TO_MSEC(sec,nsec) \ #define QSE_SECNSEC_TO_MSEC(sec,nsec) \
(((qse_ntime_t)(sec) * QSE_MSECS_PER_SEC) + ((qse_ntime_t)(nsec) / QSE_NSECS_PER_MSEC)) (((qse_ntime_t)(sec) * QSE_MSECS_PER_SEC) + ((qse_ntime_t)(nsec) / QSE_NSECS_PER_MSEC))
#define QSE_SEC_TO_MSEC(sec) ((sec) * QSE_MSECS_PER_SEC)
/** /**
* The qse_ntime_t type defines a numeric time type expressed in the * The qse_ntime_t type defines a numeric time type expressed in the
* number of milliseconds since the Epoch (00:00:00 UTC, Jan 1, 1970). * number of milliseconds since the Epoch (00:00:00 UTC, Jan 1, 1970).

View File

@ -181,12 +181,18 @@ int qse_parsehttprange (
); );
/* /*
int qse_parsehttpdatetime ( int qse_parsehttptime (
const qse_mchar_t* str, const qse_mchar_t* str,
qse_ntime_t* t qse_ntime_t* t
); );
*/ */
qse_mchar_t* qse_fmthttptime (
qse_ntime_t nt,
qse_mchar_t* buf,
qse_size_t bufsz
);
/* percent-decode a string */ /* percent-decode a string */
qse_size_t qse_perdechttpstr ( qse_size_t qse_perdechttpstr (
const qse_mchar_t* str, const qse_mchar_t* str,

View File

@ -422,6 +422,38 @@ void qse_httpd_completecontent (
qse_htre_t* req qse_htre_t* req
); );
/**
* The qse_httpd_setname() function changes the string
* to be used as the value for the server header.
*/
void qse_httpd_setname (
qse_httpd_t* httpd,
const qse_mchar_t* name
);
/**
* The qse_httpd_getname() function returns the
* pointer to the string used as the value for the server
* header.
*/
qse_mchar_t* qse_httpd_getname (
qse_httpd_t* httpd
);
/**
* The qse_httpd_fmtgmtimetobb() function converts a numeric time @a nt
* to a string and stores it in a built-in buffer.
* If @a nt is QSE_NULL, the current time is used.
*/
const qse_mchar_t* qse_httpd_fmtgmtimetobb (
qse_httpd_t* httpd,
const qse_ntime_t* nt,
int idx
);
#define qse_httpd_gettaskxtn(httpd,task) ((void*)(task+1)) #define qse_httpd_gettaskxtn(httpd,task) ((void*)(task+1))
qse_httpd_task_t* qse_httpd_entask ( qse_httpd_task_t* qse_httpd_entask (
@ -506,6 +538,12 @@ qse_httpd_task_t* qse_httpd_entaskfile (
qse_htre_t* req qse_htre_t* req
); );
/**
* The qse_httpd_entaskphat() functions a dispatcher between
* qse_httpd_entaskdir() and qse_httpd_entaskfile(). It calls
* the former if @a name is a directory and calls the latter
* otherwise.
*/
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,

View File

@ -23,18 +23,24 @@
#if defined(_WIN32) #if defined(_WIN32)
# include <windows.h> # include <windows.h>
# include <time.h>
#elif defined(__OS2__) #elif defined(__OS2__)
# define INCL_DOSDATETIME # define INCL_DOSDATETIME
# define INCL_DOSERRORS # define INCL_DOSERRORS
# include <os2.h> # include <os2.h>
# include <time.h>
#elif defined(__DOS__) #elif defined(__DOS__)
# include <dos.h> # include <dos.h>
# include <time.h>
#else #else
# include "syscall.h" # include "syscall.h"
# if defined(HAVE_SYS_TIME_H)
# include <sys/time.h> # include <sys/time.h>
# endif # endif
# if defined(HAVE_TIME_H)
# include <time.h> # include <time.h>
# endif
#endif
#if defined(_WIN32) #if defined(_WIN32)
#define WIN_EPOCH_YEAR (1601) #define WIN_EPOCH_YEAR (1601)
@ -479,4 +485,3 @@ int qse_timelocal (const qse_btime_t* bt, qse_ntime_t* nt)
return 0; return 0;
#endif #endif
} }

View File

@ -24,6 +24,8 @@
#include <qse/cmn/htb.h> #include <qse/cmn/htb.h>
#include "../cmn/mem.h" #include "../cmn/mem.h"
#include <qse/cmn/stdio.h> /* for snprintf. TODO: remove this. */
int qse_comparehttpversions ( int qse_comparehttpversions (
const qse_http_version_t* v1, const qse_http_version_t* v1,
const qse_http_version_t* v2) const qse_http_version_t* v2)
@ -188,13 +190,59 @@ int qse_parsehttprange (const qse_mchar_t* str, qse_http_range_t* range)
} }
#if 0 #if 0
int qse_parsehttpdatetime (const qse_mchar_t* str, qse_ntime_t* t) int qse_parsehttptime (const qse_mchar_t* str, qse_ntime_t* t)
{ {
/* TODO: */ /* TODO: */
return -1; return -1;
} }
#endif #endif
qse_mchar_t* qse_fmthttptime (
qse_ntime_t nt, qse_mchar_t* buf, qse_size_t bufsz)
{
static const qse_mchar_t* wday_name[] =
{
QSE_MT("Sun"),
QSE_MT("Mon"),
QSE_MT("Tue"),
QSE_MT("Wed"),
QSE_MT("Thu"),
QSE_MT("Fri"),
QSE_MT("Sat")
};
static const qse_mchar_t* mon_name[] =
{
QSE_MT("Jan"),
QSE_MT("Feb"),
QSE_MT("Mar"),
QSE_MT("Apr"),
QSE_MT("May"),
QSE_MT("Jun"),
QSE_MT("Jul"),
QSE_MT("Aug"),
QSE_MT("Sep"),
QSE_MT("Oct"),
QSE_MT("Nov"),
QSE_MT("Dec")
};
qse_btime_t bt;
qse_gmtime (nt, &bt);
/* TODO: avoid using snprintf () */
snprintf (buf, bufsz,
QSE_MT("%s, %d %s %d %02d:%02d:%02d GMT"),
wday_name[bt.wday],
bt.mday,
mon_name[bt.mon],
bt.year + QSE_BTIME_YEAR_BASE,
bt.hour, bt.min, bt.sec);
return buf;
}
qse_size_t qse_perdechttpstr (const qse_mchar_t* str, qse_mchar_t* buf) qse_size_t qse_perdechttpstr (const qse_mchar_t* str, qse_mchar_t* buf)
{ {
const qse_mchar_t* p = str; const qse_mchar_t* p = str;

View File

@ -181,10 +181,11 @@ static int cgi_capture_script_header (qse_htre_t* req, const qse_mchar_t* key, c
{ {
task_cgi_t* cgi = (task_cgi_t*)ctx; task_cgi_t* cgi = (task_cgi_t*)ctx;
/* capture a header excluding Status and Connection */ /* capture a header except Status, Connection, Transfer-Encoding, and Server */
if (qse_mbscasecmp (key, QSE_MT("Status")) != 0 && if (qse_mbscasecmp (key, QSE_MT("Status")) != 0 &&
qse_mbscasecmp (key, QSE_MT("Connection")) != 0 && qse_mbscasecmp (key, QSE_MT("Connection")) != 0 &&
qse_mbscasecmp (key, QSE_MT("Transfer-Encoding")) != 0) qse_mbscasecmp (key, QSE_MT("Transfer-Encoding")) != 0 &&
qse_mbscasecmp (key, QSE_MT("Server")) != 0)
{ {
return cgi_add_header_to_buffer (cgi, cgi->res, key, val); return cgi_add_header_to_buffer (cgi, cgi->res, key, val);
} }
@ -268,6 +269,28 @@ static int cgi_htrd_peek_script_output (qse_htrd_t* htrd, qse_htre_t* req)
} }
} }
/* Add the server header. the server header in the cgi output will
* be ignored by cgi_capture_script_header() */
if (qse_mbs_cat (cgi->res, QSE_MT("Server: ")) == (qse_size_t)-1 ||
qse_mbs_cat (cgi->res, qse_httpd_getname (cgi->httpd)) == (qse_size_t)-1 ||
qse_mbs_cat (cgi->res, QSE_MT("\r\n")) == (qse_size_t)-1)
{
cgi->httpd->errnum = QSE_HTTPD_ENOMEM;
return -1;
}
if (qse_htre_getheaderval (req, QSE_MT("Date")) == QSE_NULL)
{
/* generate the Date header if it's not included in the script output */
if (qse_mbs_cat (cgi->res, QSE_MT("Date: ")) == (qse_size_t)-1 ||
qse_mbs_cat (cgi->res, qse_httpd_fmtgmtimetobb (cgi->httpd, QSE_NULL, 0)) == (qse_size_t)-1 ||
qse_mbs_cat (cgi->res, QSE_MT("\r\n")) == (qse_size_t)-1)
{
cgi->httpd->errnum = QSE_HTTPD_ENOMEM;
return -1;
}
}
keepalive = cgi->keepalive; keepalive = cgi->keepalive;
if (req->attr.flags & QSE_HTRE_ATTR_LENGTH) if (req->attr.flags & QSE_HTRE_ATTR_LENGTH)
{ {

View File

@ -164,6 +164,7 @@ static int task_main_dseg (
} }
/* the buffer size is fixed to QSE_COUNTOF(ctx->buf). /* the buffer size is fixed to QSE_COUNTOF(ctx->buf).
*
* the number of digits need to hold the the size converted to * the number of digits need to hold the the size converted to
* a hexadecimal notation is roughly (log16(QSE_COUNTOF(ctx->buf) + 1). * a hexadecimal notation is roughly (log16(QSE_COUNTOF(ctx->buf) + 1).
* it should be safter to use ceil(log16(QSE_COUNTOF(ctx->buf)) + 1 * it should be safter to use ceil(log16(QSE_COUNTOF(ctx->buf)) + 1
@ -410,8 +411,10 @@ static QSE_INLINE int task_main_dir (
{ {
x = qse_httpd_entaskformat ( x = qse_httpd_entaskformat (
httpd, client, x, httpd, client, x,
QSE_MT("HTTP/%d.%d 200 OK\r\nConnection: %s\r\nContent-Type: text/html\r\n%s\r\n"), QSE_MT("HTTP/%d.%d 200 OK\r\nServer: %s\r\nDate: %s\r\nConnection: %s\r\nContent-Type: text/html\r\n%s\r\n"),
dir->version.major, dir->version.minor, dir->version.major, dir->version.minor,
qse_httpd_getname (httpd),
qse_httpd_fmtgmtimetobb (httpd, QSE_NULL, 0),
(dir->keepalive? QSE_MT("keep-alive"): QSE_MT("close")), (dir->keepalive? QSE_MT("keep-alive"): QSE_MT("close")),
(dir->keepalive? QSE_MT("Transfer-Encoding: chunked\r\n"): QSE_MT("")) (dir->keepalive? QSE_MT("Transfer-Encoding: chunked\r\n"): QSE_MT(""))
); );
@ -438,8 +441,10 @@ static QSE_INLINE int task_main_dir (
{ {
x = qse_httpd_entaskformat ( x = qse_httpd_entaskformat (
httpd, client, x, httpd, client, x,
QSE_MT("HTTP/%d.%d 301 Moved Permanently\r\nContent-Length: 0\r\nConnection: %s\r\nLocation: %s/\r\n\r\n"), QSE_MT("HTTP/%d.%d 301 Moved Permanently\r\nServer: %s\r\nDate: %s\r\nContent-Length: 0\r\nConnection: %s\r\nLocation: %s/\r\n\r\n"),
dir->version.major, dir->version.minor, dir->version.major, dir->version.minor,
qse_httpd_getname (httpd),
qse_httpd_fmtgmtimetobb (httpd, QSE_NULL, 0),
(dir->keepalive? QSE_MT("keep-alive"): QSE_MT("close")), (dir->keepalive? QSE_MT("keep-alive"): QSE_MT("close")),
dir->path dir->path
); );

View File

@ -22,7 +22,9 @@
#include "../cmn/mem.h" #include "../cmn/mem.h"
#include "../cmn/syscall.h" #include "../cmn/syscall.h"
#include <qse/cmn/str.h> #include <qse/cmn/str.h>
#include <qse/cmn/fmt.h>
#include <qse/cmn/path.h> #include <qse/cmn/path.h>
#include <qse/cmn/time.h>
#include <qse/cmn/stdio.h> /* TODO: remove this */ #include <qse/cmn/stdio.h> /* TODO: remove this */
typedef struct task_file_t task_file_t; typedef struct task_file_t task_file_t;
@ -30,6 +32,7 @@ struct task_file_t
{ {
const qse_mchar_t* path; const qse_mchar_t* path;
qse_http_range_t range; qse_http_range_t range;
qse_ntime_t if_modified_since;
qse_http_version_t version; qse_http_version_t version;
int keepalive; int keepalive;
}; };
@ -174,6 +177,8 @@ qse_printf (QSE_T("opening file %hs\n"), file->path);
if (file->range.type != QSE_HTTP_RANGE_NONE) if (file->range.type != QSE_HTTP_RANGE_NONE)
{ {
qse_mchar_t tmp[4][64];
if (file->range.type == QSE_HTTP_RANGE_SUFFIX) if (file->range.type == QSE_HTTP_RANGE_SUFFIX)
{ {
if (file->range.to > st.size) file->range.to = st.size; if (file->range.to > st.size) file->range.to = st.size;
@ -191,37 +196,23 @@ qse_printf (QSE_T("opening file %hs\n"), file->path);
if (file->range.to >= st.size) file->range.to = st.size - 1; if (file->range.to >= st.size) file->range.to = st.size - 1;
#if (QSE_SIZEOF_LONG_LONG > 0) qse_fmtuintmaxtombs (tmp[0], QSE_COUNTOF(tmp[0]), (file->range.to - file->range.from + 1), 10, -1, QSE_MT('\0'), QSE_NULL);
qse_fmtuintmaxtombs (tmp[1], QSE_COUNTOF(tmp[1]), file->range.from, 10, -1, QSE_MT('\0'), QSE_NULL);
qse_fmtuintmaxtombs (tmp[2], QSE_COUNTOF(tmp[2]), file->range.to, 10, -1, QSE_MT('\0'), QSE_NULL);
qse_fmtuintmaxtombs (tmp[3], QSE_COUNTOF(tmp[3]), st.size, 10, -1, QSE_MT('\0'), QSE_NULL);
x = qse_httpd_entaskformat ( x = qse_httpd_entaskformat (
httpd, client, x, httpd, client, x,
QSE_MT("HTTP/%d.%d 206 Partial Content\r\nConnection: %s\r\n%s%s%sContent-Length: %llu\r\nContent-Range: bytes %llu-%llu/%llu\r\n\r\n"), QSE_MT("HTTP/%d.%d 206 Partial Content\r\nServer: %s\r\nDate: %s\r\nConnection: %s\r\n%s%s%sContent-Length: %s\r\nContent-Range: bytes %s-%s/%s\r\nAccept-Ranges: bytes\r\nLast-Modified: %s\r\n\r\n"),
file->version.major, file->version.major, file->version.minor,
file->version.minor, qse_httpd_getname (httpd),
qse_httpd_fmtgmtimetobb (httpd, QSE_NULL, 0),
(file->keepalive? QSE_MT("keep-alive"): QSE_MT("close")), (file->keepalive? QSE_MT("keep-alive"): QSE_MT("close")),
(st.mime? QSE_MT("Content-Type: "): QSE_MT("")), (st.mime? QSE_MT("Content-Type: "): QSE_MT("")),
(st.mime? st.mime: QSE_MT("")), (st.mime? st.mime: QSE_MT("")),
(st.mime? QSE_MT("\r\n"): QSE_MT("")), (st.mime? QSE_MT("\r\n"): QSE_MT("")),
(unsigned long long)(file->range.to - file->range.from + 1), tmp[0], tmp[1], tmp[2], tmp[3]
(unsigned long long)file->range.from,
(unsigned long long)file->range.to,
(unsigned long long)st.size
); );
#else
x = qse_httpd_entaskformat (
httpd, client, x,
QSE_MT("HTTP/%d.%d 206 Partial Content\r\nConnection: %s\r\n%s%s%sContent-Length: %lu\r\nContent-Range: bytes %lu-%lu/%lu\r\n\r\n"),
file->version.major,
file->version.minor,
(file->keepalive? QSE_MT("keep-alive"): QSE_MT("close")),
(st.mime? QSE_MT("Content-Type: "): QSE_MT("")),
(st.mime? st.mime: QSE_MT("")),
(st.mime? QSE_MT("\r\n"): QSE_MT("")),
(unsigned long)(file->range.to - file->range.from + 1),
(unsigned long)file->range.from,
(unsigned long)file->range.to,
(unsigned long)st.size
);
#endif
if (x) if (x)
{ {
x = entask_file_segment ( x = entask_file_segment (
@ -234,36 +225,28 @@ qse_printf (QSE_T("opening file %hs\n"), file->path);
} }
else else
{ {
/* TODO: int64 format.... don't hard code it llu */ qse_mchar_t b_fsize[64];
qse_fmtuintmaxtombs (b_fsize, QSE_COUNTOF(b_fsize), st.size, 10, -1, QSE_MT('\0'), QSE_NULL);
/* wget 1.8.2 set 'Connection: keep-alive' in the http 1.0 header. /* 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 * if the reply doesn't contain 'Connection: keep-alive', it didn't
* close connection.*/ * close connection.*/
#if (QSE_SIZEOF_LONG_LONG > 0)
x = qse_httpd_entaskformat (
httpd, client, x,
QSE_MT("HTTP/%d.%d 200 OK\r\nConnection: %s\r\n%s%s%sContent-Length: %llu\r\n\r\n"),
file->version.major, file->version.minor,
(file->keepalive? QSE_MT("keep-alive"): QSE_MT("close")),
(st.mime? QSE_MT("Content-Type: "): QSE_MT("")),
(st.mime? st.mime: QSE_MT("")),
(st.mime? QSE_MT("\r\n"): QSE_MT("")),
(unsigned long long)st.size
);
#else
x = qse_httpd_entaskformat (
httpd, client, x,
QSE_MT("HTTP/%d.%d 200 OK\r\nConnection: %s\r\n%s%s%sContent-Length: %lu\r\n\r\n"),
file->version.major,
file->version.minor,
(file->keepalive? QSE_MT("keep-alive"): QSE_MT("close")),
(st.mime? QSE_MT("Content-Type: "): QSE_MT("")),
(st.mime? st.mime: QSE_MT("")),
(st.mime? QSE_MT("\r\n"): QSE_MT("")),
(unsigned long)st.size
);
#endif
if (x) x = entask_file_segment (httpd, client, x, handle, 0, st.size);
x = qse_httpd_entaskformat (
httpd, client, x,
QSE_MT("HTTP/%d.%d 200 OK\r\nServer: %s\r\nDate: %s\r\nConnection: %s\r\n%s%s%sContent-Length: %s\r\nAccept-Ranges: bytes\r\nLast-Modified: %s\r\n\r\n"),
file->version.major, file->version.minor,
qse_httpd_getname (httpd),
qse_httpd_fmtgmtimetobb (httpd, QSE_NULL, 0),
(file->keepalive? QSE_MT("keep-alive"): QSE_MT("close")),
(st.mime? QSE_MT("Content-Type: "): QSE_MT("")),
(st.mime? st.mime: QSE_MT("")),
(st.mime? QSE_MT("\r\n"): QSE_MT("")),
b_fsize,
qse_httpd_fmtgmtimetobb (httpd, &st.mtime, 1)
);
if (x) x = entask_file_segment (httpd, client, x, handle, 0, st.size);
} }
if (x) return 0; if (x) return 0;
@ -305,11 +288,13 @@ qse_httpd_task_t* qse_httpd_entaskfile (
data.range.type = QSE_HTTP_RANGE_NONE; data.range.type = QSE_HTTP_RANGE_NONE;
} }
data.if_modified_since = QSE_TYPE_MIN(qse_ntime_t);
/* /*
TODO: If-Modified-Since... TODO: If-Modified-Since...
tmp = qse_htre_getheaderval(req, QSE_MT("If-Modified-Since")); tmp = qse_htre_getheaderval(req, QSE_MT("If-Modified-Since"));
if (tmp) if (tmp)
{ {
qse_httpd_parsegmtime (tmp, &
} }
*/ */

View File

@ -987,7 +987,7 @@ static int file_stat (
#elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC) #elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC)
hst->mtime = QSE_SECNSEC_TO_MSEC(st.st_mtimespec.tv_sec,st.st_mtimespec.tv_nsec); hst->mtime = QSE_SECNSEC_TO_MSEC(st.st_mtimespec.tv_sec,st.st_mtimespec.tv_nsec);
#else #else
hst->mtime = st.st_mtime * QSE_MSECS_PER_SEC; hst->mtime = QSE_SEC_TO_MSEC(st.st_mtime);
#endif #endif
hst->mime = qse_mbsend (path, QSE_MT(".html"))? QSE_MT("text/html"): hst->mime = qse_mbsend (path, QSE_MT(".html"))? QSE_MT("text/html"):

View File

@ -392,8 +392,10 @@ qse_httpd_task_t* qse_httpd_entask_error (
return qse_httpd_entaskformat ( return qse_httpd_entaskformat (
httpd, client, pred, httpd, client, pred,
QSE_MT("HTTP/%d.%d %d %s\r\nConnection: %s\r\nContent-Type: text/html\r\nContent-Length: %lu\r\n\r\n%s\r\n\r\n"), QSE_MT("HTTP/%d.%d %d %s\r\nServer: %s\r\nDate: %s\r\nConnection: %s\r\nContent-Type: text/html\r\nContent-Length: %lu\r\n\r\n%s\r\n\r\n"),
version->major, version->minor, code, smsg, version->major, version->minor, code, smsg,
qse_httpd_getname (httpd),
qse_httpd_fmtgmtimetobb (httpd, QSE_NULL, 0),
(keepalive? QSE_MT("keep-alive"): QSE_MT("close")), (keepalive? QSE_MT("keep-alive"): QSE_MT("close")),
(unsigned long)qse_mbslen(lmsg) + 4, lmsg (unsigned long)qse_mbslen(lmsg) + 4, lmsg
); );
@ -435,8 +437,10 @@ qse_httpd_task_t* qse_httpd_entaskauth (
return qse_httpd_entaskformat ( return qse_httpd_entaskformat (
httpd, client, pred, httpd, client, pred,
QSE_MT("HTTP/%d.%d 401 Unauthorized\r\nConnection: %s\r\nWWW-Authenticate: Basic realm=\"%s\"\r\nContent-Type: text/html\r\nContent-Length: %lu\r\n\r\n%s\r\n\r\n"), QSE_MT("HTTP/%d.%d 401 Unauthorized\r\nServer: %s\r\nDate: %s\r\nConnection: %s\r\nWWW-Authenticate: Basic realm=\"%s\"\r\nContent-Type: text/html\r\nContent-Length: %lu\r\n\r\n%s\r\n\r\n"),
version->major, version->minor, version->major, version->minor,
qse_httpd_getname (httpd),
qse_httpd_fmtgmtimetobb (httpd, QSE_NULL, 0),
((req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE)? QSE_MT("keep-alive"): QSE_MT("close")), ((req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE)? QSE_MT("keep-alive"): QSE_MT("close")),
realm, (unsigned long)qse_mbslen(lmsg) + 4, lmsg); realm, (unsigned long)qse_mbslen(lmsg) + 4, lmsg);
} }

View File

@ -18,14 +18,10 @@
License along with QSE. If not, see <http://www.gnu.org/licenses/>. License along with QSE. If not, see <http://www.gnu.org/licenses/>.
*/ */
#if defined(_WIN32) || defined(__DOS__) || defined(__OS2__)
/* UNSUPPORTED YET.. */
/* TODO: IMPLEMENT THIS */
#else
#include "httpd.h" #include "httpd.h"
#include "../cmn/mem.h" #include "../cmn/mem.h"
#include "../cmn/syscall.h" #include "../cmn/syscall.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 <qse/cmn/mbwc.h>
@ -97,6 +93,7 @@ int qse_httpd_init (qse_httpd_t* httpd, qse_mmgr_t* mmgr)
{ {
QSE_MEMSET (httpd, 0, QSE_SIZEOF(*httpd)); QSE_MEMSET (httpd, 0, QSE_SIZEOF(*httpd));
httpd->mmgr = mmgr; httpd->mmgr = mmgr;
qse_mbscpy (httpd->sname, QSE_MT("QSE-HTTPD " QSE_PACKAGE_VERSION));
return 0; return 0;
} }
@ -593,8 +590,7 @@ static void free_server_list (qse_httpd_t* httpd, qse_httpd_server_t* server)
} }
} }
static qse_httpd_server_t* parse_server_uri ( static qse_httpd_server_t* parse_server_uri (qse_httpd_t* httpd, const qse_char_t* uri)
qse_httpd_t* httpd, const qse_char_t* uri)
{ {
qse_httpd_server_t* server; qse_httpd_server_t* server;
qse_uint16_t default_port; qse_uint16_t default_port;
@ -1234,4 +1230,31 @@ void qse_httpd_completecontent (qse_httpd_t* httpd, qse_htre_t* req)
qse_htre_completecontent (req); qse_htre_completecontent (req);
} }
#endif /* --------------------------------------------------- */
void qse_httpd_setname (qse_httpd_t* httpd, const qse_mchar_t* name)
{
qse_mbsxcpy (httpd->sname, QSE_COUNTOF(httpd->sname), name);
}
qse_mchar_t* qse_httpd_getname (qse_httpd_t* httpd)
{
return httpd->sname;
}
const qse_mchar_t* qse_httpd_fmtgmtimetobb (
qse_httpd_t* httpd, const qse_ntime_t* nt, int idx)
{
qse_ntime_t now;
QSE_ASSERT (idx >= 0 && idx < QSE_COUNTOF(httpd->gtbuf));
if (nt == QSE_NULL)
{
if (qse_gettime(&now) <= -1) now = 0;
nt = &now;
}
qse_fmthttptime (*nt, httpd->gtbuf[idx], QSE_COUNTOF(httpd->gtbuf[idx]));
return httpd->gtbuf[idx];
}

View File

@ -36,6 +36,9 @@ struct qse_httpd_t
int option; int option;
int stopreq; int stopreq;
qse_mchar_t sname[128]; /* server name for the server header */
qse_mchar_t gtbuf[10][64]; /* GMT time buffers */
struct struct
{ {
struct struct

View File

@ -209,6 +209,8 @@ static int httpd_main (int argc, qse_char_t* argv[])
signal (SIGINT, sigint); signal (SIGINT, sigint);
signal (SIGPIPE, SIG_IGN); signal (SIGPIPE, SIG_IGN);
qse_httpd_setname (httpd, QSE_MT("httpd02/qse 1.0"));
qse_httpd_setoption (httpd, QSE_HTTPD_CGIERRTONUL); qse_httpd_setoption (httpd, QSE_HTTPD_CGIERRTONUL);
ret = qse_httpd_loopstd (httpd, &rcb, 10000); ret = qse_httpd_loopstd (httpd, &rcb, 10000);