📄 wwwapi.cpp
字号:
//-< WWWAPI.CPP >----------------------------------------------------*--------*// FastDB Version 1.0 (c) 1999 GARRET * ? *// (Main Memory Database Management System) * /\| *// * / \ *// Created: 27-Mar-99 K.A. Knizhnik * / [] \ *// Last update: 1-Jul-99 K.A. Knizhnik * GARRET *//-------------------------------------------------------------------*--------*// Implementation of WWWapi class//-------------------------------------------------------------------*--------*#define INSIDE_FASTDB#include "wwwapi.h"#include <ctype.h>const size_t init_reply_buffer_size = 4*1024;inline unsigned string_hash_function(const char* name){ unsigned h = 0, g; while(*name) { h = (h << 4) + *name++; if ((g = h & 0xF0000000) != 0) { h ^= g >> 24; } h &= ~g; } return h;}#define ERROR_TEXT(x) \"HTTP/1.1 " x "\r\n\Connection: close\r\n\r\n\<HTML><HEAD><TITLE>Invalid request to the database</TITLE>\r\n\</HEAD><BODY>\n\r\<H1>" x "</H1>\n\r\</BODY></HTML>\r\n\r\n"WWWconnection::WWWconnection(){ memset(hash_table, 0, sizeof hash_table); sock = NULL; reply_buf = new char[init_reply_buffer_size]; reply_buf_size = init_reply_buffer_size; free_pairs = NULL; peer = NULL; userData = NULL; userDataDestructor = NULL;}WWWconnection::~WWWconnection(){ reset(); name_value_pair *nvp, *next; for (nvp = free_pairs; nvp != NULL; nvp = next) { next = nvp->next; delete nvp; } delete[] reply_buf; delete[] peer; if (userDataDestructor != NULL && userData != NULL) { userDataDestructor(userData); }}inline char* WWWconnection::extendBuffer(size_t inc){ if (reply_buf_used + inc >= reply_buf_size) { reply_buf_size = reply_buf_size*2 > reply_buf_used + inc ? reply_buf_size*2 : reply_buf_used + inc; char* new_buf = new char[reply_buf_size+1]; memcpy(new_buf, reply_buf, reply_buf_used); delete[] reply_buf; reply_buf = new_buf; } reply_buf_used += inc; return reply_buf;}bool WWWconnection::terminatedBy(char const* str) const{ size_t len = strlen(str); if (len > reply_buf_used - 4) { return false; } return memcmp(reply_buf + reply_buf_used - len, str, len) == 0;}WWWconnection& WWWconnection::append(const void *buf, int len) { int pos = reply_buf_used; char *dst = extendBuffer(len); memcpy(dst + pos, buf, len); return *this;}WWWconnection& WWWconnection::append(char const* str) { int pos = reply_buf_used; char* dst = extendBuffer(strlen(str)); unsigned char ch; switch (encoding) { case TAG: strcpy(dst + pos, str); encoding = HTML; break; case HTML: encoding = TAG;#if 1 // MS-Explorer handle " " in HTML string literals in very strange way if (str[0] == ' ' && str[1] == '\0') { strcpy(extendBuffer(5) + pos, " "); return *this; }#endif while (true) { switch(ch = *str++) { case '<': dst = extendBuffer(3); dst[pos++] = '&'; dst[pos++] = 'l'; dst[pos++] = 't'; dst[pos++] = ';'; break; case '>': dst = extendBuffer(3); dst[pos++] = '&'; dst[pos++] = 'g'; dst[pos++] = 't'; dst[pos++] = ';'; break; case '&': dst = extendBuffer(4); dst[pos++] = '&'; dst[pos++] = 'a'; dst[pos++] = 'm'; dst[pos++] = 'p'; dst[pos++] = ';'; break; case '"': dst = extendBuffer(5); dst[pos++] = '&'; dst[pos++] = 'q'; dst[pos++] = 'u'; dst[pos++] = 'o'; dst[pos++] = 't'; dst[pos++] = ';'; break; case '\0': dst[pos] = '\0'; return *this;#if 0 // MS-Explorer handle " " in HTML string literals in very strange way case ' ': dst = extendBuffer(5); dst[pos++] = '&'; dst[pos++] = 'n'; dst[pos++] = 'b'; dst[pos++] = 's'; dst[pos++] = 'p'; dst[pos++] = ';'; break; #endif default: dst[pos++] = ch; } } case URL: encoding = TAG; while (true) { ch = *str++; if (ch == '\0') { dst[pos] = '\0'; return *this; } else if (ch == ' ') { dst[pos++] = '+'; } else if (!isalnum(ch)) { dst = extendBuffer(2); dst[pos++] = '%'; dst[pos++] = (ch >> 4) >= 10 ? (ch >> 4) + 'A' - 10 : (ch >> 4) + '0'; dst[pos++] = (ch & 0xF) >= 10 ? (ch & 0xF) + 'A' - 10 : (ch & 0xF) + '0'; } else { dst[pos++] = ch; } } } return *this;}void WWWconnection::reset(){ reply_buf_used = 0; encoding = TAG; for (int i = itemsof(hash_table); --i >= 0;) { name_value_pair *nvp, *next; for (nvp = hash_table[i]; nvp != NULL; nvp = next) { next = nvp->next; nvp->next = free_pairs; free_pairs = nvp; } hash_table[i] = NULL; } }void WWWconnection::addPair(char const* name, char const* value){ name_value_pair* nvp; if (free_pairs != NULL) { nvp = free_pairs; free_pairs = nvp->next; } else { nvp = new name_value_pair; } unsigned hash_code = string_hash_function(name); nvp->hash_code = hash_code; hash_code %= hash_table_size; nvp->next = hash_table[hash_code]; hash_table[hash_code] = nvp; nvp->value = value; nvp->name = name;}#define HEX_DIGIT(ch) ((ch) >= 'a' ? ((ch) - 'a' + 10) : (ch) >= 'A' ? ((ch) - 'A' + 10) : ((ch) - '0'))char* WWWconnection::unpack(char* body, size_t length){ char *src = body, *end = body + length; while (src < end) { char* name = src; char ch; char* dst = src; while (src < end && (ch = *src++) != '=') { if (ch == '+') { ch = ' '; } else if (ch == '%') { ch = (HEX_DIGIT(src[0]) << 4) | HEX_DIGIT(src[1]); src += 2; } *dst++ = ch; } *dst = '\0'; char* value = dst = src; while (src < end && (ch = *src++) != '&') { if (ch == '+') { ch = ' '; } else if (ch == '%') { ch = (HEX_DIGIT(src[0]) << 4) | HEX_DIGIT(src[1]); src += 2; } *dst++ = ch; } *dst = '\0'; addPair(name, value); } stub = get("stub"); return get("page");}char* WWWconnection::get(char const* name, int n){ unsigned hash_code = string_hash_function(name); name_value_pair* nvp; for (nvp = hash_table[hash_code % hash_table_size]; nvp != NULL; nvp = nvp->next) { if (nvp->hash_code == hash_code && strcmp(nvp->name, name) == 0) { if (n == 0) { return (char*)nvp->value; } n -= 1; } } return NULL;} //--------------------------------------------------WWWapi::WWWapi(dbDatabase& dbase, int n_handlers, dispatcher* dispatch_table): db(dbase){ memset(hash_table, 0, sizeof hash_table); sock = NULL; address = NULL; dispatcher* disp = dispatch_table; while (--n_handlers >= 0) { unsigned hash_code = string_hash_function(disp->page); disp->hash_code = hash_code; hash_code %= hash_table_size; disp->collision_chain = hash_table[hash_code]; hash_table[hash_code] = disp; disp += 1; }}bool WWWapi::open(char const* socket_address, socket_t::socket_domain domain, int listen_queue){ if (sock != NULL) { close(); } address = new char[strlen(socket_address) + 1]; strcpy(address, socket_address); sock = domain != socket_t::sock_global_domain ? socket_t::create_local(socket_address, listen_queue) : socket_t::create_global(socket_address, listen_queue); canceled = false; if (!sock->is_ok()) { char buf[64]; sock->get_error_text(buf, sizeof buf); fprintf(stderr, "WWWapi::open: create socket failed: %s\n", buf); return false; } return true; }bool WWWapi::connect(WWWconnection& con){ assert(sock != NULL); con.reset(); delete con.sock; con.sock = sock->accept(); con.address = address; if (con.sock == NULL) { if (!canceled) { char buf[64]; sock->get_error_text(buf, sizeof buf); fprintf(stderr, "WWWapi::connect: accept failed: %s\n", buf); } return false; } return true;}void WWWapi::cancel(){ canceled = true; sock->cancel_accept();}void WWWapi::close(){ delete sock; delete[] address; sock = NULL;}bool WWWapi::dispatch(WWWconnection& con, char* page){ unsigned hash_code = string_hash_function(page); for (dispatcher* disp = hash_table[hash_code % hash_table_size]; disp != NULL; disp = disp->collision_chain) { if (disp->hash_code == hash_code && strcmp(disp->page, page) == 0) { bool result = disp->func(con); db.commit(); return result; } } return true;}void URL2ASCII(char* src){ char* dst = src; char ch; while ((ch = *src++) != '\0') { if (ch == '%') { *dst++ = ((src[0] - '0') << 8) | (src[1] - '0'); } else if (ch == '+') { *dst++ = ' '; } else if (ch == '.' && *src == '.') { // for security reasons do not allow access to parent directory break; } else { *dst++ = ch; } } *dst = '\0';}bool CGIapi::serve(WWWconnection& con){ nat4 length; con.reset(); if ((size_t)con.sock->read(&length, sizeof length, sizeof length) != sizeof(length))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -