2011-07-25 08:24:13 +00:00
|
|
|
/*
|
|
|
|
* $Id$
|
|
|
|
*
|
2012-07-20 04:13:39 +00:00
|
|
|
Copyright 2006-2012 Chung, Hyung-Hwan.
|
2011-07-25 08:24:13 +00:00
|
|
|
This file is part of QSE.
|
|
|
|
|
|
|
|
QSE is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU Lesser General Public License as
|
|
|
|
published by the Free Software Foundation, either version 3 of
|
|
|
|
the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
QSE is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU Lesser General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
|
|
License along with QSE. If not, see <htrd://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
2011-07-21 10:17:16 +00:00
|
|
|
#include "httpd.h"
|
|
|
|
#include <qse/cmn/str.h>
|
2012-02-08 12:59:59 +00:00
|
|
|
#include <qse/cmn/fmt.h>
|
2012-09-27 12:54:35 +00:00
|
|
|
#include "../cmn/mem.h"
|
2011-07-21 10:17:16 +00:00
|
|
|
|
2011-07-28 23:06:16 +00:00
|
|
|
#include <stdarg.h>
|
2012-12-28 08:39:41 +00:00
|
|
|
#include <stdio.h> /* TODO: remove this */
|
2012-09-12 15:47:41 +00:00
|
|
|
|
2011-07-28 23:06:16 +00:00
|
|
|
|
2012-04-09 15:29:33 +00:00
|
|
|
/* TODO:
|
|
|
|
* many functions in this file use qse_size_t.
|
|
|
|
* so the size data transfers is limited by this type.
|
|
|
|
* break this barrier... */
|
|
|
|
|
2011-07-21 10:17:16 +00:00
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
static int task_main_disconnect (
|
|
|
|
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task)
|
|
|
|
{
|
2013-02-20 08:47:22 +00:00
|
|
|
httpd->opt.scb.client.shutdown (httpd, client);
|
2011-07-21 10:17:16 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-07-30 02:14:04 +00:00
|
|
|
qse_httpd_task_t* qse_httpd_entaskdisconnect (
|
|
|
|
qse_httpd_t* httpd,
|
|
|
|
qse_httpd_client_t* client,
|
2012-03-18 14:24:54 +00:00
|
|
|
qse_httpd_task_t* pred)
|
2011-07-21 10:17:16 +00:00
|
|
|
{
|
|
|
|
qse_httpd_task_t task;
|
|
|
|
|
|
|
|
QSE_MEMSET (&task, 0, QSE_SIZEOF(task));
|
|
|
|
task.main = task_main_disconnect;
|
|
|
|
|
2011-07-30 02:14:04 +00:00
|
|
|
return qse_httpd_entask (httpd, client, pred, &task, 0);
|
2011-07-21 10:17:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
/* TODO: send wide character string when QSE_CHAR_IS_WCHAR */
|
|
|
|
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
|
2011-07-28 08:35:28 +00:00
|
|
|
typedef struct task_format_t task_format_t;
|
|
|
|
struct task_format_t
|
2011-07-21 10:17:16 +00:00
|
|
|
{
|
|
|
|
qse_mchar_t* org;
|
|
|
|
const qse_mchar_t* ptr;
|
|
|
|
qse_size_t left;
|
|
|
|
};
|
|
|
|
|
2011-07-28 08:35:28 +00:00
|
|
|
static int task_init_format (
|
2011-07-21 10:17:16 +00:00
|
|
|
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task)
|
|
|
|
{
|
2011-07-28 08:35:28 +00:00
|
|
|
task_format_t* xtn = qse_httpd_gettaskxtn (httpd, task);
|
2011-07-21 10:17:16 +00:00
|
|
|
|
|
|
|
QSE_MEMCPY (xtn, task->ctx, QSE_SIZEOF(*xtn));
|
|
|
|
task->ctx = xtn;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-07-28 08:35:28 +00:00
|
|
|
static void task_fini_format (
|
2011-07-21 10:17:16 +00:00
|
|
|
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task)
|
|
|
|
{
|
2011-07-28 08:35:28 +00:00
|
|
|
task_format_t* ctx = (task_format_t*)task->ctx;
|
2011-07-21 10:17:16 +00:00
|
|
|
qse_httpd_freemem (httpd, ctx->org);
|
|
|
|
}
|
|
|
|
|
2011-07-28 08:35:28 +00:00
|
|
|
static int task_main_format (
|
2011-07-21 10:17:16 +00:00
|
|
|
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* task)
|
|
|
|
{
|
2011-07-28 21:57:39 +00:00
|
|
|
qse_ssize_t n;
|
|
|
|
qse_size_t count;
|
2011-07-28 08:35:28 +00:00
|
|
|
task_format_t* ctx = (task_format_t*)task->ctx;
|
2011-07-21 10:17:16 +00:00
|
|
|
|
2011-07-30 02:14:04 +00:00
|
|
|
count = MAX_SEND_SIZE;
|
2011-07-21 10:17:16 +00:00
|
|
|
if (count >= ctx->left) count = ctx->left;
|
|
|
|
|
2013-02-20 08:47:22 +00:00
|
|
|
n = httpd->opt.scb.client.send (httpd, client, ctx->ptr, count);
|
2011-07-21 10:17:16 +00:00
|
|
|
if (n <= -1) return -1;
|
|
|
|
|
|
|
|
ctx->left -= n;
|
|
|
|
if (ctx->left <= 0) return 0;
|
|
|
|
|
|
|
|
ctx->ptr += n;
|
|
|
|
return 1; /* more work to do */
|
|
|
|
}
|
|
|
|
|
2011-07-30 02:14:04 +00:00
|
|
|
qse_httpd_task_t* qse_httpd_entaskformat (
|
2012-03-27 15:45:10 +00:00
|
|
|
qse_httpd_t* httpd,
|
2011-07-30 02:14:04 +00:00
|
|
|
qse_httpd_client_t* client,
|
2012-03-18 14:24:54 +00:00
|
|
|
qse_httpd_task_t* pred,
|
2011-07-30 02:14:04 +00:00
|
|
|
const qse_mchar_t* fmt, ...)
|
2011-07-21 10:17:16 +00:00
|
|
|
{
|
|
|
|
qse_httpd_task_t task;
|
2011-07-28 08:35:28 +00:00
|
|
|
task_format_t data;
|
2011-07-21 10:17:16 +00:00
|
|
|
|
|
|
|
va_list ap;
|
|
|
|
qse_mchar_t n[2];
|
|
|
|
qse_mchar_t* buf;
|
|
|
|
int bytes_req, l;
|
|
|
|
|
|
|
|
va_start (ap, fmt);
|
|
|
|
bytes_req = vsnprintf (n, 1, fmt, ap);
|
|
|
|
va_end (ap);
|
|
|
|
|
|
|
|
if (bytes_req == -1)
|
|
|
|
{
|
|
|
|
qse_size_t capa = 256;
|
|
|
|
|
2012-02-09 14:30:22 +00:00
|
|
|
buf = (qse_mchar_t*) qse_httpd_allocmem (
|
|
|
|
httpd, (capa + 1) * QSE_SIZEOF(*buf));
|
2011-07-30 02:14:04 +00:00
|
|
|
if (buf == QSE_NULL) return QSE_NULL;
|
2011-07-21 10:17:16 +00:00
|
|
|
|
|
|
|
/* an old vsnprintf behaves differently from C99 standard.
|
|
|
|
* thus, it returns -1 when it can't write all the input given. */
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
va_start (ap, fmt);
|
|
|
|
l = vsnprintf (buf, capa + 1, fmt, ap);
|
|
|
|
va_end (ap);
|
|
|
|
|
|
|
|
if (l == -1)
|
|
|
|
{
|
|
|
|
qse_httpd_freemem (httpd, buf);
|
|
|
|
|
|
|
|
capa = capa * 2;
|
|
|
|
buf = (qse_mchar_t*) qse_httpd_allocmem (httpd, (capa + 1) * QSE_SIZEOF(*buf));
|
2012-02-10 13:58:23 +00:00
|
|
|
if (buf == QSE_NULL) return QSE_NULL;
|
2011-07-21 10:17:16 +00:00
|
|
|
}
|
|
|
|
else break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* vsnprintf returns the number of characters that would
|
|
|
|
* have been written not including the terminating '\0'
|
|
|
|
* if the _data buffer were large enough */
|
2012-02-10 13:58:23 +00:00
|
|
|
buf = (qse_mchar_t*) qse_httpd_allocmem (
|
|
|
|
httpd, (bytes_req + 1) * QSE_SIZEOF(*buf));
|
2011-07-30 02:14:04 +00:00
|
|
|
if (buf == QSE_NULL) return QSE_NULL;
|
2011-07-21 10:17:16 +00:00
|
|
|
|
|
|
|
va_start (ap, fmt);
|
|
|
|
l = vsnprintf (buf, bytes_req + 1, fmt, ap);
|
|
|
|
va_end (ap);
|
|
|
|
|
|
|
|
if (l != bytes_req)
|
|
|
|
{
|
|
|
|
/* something got wrong ... */
|
|
|
|
qse_httpd_freemem (httpd, buf);
|
|
|
|
httpd->errnum = QSE_HTTPD_EINTERN;
|
2011-07-30 02:14:04 +00:00
|
|
|
return QSE_NULL;
|
2011-07-21 10:17:16 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
QSE_MEMSET (&data, 0, QSE_SIZEOF(data));
|
|
|
|
data.org = buf;
|
|
|
|
data.ptr = buf;
|
|
|
|
data.left = l;
|
|
|
|
|
|
|
|
QSE_MEMSET (&task, 0, QSE_SIZEOF(task));
|
2011-07-28 08:35:28 +00:00
|
|
|
task.init = task_init_format;
|
|
|
|
task.fini = task_fini_format;
|
|
|
|
task.main = task_main_format;
|
2011-07-21 10:17:16 +00:00
|
|
|
task.ctx = &data;
|
|
|
|
|
|
|
|
return qse_httpd_entask (
|
2011-07-30 02:14:04 +00:00
|
|
|
httpd, client, pred, &task, QSE_SIZEOF(data));
|
2011-07-21 10:17:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* TODO: send wide character string when QSE_CHAR_IS_WCHAR */
|
|
|
|
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
|
2012-10-16 08:54:07 +00:00
|
|
|
typedef struct status_reloc_t status_reloc_t;
|
|
|
|
struct status_reloc_t
|
|
|
|
{
|
|
|
|
const qse_mchar_t* dst;
|
|
|
|
int redir;
|
|
|
|
};
|
|
|
|
|
|
|
|
static qse_httpd_task_t* entask_status (
|
2012-01-31 14:32:20 +00:00
|
|
|
qse_httpd_t* httpd, qse_httpd_client_t* client,
|
2012-10-16 08:54:07 +00:00
|
|
|
qse_httpd_task_t* pred, int code, void* extra,
|
2013-03-28 09:43:59 +00:00
|
|
|
qse_http_method_t method, const qse_http_version_t* version,
|
|
|
|
int keepalive)
|
2012-01-31 14:32:20 +00:00
|
|
|
{
|
2012-10-16 08:54:07 +00:00
|
|
|
const qse_mchar_t* msg;
|
2012-01-31 14:32:20 +00:00
|
|
|
|
2012-10-16 08:54:07 +00:00
|
|
|
const qse_mchar_t* extrapre = QSE_MT("");
|
|
|
|
const qse_mchar_t* extrapst = QSE_MT("");
|
|
|
|
const qse_mchar_t* extraval = QSE_MT("");
|
2012-04-05 15:41:53 +00:00
|
|
|
|
2013-03-28 09:43:59 +00:00
|
|
|
qse_mchar_t text[1024] = QSE_MT(""); /* TODO: make this buffer dynamic or scalable */
|
2012-10-16 08:54:07 +00:00
|
|
|
|
|
|
|
msg = qse_httpstatustombs (code);
|
2013-03-28 09:43:59 +00:00
|
|
|
switch (code)
|
2012-10-16 08:54:07 +00:00
|
|
|
{
|
2013-03-28 09:43:59 +00:00
|
|
|
case 301:
|
|
|
|
case 307:
|
2012-10-16 08:54:07 +00:00
|
|
|
{
|
2013-03-28 09:43:59 +00:00
|
|
|
status_reloc_t* reloc;
|
|
|
|
reloc = (status_reloc_t*)extra;
|
|
|
|
extrapre = QSE_MT("Location: ");
|
|
|
|
extrapst = reloc->redir? QSE_MT("/\r\n"): QSE_MT("\r\n");
|
|
|
|
extraval = reloc->dst;
|
|
|
|
break;
|
2012-10-16 08:54:07 +00:00
|
|
|
}
|
2013-03-28 09:43:59 +00:00
|
|
|
|
|
|
|
case 304:
|
|
|
|
case 200:
|
|
|
|
case 201:
|
|
|
|
case 202:
|
|
|
|
case 203:
|
|
|
|
case 204:
|
|
|
|
case 205:
|
|
|
|
case 206:
|
|
|
|
/* nothing to do */
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
if (method != QSE_HTTP_HEAD &&
|
|
|
|
httpd->opt.rcb.fmterr (httpd, client, code, text, QSE_COUNTOF(text)) <= -1) return QSE_NULL;
|
|
|
|
|
|
|
|
if (code == 401)
|
|
|
|
{
|
|
|
|
extrapre = QSE_MT("WWW-Authenticate: Basic realm=\"");
|
|
|
|
extrapst = QSE_MT("\"\r\n");
|
|
|
|
extraval = (const qse_mchar_t*)extra;
|
|
|
|
}
|
|
|
|
break;
|
2012-01-31 14:32:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return qse_httpd_entaskformat (
|
2012-03-18 14:24:54 +00:00
|
|
|
httpd, client, pred,
|
2012-12-04 16:44:59 +00:00
|
|
|
QSE_MT("HTTP/%d.%d %d %s\r\nServer: %s\r\nDate: %s\r\nConnection: %s\r\nContent-Type: text/html\r\nContent-Length: %u\r\n%s%s%s\r\n%s"),
|
2012-10-16 08:54:07 +00:00
|
|
|
version->major, version->minor,
|
|
|
|
code, msg, qse_httpd_getname (httpd),
|
2012-09-13 12:31:01 +00:00
|
|
|
qse_httpd_fmtgmtimetobb (httpd, QSE_NULL, 0),
|
2012-01-31 14:32:20 +00:00
|
|
|
(keepalive? QSE_MT("keep-alive"): QSE_MT("close")),
|
2012-12-04 16:44:59 +00:00
|
|
|
(unsigned int)qse_mbslen(text), /* unsigned int should be large enough since text is small */
|
2012-10-16 08:54:07 +00:00
|
|
|
extrapre, extraval, extrapst, text);
|
|
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
|
2012-10-18 06:52:03 +00:00
|
|
|
qse_httpd_task_t* qse_httpd_entask_err (
|
2012-10-16 08:54:07 +00:00
|
|
|
qse_httpd_t* httpd, qse_httpd_client_t* client,
|
|
|
|
qse_httpd_task_t* pred, int code,
|
2013-03-28 09:43:59 +00:00
|
|
|
qse_http_method_t method, const qse_http_version_t* version, int keepalive)
|
2012-10-16 08:54:07 +00:00
|
|
|
{
|
2013-03-28 09:43:59 +00:00
|
|
|
return entask_status (httpd, client, pred, code, QSE_NULL, method, version, keepalive);
|
2012-01-31 14:32:20 +00:00
|
|
|
}
|
|
|
|
|
2012-10-18 06:52:03 +00:00
|
|
|
qse_httpd_task_t* qse_httpd_entaskerr (
|
2012-01-31 14:32:20 +00:00
|
|
|
qse_httpd_t* httpd, qse_httpd_client_t* client,
|
2012-03-18 14:24:54 +00:00
|
|
|
qse_httpd_task_t* pred, int code, qse_htre_t* req)
|
2012-01-31 14:32:20 +00:00
|
|
|
{
|
2012-10-16 08:54:07 +00:00
|
|
|
return entask_status (
|
|
|
|
httpd, client, pred, code, QSE_NULL,
|
2013-03-28 09:43:59 +00:00
|
|
|
qse_htre_getqmethodtype(req),
|
|
|
|
qse_htre_getversion(req),
|
|
|
|
(req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE)
|
|
|
|
);
|
2012-01-31 14:32:20 +00:00
|
|
|
}
|
|
|
|
|
2012-02-08 12:59:59 +00:00
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
qse_httpd_task_t* qse_httpd_entaskcontinue (
|
|
|
|
qse_httpd_t* httpd, qse_httpd_client_t* client,
|
2012-03-18 14:24:54 +00:00
|
|
|
qse_httpd_task_t* pred, qse_htre_t* req)
|
2012-02-08 12:59:59 +00:00
|
|
|
{
|
2012-02-09 12:54:00 +00:00
|
|
|
const qse_http_version_t* version = qse_htre_getversion(req);
|
2012-02-08 12:59:59 +00:00
|
|
|
return qse_httpd_entaskformat (
|
2012-03-18 14:24:54 +00:00
|
|
|
httpd, client, pred,
|
2012-02-08 12:59:59 +00:00
|
|
|
QSE_MT("HTTP/%d.%d 100 Continue\r\n\r\n"),
|
|
|
|
version->major, version->minor);
|
|
|
|
}
|
|
|
|
|
2012-01-31 14:32:20 +00:00
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
|
2012-02-13 14:43:50 +00:00
|
|
|
qse_httpd_task_t* qse_httpd_entaskauth (
|
|
|
|
qse_httpd_t* httpd, qse_httpd_client_t* client,
|
2012-03-18 14:24:54 +00:00
|
|
|
qse_httpd_task_t* pred, const qse_mchar_t* realm, qse_htre_t* req)
|
2011-07-21 10:17:16 +00:00
|
|
|
{
|
2012-10-16 08:54:07 +00:00
|
|
|
return entask_status (
|
|
|
|
httpd, client, pred, 401, (void*)realm,
|
2013-03-28 09:43:59 +00:00
|
|
|
qse_htre_getqmethodtype(req),
|
2012-10-16 08:54:07 +00:00
|
|
|
qse_htre_getversion(req),
|
|
|
|
(req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE));
|
2011-07-21 10:17:16 +00:00
|
|
|
}
|
|
|
|
|
2012-10-16 08:54:07 +00:00
|
|
|
|
2012-09-12 15:47:41 +00:00
|
|
|
/*------------------------------------------------------------------------*/
|
2012-09-18 13:03:57 +00:00
|
|
|
|
2012-09-25 02:47:25 +00:00
|
|
|
qse_httpd_task_t* qse_httpd_entaskreloc (
|
2012-09-12 15:47:41 +00:00
|
|
|
qse_httpd_t* httpd, qse_httpd_client_t* client,
|
2012-09-25 02:47:25 +00:00
|
|
|
qse_httpd_task_t* pred, const qse_mchar_t* dst, qse_htre_t* req)
|
2012-09-12 15:47:41 +00:00
|
|
|
{
|
2012-10-16 08:54:07 +00:00
|
|
|
status_reloc_t reloc;
|
2012-09-12 15:47:41 +00:00
|
|
|
|
2012-10-16 08:54:07 +00:00
|
|
|
reloc.dst = dst;
|
|
|
|
reloc.redir = 0;
|
2012-09-12 15:47:41 +00:00
|
|
|
|
2012-10-16 08:54:07 +00:00
|
|
|
return entask_status (
|
|
|
|
httpd, client, pred, 301, (void*)&reloc,
|
2013-03-28 09:43:59 +00:00
|
|
|
qse_htre_getqmethodtype(req),
|
2012-10-16 08:54:07 +00:00
|
|
|
qse_htre_getversion(req),
|
|
|
|
(req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE));
|
|
|
|
}
|
|
|
|
|
|
|
|
qse_httpd_task_t* qse_httpd_entaskredir (
|
|
|
|
qse_httpd_t* httpd, qse_httpd_client_t* client,
|
|
|
|
qse_httpd_task_t* pred, const qse_mchar_t* dst, qse_htre_t* req)
|
|
|
|
{
|
|
|
|
status_reloc_t reloc;
|
|
|
|
|
|
|
|
reloc.dst = dst;
|
|
|
|
reloc.redir = 1;
|
|
|
|
|
|
|
|
return entask_status (
|
|
|
|
httpd, client, pred, 301, (void*)&reloc,
|
2013-03-28 09:43:59 +00:00
|
|
|
qse_htre_getqmethodtype(req),
|
2012-10-16 08:54:07 +00:00
|
|
|
qse_htre_getversion(req),
|
|
|
|
(req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE));
|
|
|
|
}
|
|
|
|
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
qse_httpd_task_t* qse_httpd_entask_nomod (
|
2013-03-28 09:43:59 +00:00
|
|
|
qse_httpd_t* httpd, qse_httpd_client_t* client, qse_httpd_task_t* pred,
|
|
|
|
qse_http_method_t method, const qse_http_version_t* version, int keepalive)
|
2012-10-16 08:54:07 +00:00
|
|
|
{
|
|
|
|
return entask_status (
|
2013-03-28 09:43:59 +00:00
|
|
|
httpd, client, pred, 304, QSE_NULL, method, version, keepalive);
|
2012-10-16 08:54:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
qse_httpd_task_t* qse_httpd_entasknomod (
|
|
|
|
qse_httpd_t* httpd, qse_httpd_client_t* client,
|
|
|
|
qse_httpd_task_t* pred, qse_htre_t* req)
|
|
|
|
{
|
|
|
|
return entask_status (
|
2013-03-28 09:43:59 +00:00
|
|
|
httpd, client, pred, 304, QSE_NULL,
|
|
|
|
qse_htre_getqmethodtype(req),
|
|
|
|
qse_htre_getversion(req),
|
2012-10-16 08:54:07 +00:00
|
|
|
(req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE));
|
2012-09-12 15:47:41 +00:00
|
|
|
}
|
2012-09-18 13:03:57 +00:00
|
|
|
|
2012-01-25 15:39:02 +00:00
|
|
|
/*------------------------------------------------------------------------*/
|
2012-02-13 14:43:50 +00:00
|
|
|
|
2013-03-28 09:43:59 +00:00
|
|
|
qse_httpd_task_t* qse_httpd_entaskallow (
|
|
|
|
qse_httpd_t* httpd, qse_httpd_client_t* client,
|
|
|
|
qse_httpd_task_t* pred, const qse_mchar_t* allow, qse_htre_t* req)
|
|
|
|
{
|
|
|
|
int code = 200;
|
|
|
|
const qse_mchar_t* msg;
|
|
|
|
const qse_http_version_t* version;
|
|
|
|
int keepalive;
|
|
|
|
|
|
|
|
msg = qse_httpstatustombs (code);
|
|
|
|
version = qse_htre_getversion(req);
|
|
|
|
keepalive = (req->attr.flags & QSE_HTRE_ATTR_KEEPALIVE);
|
|
|
|
return qse_httpd_entaskformat (
|
|
|
|
httpd, client, pred,
|
|
|
|
QSE_MT("HTTP/%d.%d %d %s\r\nServer: %s\r\nDate: %s\r\nConnection: %s\r\nAllow: %s\r\nContent-Length: 0\r\n\r\n"),
|
|
|
|
version->major, version->minor,
|
|
|
|
code, msg, qse_httpd_getname (httpd),
|
|
|
|
qse_httpd_fmtgmtimetobb (httpd, QSE_NULL, 0),
|
|
|
|
(keepalive? QSE_MT("keep-alive"): QSE_MT("close")),
|
|
|
|
allow
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
|
2012-04-13 15:21:36 +00:00
|
|
|
#if 0
|
|
|
|
qse_httpd_task_t* qse_httpd_entaskconnect (
|
|
|
|
qse_httpd_t* httpd,
|
|
|
|
qse_httpd_client_t* client,
|
|
|
|
qse_httpd_task_t* pred,
|
|
|
|
const qse_nwad_t* nwad,
|
|
|
|
qse_htre_t* req)
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2012-09-25 02:47:25 +00:00
|
|
|
|
|
|
|
qse_httpd_task_t* qse_httpd_entaskrsrc (
|
|
|
|
qse_httpd_t* httpd,
|
|
|
|
qse_httpd_client_t* client,
|
|
|
|
qse_httpd_task_t* pred,
|
|
|
|
qse_httpd_rsrc_t* rsrc,
|
|
|
|
qse_htre_t* req)
|
|
|
|
{
|
|
|
|
qse_httpd_task_t* task;
|
|
|
|
|
|
|
|
switch (rsrc->type)
|
|
|
|
{
|
|
|
|
case QSE_HTTPD_RSRC_AUTH:
|
2013-01-30 14:08:38 +00:00
|
|
|
task = qse_httpd_entaskauth (httpd, client, pred, rsrc->u.auth.realm, req);
|
2012-09-25 02:47:25 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case QSE_HTTPD_RSRC_CGI:
|
2013-01-30 14:08:38 +00:00
|
|
|
task = qse_httpd_entaskcgi (httpd, client, pred, &rsrc->u.cgi, req);
|
2012-09-25 02:47:25 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case QSE_HTTPD_RSRC_DIR:
|
2013-01-30 14:08:38 +00:00
|
|
|
task = qse_httpd_entaskdir (httpd, client, pred, rsrc->u.dir.path, req);
|
2012-09-25 02:47:25 +00:00
|
|
|
break;
|
|
|
|
|
2012-10-18 06:52:03 +00:00
|
|
|
case QSE_HTTPD_RSRC_ERR:
|
2013-01-30 14:08:38 +00:00
|
|
|
task = qse_httpd_entaskerr (httpd, client, pred, rsrc->u.err.code, req);
|
2012-10-01 13:30:44 +00:00
|
|
|
break;
|
2012-09-25 02:47:25 +00:00
|
|
|
|
|
|
|
case QSE_HTTPD_RSRC_FILE:
|
2013-01-30 14:08:38 +00:00
|
|
|
task = qse_httpd_entaskfile (httpd, client, pred, rsrc->u.file.path, rsrc->u.file.mime, req);
|
2012-09-25 02:47:25 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case QSE_HTTPD_RSRC_PROXY:
|
2013-01-30 14:08:38 +00:00
|
|
|
task = qse_httpd_entaskproxy (httpd, client, pred, &rsrc->u.proxy.dst, &rsrc->u.proxy.src, req);
|
2012-09-25 02:47:25 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case QSE_HTTPD_RSRC_RELOC:
|
2013-01-30 14:08:38 +00:00
|
|
|
task = qse_httpd_entaskreloc (httpd, client, pred, rsrc->u.reloc.dst, req);
|
2012-09-25 02:47:25 +00:00
|
|
|
break;
|
|
|
|
|
2012-10-16 08:54:07 +00:00
|
|
|
case QSE_HTTPD_RSRC_REDIR:
|
2013-01-30 14:08:38 +00:00
|
|
|
task = qse_httpd_entaskredir (httpd, client, pred, rsrc->u.redir.dst, req);
|
2012-10-16 08:54:07 +00:00
|
|
|
break;
|
|
|
|
|
2012-09-25 02:47:25 +00:00
|
|
|
case QSE_HTTPD_RSRC_TEXT:
|
2013-01-30 14:08:38 +00:00
|
|
|
task = qse_httpd_entasktext (httpd, client, pred, rsrc->u.text.ptr, rsrc->u.text.mime, req);
|
2012-09-25 02:47:25 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
qse_httpd_discardcontent (httpd, req);
|
|
|
|
task = QSE_NULL;
|
|
|
|
httpd->errnum = QSE_HTTPD_EINVAL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return task;
|
|
|
|
}
|