⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 wwwapi.cpp

📁 实现内存数据库的源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//-< 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;
}

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;
}


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];
	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(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;
	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;
	      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 = items(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;
}

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 = ((src[0] >= 'A' ? src[0] - 'A'+ 10 : src[0] - '0') << 4) |
		     (src[1] >= 'A' ? src[1] - 'A'+ 10 : src[1] - '0');
		src += 2;
	    }
	    *dst++ = ch;
	}
	*dst = '\0';
	char* value = dst = src;
	while (src < end && (ch = *src++) != '&') { 
	    if (ch == '+') {
		ch = ' ';
	    } else if (ch == '%') { 
		ch = ((src[0] >= 'A' ? src[0] - 'A'+ 10 : src[0] - '0') << 4) |
		     (src[1] >= 'A' ? src[1] - 'A'+ 10 : src[1] - '0');
		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)) 
    {
	return true;
    }
    int size = length - sizeof length;
    char* buf = new char[size];
    if (con.sock->read(buf, size, size) != size) {
	return true;
    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -