📄 http.c
字号:
*httpErrorCodeP = 400; /* Bad Request */ else { if (fieldName[strlen(fieldName)-1] != ':') /* Not a valid field name */ *httpErrorCodeP = 400; /* Bad Request */ else { fieldName[strlen(fieldName)-1] = '\0'; /* remove trailing colon */ strtolower(fieldName); *httpErrorCodeP = 0; /* no error */ *fieldNameP = fieldName; } }}static voidprocessHeader(const char * const fieldName, char * const fieldValue, TSession * const sessionP, uint16_t * const httpErrorCodeP) {/*---------------------------------------------------------------------------- We may modify *fieldValue, and we put pointers to *fieldValue and *fieldName into *sessionP. We must fix this some day. *sessionP should point to individual malloc'ed strings.-----------------------------------------------------------------------------*/ *httpErrorCodeP = 0; /* initial assumption */ if (xmlrpc_streq(fieldName, "connection")) { if (xmlrpc_strcaseeq(fieldValue, "keep-alive")) sessionP->request_info.keepalive = TRUE; else sessionP->request_info.keepalive = FALSE; } else if (xmlrpc_streq(fieldName, "host")) parseHostPort(fieldValue, &sessionP->request_info.host, &sessionP->request_info.port, httpErrorCodeP); else if (xmlrpc_streq(fieldName, "from")) sessionP->request_info.from = fieldValue; else if (xmlrpc_streq(fieldName, "user-agent")) sessionP->request_info.useragent = fieldValue; else if (xmlrpc_streq(fieldName, "referer")) sessionP->request_info.referer = fieldValue; else if (xmlrpc_streq(fieldName, "range")) { if (xmlrpc_strneq(fieldValue, "bytes=", 6)) { abyss_bool succeeded; succeeded = ListAddFromString(&sessionP->ranges, &fieldValue[6]); *httpErrorCodeP = succeeded ? 0 : 400; } } else if (xmlrpc_streq(fieldName, "cookies")) { abyss_bool succeeded; succeeded = ListAddFromString(&sessionP->cookies, fieldValue); *httpErrorCodeP = succeeded ? 0 : 400; }}abyss_boolRequestRead(TSession * const sessionP) { uint16_t httpErrorCode; /* zero for no error */ char * requestLine; readRequestLine(sessionP, &requestLine, &httpErrorCode); if (!httpErrorCode) { TMethod httpMethod; const char * host; const char * path; const char * query; unsigned short port; abyss_bool moreHeaders; parseRequestLine(requestLine, &httpMethod, &sessionP->version, &host, &port, &path, &query, &moreHeaders, &httpErrorCode); if (!httpErrorCode) initRequestInfo(&sessionP->request_info, sessionP->version, strdup(requestLine), httpMethod, host, port, path, query); while (moreHeaders && !httpErrorCode) { char * p; abyss_bool succeeded; succeeded = ConnReadHeader(sessionP->conn, &p); if (!succeeded) httpErrorCode = 408; /* Request Timeout */ else { if (!*p) /* We have reached the empty line so all the request was read. */ moreHeaders = FALSE; else { char * fieldName; getFieldNameToken(&p, &fieldName, &httpErrorCode); if (!httpErrorCode) { char * fieldValue; NextToken((const char **)&p); fieldValue = p; TableAdd(&sessionP->request_headers, fieldName, fieldValue); processHeader(fieldName, fieldValue, sessionP, &httpErrorCode); } } } } } if (httpErrorCode) ResponseStatus(sessionP, httpErrorCode); else sessionP->validRequest = true; return !httpErrorCode;}char *RequestHeaderValue(TSession *r,char *name){ return (TableFind(&r->request_headers,name));}abyss_boolRequestValidURI(TSession * const sessionP) { if (!sessionP->request_info.uri) return FALSE; if (xmlrpc_streq(sessionP->request_info.uri, "*")) return (sessionP->request_info.method != m_options); if (strchr(sessionP->request_info.uri, '*')) return FALSE; return TRUE;}abyss_boolRequestValidURIPath(TSession * const sessionP) { uint32_t i; const char * p; p = sessionP->request_info.uri; i = 0; if (*p == '/') { i = 1; while (*p) if (*(p++) == '/') { if (*p == '/') break; else if ((strncmp(p,"./",2) == 0) || (strcmp(p, ".") == 0)) ++p; else if ((strncmp(p, "../", 2) == 0) || (strcmp(p, "..") == 0)) { p += 2; --i; if (i == 0) break; } /* Prevent accessing hidden files (starting with .) */ else if (*p == '.') return FALSE; else if (*p) ++i; } } return (*p == 0 && i > 0);}abyss_boolRequestAuth(TSession *r,char *credential,char *user,char *pass) { char *p,*x; char z[80],t[80]; p=RequestHeaderValue(r,"authorization"); if (p) { NextToken((const char **)&p); x=GetToken(&p); if (x) { if (strcasecmp(x,"basic")==0) { NextToken((const char **)&p); sprintf(z,"%s:%s",user,pass); Base64Encode(z,t); if (strcmp(p,t)==0) { r->request_info.user=strdup(user); return TRUE; }; }; } }; sprintf(z,"Basic realm=\"%s\"",credential); ResponseAddField(r,"WWW-Authenticate",z); ResponseStatus(r,401); return FALSE;}/*********************************************************************** Range*********************************************************************/abyss_bool RangeDecode(char *str,uint64_t filesize,uint64_t *start,uint64_t *end){ char *ss; *start=0; *end=filesize-1; if (*str=='-') { *start=filesize-strtol(str+1,&ss,10); return ((ss!=str) && (!*ss)); }; *start=strtol(str,&ss,10); if ((ss==str) || (*ss!='-')) return FALSE; str=ss+1; if (!*str) return TRUE; *end=strtol(str,&ss,10); if ((ss==str) || (*ss) || (*end<*start)) return FALSE; return TRUE;}/*********************************************************************** HTTP*********************************************************************/const char *HTTPReasonByStatus(uint16_t const code) { struct _HTTPReasons { uint16_t status; const char * reason; }; static struct _HTTPReasons const reasons[] = { { 100,"Continue" }, { 101,"Switching Protocols" }, { 200,"OK" }, { 201,"Created" }, { 202,"Accepted" }, { 203,"Non-Authoritative Information" }, { 204,"No Content" }, { 205,"Reset Content" }, { 206,"Partial Content" }, { 300,"Multiple Choices" }, { 301,"Moved Permanently" }, { 302,"Moved Temporarily" }, { 303,"See Other" }, { 304,"Not Modified" }, { 305,"Use Proxy" }, { 400,"Bad Request" }, { 401,"Unauthorized" }, { 402,"Payment Required" }, { 403,"Forbidden" }, { 404,"Not Found" }, { 405,"Method Not Allowed" }, { 406,"Not Acceptable" }, { 407,"Proxy Authentication Required" }, { 408,"Request Timeout" }, { 409,"Conflict" }, { 410,"Gone" }, { 411,"Length Required" }, { 412,"Precondition Failed" }, { 413,"Request Entity Too Large" }, { 414,"Request-URI Too Long" }, { 415,"Unsupported Media Type" }, { 500,"Internal Server Error" }, { 501,"Not Implemented" }, { 502,"Bad Gateway" }, { 503,"Service Unavailable" }, { 504,"Gateway Timeout" }, { 505,"HTTP Version Not Supported" }, { 000, NULL } }; const struct _HTTPReasons * reasonP; reasonP = &reasons[0]; while (reasonP->status <= code) if (reasonP->status == code) return reasonP->reason; else ++reasonP; return "No Reason";}int32_tHTTPRead(TSession * const s ATTR_UNUSED, const char * const buffer ATTR_UNUSED, uint32_t const len ATTR_UNUSED) { return 0;}abyss_boolHTTPWriteBodyChunk(TSession * const sessionP, const char * const buffer, uint32_t const len) { abyss_bool succeeded; if (sessionP->chunkedwrite && sessionP->chunkedwritemode) { char chunkHeader[16]; sprintf(chunkHeader, "%x\r\n", len); succeeded = ConnWrite(sessionP->conn, chunkHeader, strlen(chunkHeader)); if (succeeded) { succeeded = ConnWrite(sessionP->conn, buffer, len); if (succeeded) succeeded = ConnWrite(sessionP->conn, "\r\n", 2); } } else succeeded = ConnWrite(sessionP->conn, buffer, len); return succeeded;}abyss_boolHTTPWriteEndChunk(TSession * const sessionP) { abyss_bool retval; if (sessionP->chunkedwritemode && sessionP->chunkedwrite) { /* May be one day trailer dumping will be added */ sessionP->chunkedwritemode = FALSE; retval = ConnWrite(sessionP->conn, "0\r\n\r\n", 5); } else retval = TRUE; return retval;}abyss_boolHTTPKeepalive(TSession * const sessionP) {/*---------------------------------------------------------------------------- Return value: the connection should be kept alive after the session *sessionP is over.-----------------------------------------------------------------------------*/ return (sessionP->request_info.keepalive && !sessionP->serverDeniesKeepalive && sessionP->status < 400);}/********************************************************************************** http.c**** Copyright (C) 2000 by Moez Mahfoudh <mmoez@bigfoot.com>.** All rights reserved.**** Redistribution and use in source and binary forms, with or without** modification, are permitted provided that the following conditions** are met:** 1. Redistributions of source code must retain the above copyright** notice, this list of conditions and the following disclaimer.** 2. Redistributions in binary form must reproduce the above copyright** notice, this list of conditions and the following disclaimer in the** documentation and/or other materials provided with the distribution.** 3. The name of the author may not be used to endorse or promote products** derived from this software without specific prior written permission.** ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF** SUCH DAMAGE.********************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -