/*
* Copyright (c) 2004-2005 Sergey Lyubka <valenok@gmail.com>
* All rights reserved
*
* "THE BEER-WARE LICENSE" (Revision 42):
* Sergey Lyubka wrote this file. As long as you retain this notice you
* can do whatever you want with this stuff. If we meet some day, and you think
* this stuff is worth it, you can buy me a beer in return.
*/
/*
* Small and portable HTTP server, http://shttpd.sourceforge.net
* $Id: shttpd.c,v 1.57 2008/08/23 21:00:38 drozd Exp $
*/
#include "defs.h"
time_t _shttpd_current_time; /* Current UTC time */
int _shttpd_tz_offset; /* Time zone offset from UTC */
int _shttpd_exit_flag; /* Program exit flag */
const struct vec _shttpd_known_http_methods[] = {
{"GET", 3},
{"POST", 4},
{"PUT", 3},
{"DELETE", 6},
{"HEAD", 4},
{NULL, 0}
};
/*
* This structure tells how HTTP headers must be parsed.
* Used by parse_headers() function.
*/
#define OFFSET(x) offsetof(struct headers, x)
static const struct http_header http_headers[] = {
{16, HDR_INT, OFFSET(cl), "Content-Length: " },
{14, HDR_STRING, OFFSET(ct), "Content-Type: " },
{12, HDR_STRING, OFFSET(useragent), "User-Agent: " },
{19, HDR_DATE, OFFSET(ims), "If-Modified-Since: " },
{15, HDR_STRING, OFFSET(auth), "Authorization: " },
{9, HDR_STRING, OFFSET(referer), "Referer: " },
{8, HDR_STRING, OFFSET(cookie), "Cookie: " },
{10, HDR_STRING, OFFSET(location), "Location: " },
{8, HDR_INT, OFFSET(status), "Status: " },
{7, HDR_STRING, OFFSET(range), "Range: " },
{12, HDR_STRING, OFFSET(connection), "Connection: " },
{19, HDR_STRING, OFFSET(transenc), "Transfer-Encoding: " },
{0, HDR_INT, 0, NULL }
};
struct shttpd_ctx *init_ctx(const char *config_file, int argc, char *argv[]);
static void process_connection(struct conn *, int, int);
int
_shttpd_is_true(const char *str)
{
static const char *trues[] = {"1", "yes", "true", "jawohl", NULL};
const char **p;
for (p = trues; *p != NULL; p++)
if (str && !strcmp(str, *p))
return (TRUE);
return (FALSE);
}
static void
free_list(struct llhead *head, void (*dtor)(struct llhead *))
{
struct llhead *lp, *tmp;
LL_FOREACH_SAFE(head, lp, tmp) {
LL_DEL(lp);
dtor(lp);
}
}
static void
listener_destructor(struct llhead *lp)
{
struct listener *listener = LL_ENTRY(lp, struct listener, link);
(void) closesocket(listener->sock);
free(listener);
}
static void
registered_uri_destructor(struct llhead *lp)
{
struct registered_uri *ruri = LL_ENTRY(lp, struct registered_uri, link);
free((void *) ruri->uri);
free(ruri);
}
static void
acl_destructor(struct llhead *lp)
{
struct acl *acl = LL_ENTRY(lp, struct acl, link);
free(acl);
}
int
_shttpd_url_decode(const char *src, int src_len, char *dst, int dst_len)
{
int i, j, a, b;
#define HEXTOI(x) (isdigit(x) ? x - '0' : x - 'W')
for (i = j = 0; i < src_len && j < dst_len - 1; i++, j++)
switch (src[i]) {
case '%':
if (isxdigit(((unsigned char *) src)[i + 1]) &&
isxdigit(((unsigned char *) src)[i + 2])) {
a = tolower(((unsigned char *)src)[i + 1]);
b = tolower(((unsigned char *)src)[i + 2]);
dst[j] = (HEXTOI(a) << 4) | HEXTOI(b);
i += 2;
} else {
dst[j] = '%';
}
break;
default:
dst[j] = src[i];
break;
}
dst[j] = '\0'; /* Null-terminate the destination */
return (j);
}
static const char *
is_alias(struct shttpd_ctx *ctx, const char *uri,
struct vec *a_uri, struct vec *a_path)
{
const char *p, *s = ctx->options[OPT_ALIASES];
size_t len;
DBG(("is_alias: aliases [%s]", s == NULL ? "" : s));
FOR_EACH_WORD_IN_LIST(s, len) {
if ((p = memchr(s, '=', len)) == NULL || p >= s + len || p == s)
continue;
if (memcmp(uri, s, p - s) == 0) {
a_uri->ptr = s;
a_uri->len = p - s;
a_path->ptr = ++p;
a_path->len = (s + len) - p;
return (s);
}
}
return (NULL);
}
void
_shttpd_stop_stream(struct stream *stream)
{
if (stream->io_class != NULL && stream->io_class->close != NULL)
stream->io_class->close(stream);
stream->io_class= NULL;
stream->flags |= FLAG_CLOSED;
stream->flags &= ~(FLAG_R | FLAG_W | FLAG_ALWAYS_READY);
DBG(("%d %s stopped. %lu of content data, %d now in a buffer",
stream->conn->rem.chan.sock,
stream->io_class ? stream->io_class->name : "(null)",
(unsigned long) stream->io.total, (int) io_data_len(&stream->io)));
}
/*
* Setup listening socket on given port, return socket
*/
static int
shttpd_open_listening_port(int port)
{
int sock, on = 1;
struct usa sa;
#ifdef _WIN32
{WSADATA data; WSAStartup(MAKEWORD(2,2), &data);}
#endif /* _WIN32 */
sa.len = sizeof(sa.u.sin);
sa.u.sin.sin_family = AF_INET;
sa.u.sin.sin_port = htons((uint16_t) port);
sa.u.sin.sin_addr.s_addr = htonl(INADDR_ANY);
if ((sock = socket(PF_INET, SOCK_STREAM, 6)) == -1)
goto fail;
if (_shttpd_set_non_blocking_mode(sock) != 0)
goto fail;
if (setsockopt(sock, SOL_SOCKET,
SO_REUSEADDR,(char *) &on, sizeof(on)) != 0)
goto fail;
if (bind(sock, &sa.u.sa, sa.len) < 0)
goto fail;
if (listen(sock, 128) != 0)
goto fail;
#ifndef _WIN32
(void) fcntl(sock, F_SETFD, FD_CLOEXEC);
#endif /* !_WIN32 */
return (sock);
fail:
if (sock != -1)
(void) closesocket(sock);
_shttpd_elog(E_LOG, NULL, "open_listening_port(%d): %s", port, strerror(errno));
return (-1);
}
/*
* Check whether full request is buffered Return headers length, or 0
*/
int
_shttpd_get_headers_len(const char *buf, size_t buflen)
{
const char *s, *e;
int len = 0;
for (s = buf, e = s + buflen - 1; len == 0 && s < e; s++)
/* Control characters are not allowed but >=128 is. */
if (!isprint(* (unsigned char *) s) && *s != '\r' &&
*s != '\n' && * (unsigned char *) s < 128)
len = -1;
else if (s[0] == '\n' && s[1] == '\n')
len = s - buf + 2;
else if (s[0] == '\n' && &s[1] < e &&
s[1] == '\r' && s[2] == '\n')
len = s - buf + 3;
return (len);
}
/*
* Send error message back to a client.
*/
void
_shttpd_send_server_error(struct conn *c, int status, const char *reason)
{
struct llhead *lp;
struct error_handler *e;
LL_FOREACH(&c->ctx->error_handlers, lp) {
e = LL_ENTRY(lp, struct error_handler, link);
if (e->code == status) {
if (c->loc.io_class != NULL &&
c->loc.io_class->close != NULL)
c->loc.io_class->close(&c->loc);
io_clear(&c->loc.io);
_shttpd_setup_embedded_stream(c,
e->callback, e->callback_data);
return;
}
}
io_clear(&c->loc.io);
c->loc.io.head = _shttpd_snprintf(c->loc.io.buf, c->loc.io.size,
"HTTP/1.1 %d %s\r\n"
"Content-Type: text/plain\r\n"
"Content-Length: 12\r\n"
"\r\n"
"Error: %03d\r\n",
status, reason, status);
c->loc.content_len = 10;
c->status = status;
_shttpd_stop_stream(&c->loc);
}
/*
* Convert month to the month number. Return -1 on error, or month number
*/
static int
montoi(const char *s)
{
static const char *ar[] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
size_t i;
for (i = 0; i < sizeof(ar) / sizeof(ar[0]); i++)
if (!strcmp(s, ar[i]))
return (i);
return (-1);
}
/*
* Parse date-time string, and return the corresponding time_t value
*/
static time_t
date_to_epoch(const char *s)
{
struct tm tm, *tmp;
char mon[32];
int sec, min, hour, mday, month, year;
(void) memset(&tm, 0, sizeof(tm));
sec = min = hour = mday = month = year = 0;
if (((sscanf(s, "%d/%3s/%d %d:%d:%d",
&mday, mon, &year, &hour, &min, &sec) == 6) ||
(sscanf(s, "%d %3s %d %d:%d:%d",
&mday, mon, &year, &hour, &min, &sec) == 6) ||
(sscanf(s, "%*3s, %d %3s %d %d:%d:%d",
&mday, mon, &year, &hour, &min, &sec) == 6) ||
(sscanf(s, "%d-%3s-%d %d:%d:%d",
&mday, mon, &year, &hour, &min, &sec) == 6)) &&
(month = montoi(mon)) != -1) {
tm.tm_mday = mday;
tm.tm_mon = month;
tm.tm_year = year;
tm.tm_hour = hour;
tm.tm_min = min;
tm.tm_sec = sec;
}
if (tm.tm_year > 1900)
tm.tm_year -= 1900;
else if (tm.tm_year < 70)
tm.tm_year += 100;
/* S
没有合适的资源?快使用搜索试试~ 我知道了~
资源推荐
资源详情
资源评论
收起资源包目录
shttpd.1.42.7z (41个子文件)
shttpd
CHANGELOG 7KB
src
md5.h 714B
config.h 1KB
compat_win32.c 16KB
io_ssi.c 11KB
cgi.c 6KB
auth.c 10KB
llist.h 1KB
compat_unix.c 2KB
std_includes.h 1KB
shttpd.h 4KB
compat_rtems.h 2KB
compat_rtems.c 5KB
compat_wince.h 4KB
io_emb.c 7KB
io_socket.c 917B
shttpd.1 7KB
string.c 2KB
compat_wince.c 40KB
compat_unix.h 950B
io.h 2KB
io_cgi.c 3KB
log.c 2KB
compat_win32.h 2KB
io_ssl.c 2KB
md5.c 7KB
Makefile 2KB
defs.h 12KB
shttpd.c 50KB
io_file.c 4KB
io_dir.c 4KB
standalone.c 2KB
ssl.h 2KB
README 369B
examples
example_win32_dialog_app.c 875B
passfile 195B
example.c 11KB
ssi_test.shtml 144B
dialog.rc 273B
Makefile 446B
COPYING 247B
共 41 条
- 1
资源评论
- zhangxuyu11182016-07-15这份资源我也有, 编译时"set_ssl"有问题。后来我自己更改makefile后才可以的。
- yaoyanchun12016-03-23不错,谢谢了
- wq_143653272013-10-11提供的资源可以使用
- mingzi1501102012-12-21是源代码,不过shttpd已经更新了,叫mongoose
- gengzhiwei2013-06-09我在 google 里面有搜索一份,和这个代码一样的,不错啊
bobo463
- 粉丝: 0
- 资源: 2
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功