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

📄 http.c

📁 一个很好用的解析
💻 C
📖 第 1 页 / 共 2 页
字号:
/* Copyright information is at the end of the file */#include <ctype.h>#include <assert.h>#include <stdlib.h>#include <stdio.h>#include <string.h>#include <errno.h>#include <time.h>#include "xmlrpc_config.h"#include "mallocvar.h"#include "xmlrpc-c/string_int.h"#include "xmlrpc-c/abyss.h"#include "server.h"#include "session.h"#include "conn.h"#include "token.h"#include "date.h"#include "data.h"#include "abyss_info.h"#include "http.h"/*********************************************************************** Request Parser*********************************************************************//*********************************************************************** Request*********************************************************************/static voidinitRequestInfo(TRequestInfo * const requestInfoP,                httpVersion    const httpVersion,                const char *   const requestLine,                TMethod        const httpMethod,                const char *   const host,                unsigned int   const port,                const char *   const path,                const char *   const query) {/*----------------------------------------------------------------------------  Set up the request info structure.  For information that is  controlled by headers, use the defaults -- I.e. the value that  applies if the request contains no applicable header.-----------------------------------------------------------------------------*/    requestInfoP->requestline = requestLine;    requestInfoP->method      = httpMethod;    requestInfoP->host        = host;    requestInfoP->port        = port;    requestInfoP->uri         = path;    requestInfoP->query       = query;    requestInfoP->from        = NULL;    requestInfoP->useragent   = NULL;    requestInfoP->referer     = NULL;    requestInfoP->user        = NULL;    if (httpVersion.major > 1 ||        (httpVersion.major == 1 && httpVersion.minor >= 1))        requestInfoP->keepalive = TRUE;    else        requestInfoP->keepalive = FALSE;}static voidfreeRequestInfo(TRequestInfo * const requestInfoP) {    if (requestInfoP->requestline)        xmlrpc_strfree(requestInfoP->requestline);    if (requestInfoP->user)        xmlrpc_strfree(requestInfoP->user);}voidRequestInit(TSession * const sessionP,            TConn *    const connectionP) {    time_t nowtime;    sessionP->validRequest = false;  /* Don't have valid request yet */    time(&nowtime);    sessionP->date = *gmtime(&nowtime);    sessionP->conn = connectionP;    sessionP->responseStarted = FALSE;    sessionP->chunkedwrite = FALSE;    sessionP->chunkedwritemode = FALSE;    ListInit(&sessionP->cookies);    ListInit(&sessionP->ranges);    TableInit(&sessionP->request_headers);    TableInit(&sessionP->response_headers);    sessionP->status = 0;  /* No status from handler yet */    StringAlloc(&(sessionP->header));}voidRequestFree(TSession * const sessionP) {    if (sessionP->validRequest)        freeRequestInfo(&sessionP->request_info);    ListFree(&sessionP->cookies);    ListFree(&sessionP->ranges);    TableFree(&sessionP->request_headers);    TableFree(&sessionP->response_headers);    StringFree(&(sessionP->header));}static voidreadRequestLine(TSession *   const sessionP,                char **      const requestLineP,                uint16_t *   const httpErrorCodeP) {    *httpErrorCodeP = 0;    /* Ignore CRLFs in the beginning of the request (RFC2068-P30) */    do {        abyss_bool success;        success = ConnReadHeader(sessionP->conn, requestLineP);        if (!success)            *httpErrorCodeP = 408;  /* Request Timeout */    } while (!*httpErrorCodeP && (*requestLineP)[0] == '\0');}static voidunescapeUri(char *       const uri,            abyss_bool * const errorP) {    char * x;    char * y;    x = y = uri;        *errorP = FALSE;    while (*x && !*errorP) {        switch (*x) {        case '%': {            char c;            ++x;            c = tolower(*x++);            if ((c >= '0') && (c <= '9'))                c -= '0';            else if ((c >= 'a') && (c <= 'f'))                c -= 'a' - 10;            else                *errorP = TRUE;            if (!*errorP) {                char d;                d = tolower(*x++);                if ((d >= '0') && (d <= '9'))                    d -= '0';                else if ((d >= 'a') && (d <= 'f'))                    d -= 'a' - 10;                else                    *errorP = TRUE;                if (!*errorP)                    *y++ = ((c << 4) | d);            }        } break;        default:            *y++ = *x++;            break;        }    }    *y = '\0';}static voidparseHostPort(char *           const hostport,              const char **    const hostP,              unsigned short * const portP,              uint16_t *       const httpErrorCodeP) {        char * colonPos;    colonPos = strchr(hostport, ':');    if (colonPos) {        const char * p;        uint32_t port;        *colonPos = '\0';  /* Split hostport at the colon */        *hostP = hostport;        for (p = colonPos + 1, port = 0;             isdigit(*p) && port < 65535;             (port = port * 10 + (*p - '0')), ++p);                    *portP = port;        if (*p || port == 0)            *httpErrorCodeP = 400;  /* Bad Request */        else            *httpErrorCodeP = 0;    } else {        *hostP          = hostport;        *portP          = 80;        *httpErrorCodeP = 0;    }}static voidparseRequestUri(char *           const requestUri,                const char **    const hostP,                const char **    const pathP,                const char **    const queryP,                unsigned short * const portP,                uint16_t *       const httpErrorCodeP) {/*----------------------------------------------------------------------------  Parse the request URI (in the request line  "GET http://www.myserver.com/myfile?parm HTTP/1.1",  "http://www.myserver.com/myfile?parm" is the request URI).  This destroys *requestUri and returns pointers into *requestUri!  This is extremely ugly.  We need to redo it with dynamically allocated  storage.  We should return individual malloc'ed strings.-----------------------------------------------------------------------------*/    abyss_bool error;    unescapeUri(requestUri, &error);        if (error)        *httpErrorCodeP = 400;  /* Bad Request */    else {        char * requestUriNoQuery;           /* The request URI with any query (the stuff marked by a question              mark at the end of a request URI) chopped off.           */        {            /* Split requestUri at the question mark */            char * const qmark = strchr(requestUri, '?');                        if (qmark) {                *qmark = '\0';                *queryP = qmark + 1;            } else                *queryP = NULL;        }                requestUriNoQuery = requestUri;        if (requestUriNoQuery[0] == '/') {            *hostP = NULL;            *pathP = requestUriNoQuery;            *portP = 80;        } else {            if (!xmlrpc_strneq(requestUriNoQuery, "http://", 7))                *httpErrorCodeP = 400;  /* Bad Request */            else {                char * const hostportpath = &requestUriNoQuery[7];                char * const slashPos = strchr(hostportpath, '/');                char * hostport;                                if (slashPos) {                    char * p;                    *pathP = slashPos;                                        /* Nul-terminate the host name.  To make space for                       it, slide the whole name back one character.                       This moves it into the space now occupied by                       the end of "http://", which we don't need.                    */                    for (p = hostportpath; *p != '/'; ++p)                        *(p-1) = *p;                    *(p-1) = '\0';                                        hostport = hostportpath - 1;                    *httpErrorCodeP = 0;                } else {                    *pathP = "*";                    hostport = hostportpath;                    *httpErrorCodeP = 0;                }                if (!*httpErrorCodeP)                    parseHostPort(hostport, hostP, portP, httpErrorCodeP);            }        }    }}static voidparseRequestLine(char *           const requestLine,                 TMethod *        const httpMethodP,                 httpVersion *    const httpVersionP,                 const char **    const hostP,                 unsigned short * const portP,                 const char **    const pathP,                 const char **    const queryP,                 abyss_bool *     const moreLinesP,                 uint16_t *       const httpErrorCodeP) {/*----------------------------------------------------------------------------   Modifies *header1 and returns pointers to its storage!-----------------------------------------------------------------------------*/    const char * httpMethodName;    char * p;    p = requestLine;    /* Jump over spaces */    NextToken((const char **)&p);    httpMethodName = GetToken(&p);    if (!httpMethodName)        *httpErrorCodeP = 400;  /* Bad Request */    else {        char * requestUri;        if (xmlrpc_streq(httpMethodName, "GET"))            *httpMethodP = m_get;        else if (xmlrpc_streq(httpMethodName, "PUT"))            *httpMethodP = m_put;        else if (xmlrpc_streq(httpMethodName, "OPTIONS"))            *httpMethodP = m_options;        else if (xmlrpc_streq(httpMethodName, "DELETE"))            *httpMethodP = m_delete;        else if (xmlrpc_streq(httpMethodName, "POST"))            *httpMethodP = m_post;        else if (xmlrpc_streq(httpMethodName, "TRACE"))            *httpMethodP = m_trace;        else if (xmlrpc_streq(httpMethodName, "HEAD"))            *httpMethodP = m_head;        else            *httpMethodP = m_unknown;                /* URI and Query Decoding */        NextToken((const char **)&p);                requestUri = GetToken(&p);        if (!requestUri)            *httpErrorCodeP = 400;  /* Bad Request */        else {            parseRequestUri(requestUri, hostP, pathP, queryP, portP,                            httpErrorCodeP);            if (!*httpErrorCodeP) {                const char * httpVersion;                NextToken((const char **)&p);                        /* HTTP Version Decoding */                                httpVersion = GetToken(&p);                if (httpVersion) {                    uint32_t vmin, vmaj;                    if (sscanf(httpVersion, "HTTP/%d.%d", &vmaj, &vmin) != 2)                        *httpErrorCodeP = 400;  /* Bad Request */                    else {                        httpVersionP->major = vmaj;                        httpVersionP->minor = vmin;                        *httpErrorCodeP = 0;  /* no error */                    }                    *moreLinesP = TRUE;                } else {                    /* There is no HTTP version, so this is a single                       line request.                    */                    *httpErrorCodeP = 0;  /* no error */                    *moreLinesP = FALSE;                }            }        }    }}static voidstrtolower(char * const s) {    char * t;    t = &s[0];    while (*t) {        *t = tolower(*t);        ++t;    }}static voidgetFieldNameToken(char **    const pP,                  char **    const fieldNameP,                  uint16_t * const httpErrorCodeP) {        char * fieldName;    NextToken((const char **)pP);        fieldName = GetToken(pP);    if (!fieldName)

⌨️ 快捷键说明

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