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

📄 wwwapi.cpp

📁 最新版本!fastdb是高效的内存数据库系统
💻 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>

BEGIN_FASTDB_NAMESPACE

const size_t init_reply_buffer_size = 4*1024;
const time_t ACCEPT_FAILURE_TIMEOUT = 1; // second

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 "&nbsp;" in HTML string literals in very strange way
        if (str[0] == ' ' && str[1] == '\0') { 
            strcpy(extendBuffer(5) + pos, "&nbsp;");
            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 "&nbsp;" 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;
    }
}

WWWapi::~WWWapi() {}

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 + -