📄 httpheader.cpp
字号:
//Please refer to http://dansguardian.org/?page=copyright2//for the license for this code.//Written by Daniel Barron (daniel@//jadeb.com).//For support go to http://groups.yahoo.com/group/dansguardian// This program is free software; you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation; either version 2 of the License, or// (at your option) any later version.//// This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA//This file contains modifications suggested and mostly provided by//Daniel Robbins 13/4/01 drobbins@gento.org//Modifications include, but not limited to, getcontenttype(), << , >>#include "HTTPHeader.hpp"#include "Socket.hpp"#include "syslog.h"#include <string>#include <unistd.h>#include <sys/socket.h>#include <exception>#include <time.h>#include "RegExp.hpp"#include <cerrno>#include <zlib.h>void HTTPHeader::checkheader() { // this is used to fix bugs in certain // web servers that don't use the standards for (int i = 0; i < (signed)header.size(); i++) { // check each line in // the header if (header[i].startsWith("Content-length:")) { header[i] = "Content-Length:" + header[i].after("Content-length:"); } if (header[i].startsWith("x-forwarded-for:")) { header[i] = "X-Forwarded-For:" + header[i].after("x-forwarded-for:"); } if (header[i].startsWith("Content-type:")) { header[i] = "Content-Type:" + header[i].after("Content-type:"); } if (header[i].startsWith("Content-disposition:")) { header[i] = "Content-Disposition:" + header[i].after("Content-disposition:"); } if (header[i].startsWith("Proxy-Connection: keep-alive")) { header[i] = "Proxy-Connection: Keep-Alive" + header[i].after("Proxy-Connection: keep-alive"); } if (header[i].startsWith("Content-encoding:")) { header[i] = "Content-Encoding:" + header[i].after("Content-encoding:"); } if (header[i].startsWith("Accept-encoding:")) { header[i] = "Accept-Encoding:" + header[i].after("Accept-encoding:"); } if (header[i].startsWith("Accept-Encoding:")) { header[i] = modifyEncodings(header[i]) + "\r"; } if (header[i].startsWith("Connection: keep-alive")) { header[i] = "Connection: Keep-Alive" + header[i].after("Connection: keep-alive"); } if (header[i].startsWith("Connection: Keep-alive")) { header[i] = "Connection: Keep-Alive" + header[i].after("Connection: Keep-alive"); } if (header[i].startsWith("Proxy-Connection: Keep-Alive")) { header[i] = "Proxy-Connection: Close\r"; // Need to force HTTP/1.1 // clients and servers to use non persistant connections } if (header[i].startsWith("Connection: Keep-Alive")) { header[i] = "Connection: Close\r"; // ditto } if (header[i].startsWith("Proxy-authorization:")) { header[i] = "Proxy-Authorization:" + header[i].after("Proxy-authorization:"); } #ifdef DGDEBUG std::cout << header[i] << std::endl; #endif }}int HTTPHeader::contentlength() { // all self explanetory String temp; for (int i = 0; i < (signed)header.size(); i++) { // check each line in // the header if (header[i].startsWith("Content-Length:")) { temp = header[i].after(" "); return temp.toInteger(); } } return 0; // it finds the length of the POST data}bool HTTPHeader::authRequired() { String temp = header[0].after(" "); if (temp.contains(" ")) { temp = temp.before(" "); } if (temp.startsWith("407")) { return true; } return false;}String HTTPHeader::disposition() { String filename; for (int i = 0; i < (signed)header.size(); i++) { // check each line in // the header if (header[i].startsWith("Content-Disposition:")) { filename = header[i].after(";").after("="); filename.removeWhiteSpace(); // incase of trailing space if (filename.contains("\"")) { return header[i].after(";").after("\"").before("\""); } return filename; // example format: // Content-Disposition: attachment; filename="filename.ext" // Content-Disposition: attachment; filename=filename.ext } } return ""; // it finds the header proposed filename}String HTTPHeader::getcontenttype() { // most self explanetory String mimetype; int j; unsigned char c; for (int i = 0; i < (signed)header.size(); i++) { if (header[i].startsWith("Content-Type:")) { mimetype = header[i].after(" "); j = 0; while (j < (signed)mimetype.length()) { c = mimetype[j]; if (c == ' ' || c == ';' || c < 32) { // remove the mimetype = mimetype.subString(0, j); // extra info not needed j = 0; } j++; } break; } } mimetype.toLower(); if (mimetype.length() < 1) { mimetype = "-"; } return mimetype;}bool HTTPHeader::iscontenttype(String t) { // again too simple to explain return getcontenttype().startsWith(t); // it checks to see if the MIME // type is the one specified}// Modification based on a submitted patch by// Jimmy Myrick (jmyrick@tiger1.tiger.org)std::string HTTPHeader::getXForwardedForIP() { String line; for (int i = 0; i < (signed)header.size(); i++) { if (header[i].startsWith("X-Forwarded-For:")) { line = header[i].after("or: "); break; } } line.chop(); return std::string(line.toCharArray());}bool HTTPHeader::malformedURL(String url) { String host = url.after("://"); if (host.contains("/")) { host = host.before("/"); } if (host.length() < 2) { #ifdef DGDEBUG std::cout << "host len to small" << std::endl; #endif return true; } if (host.contains("..") || host.endsWith(".")) { #ifdef DGDEBUG std::cout << "double dots or ending dots" << std::endl; #endif return true; } int i, len; unsigned char c; len = host.length(); for (i = 0; i < len; i++) { c = (unsigned char)host[i]; if ( !(c >= 'a' && c <= 'z') && !(c >= 'A' && c <= 'Z') && !(c >= '0' && c <= '9') && c != '.' && c != '-' && c != '_' ) { #ifdef DGDEBUG std::cout << "bad char in hostname" << std::endl; #endif return true; // only allowed letters, digits, hiphen, dots } } return false;}// A request may be in the form:// GET http://foo.bar:80/ HTML/1.0 (if :80 is omitted 80 is assumed)// or:// GET / HTML/1.0// Host: foo.bar (optional header in HTTP/1.0, but like HTTP/1.1, we require it!)// Port: 80 (not a standard header; do any clients send it?)// or:// CONNECT foo.bar:443 HTTP/1.1// So we need to handle all 3String HTTPHeader::url() { port = 0; String hostname; String answer = header[0].after(" "); answer.removeMultiChar(' '); if (answer.after(" ").startsWith("HTTP/")) { answer = answer.before(" HTTP/"); } else { answer = answer.before(" http/"); // just in case! }//cout << answer << endl; if (requesttype() == "CONNECT") { if (!answer.startsWith("https://")) { answer = "https://" + answer; } }//cout << answer << endl; if (answer.length()) { int i; if (answer[0] == '/') { // must be the latter above for (i = 1; i < (signed)header.size(); i++) { if (header[i].startsWith("Host:")) { hostname = header[i].after(":"); hostname.removeMultiChar(' '); if (hostname.contains(":")) { hostname = hostname.before(":"); // chop off the port bit but it should never be there } hostname.removeWhiteSpace(); // remove rubbish like // ^M and blanks hostname = "http://" + hostname; answer = hostname + answer; if (port > 0) { break; // need to keep parsing to get port } } else if (header[i].startsWith("Port:")) { port = header[i].after(" ").toInteger(); if (port == 0 || port > 65535) { port = 80; } } } } else { // must be in the form GET http://foo.bar:80/ HTML/1.0 if (!answer.after("://").contains("/")) { answer += "/"; // needed later on so correct host is extracted } String protocol = answer.before("://"); hostname = answer.after("://"); String url = hostname.after("/"); url.removeWhiteSpace(); // remove rubbish like ^M and blanks if (url.length() > 0) { url = "/" + url; } hostname = hostname.before("/"); // extra / was added 4 here if (hostname.contains("@")) { // Contains a username:password combo hostname = hostname.after("@"); } if (hostname.contains(":")) { port = hostname.after(":").toInteger(); if (port == 0 || port > 65535) { port = 80; } hostname = hostname.before(":"); // chop off the port bit } answer = protocol + "://" + hostname + url; } } if (answer.endsWith("//")) { answer.chop(); } #ifdef DGDEBUG std::cout << "from header url:" << answer << std::endl; #endif return answer;}// This function ASSUMES that you really know what you are doing// Do NOT run this function unless you know that the URL contains a valid bypass code// Ernest W Lessengervoid HTTPHeader::chopBypass(String url) { if (url.contains("GBYPASS=")) { if (url.contains("?GBYPASS=")) { String bypass = url.after("?GBYPASS="); header[0] = header[0].before("?GBYPASS=") + header[0].after(bypass.toCharArray()); } else { String bypass = url.after("&GBYPASS="); header[0] = header[0].before("&GBYPASS=") + header[0].after(bypass.toCharArray()); } }}int HTTPHeader::isBypassURL(String *url, const char *magic, const char *clientip) { if ((*url).length() <= 45) return false; // Too short, can't be a bypass if (!(*url).contains("GBYPASS=")) { // If this is not a bypass url return 0; } #ifdef DGDEBUG std::cout << "URL GBYPASS found checking..." << std::endl; #endif String url_left = (*url).before("GBYPASS="); url_left.chop(); // remove the ? or & String url_right = (*url).after("GBYPASS="); String url_hash = url_right.subString(0,32); String url_time = url_right.after(url_hash.toCharArray()); #ifdef DGDEBUG std::cout << "URL: " << url_left << ", HASH: " << url_hash << "TIME: " << url_time << std::endl; #endif String mymagic = magic; mymagic += clientip; mymagic += url_time; String hashed = url_left.md5(mymagic.toCharArray()); if (hashed != url_hash) { return 0; } time_t timen = time(NULL); time_t timeu = url_time.toLong(); if (timeu < 1) { #ifdef DGDEBUG std::cout << "URL GBYPASS bad time value" << std::endl; #endif return 1; // bad time value } if (timeu < timen) { // expired key #ifdef DGDEBUG std::cout << "URL GBYPASS expired" << std::endl; #endif return 1; // denotes expired but there } #ifdef DGDEBUG std::cout << "URL GBYPASS not expired" << std::endl; #endif return (int)timeu;}bool HTTPHeader::isBypassCookie(String *url, const char *magic, const char *clientip) { String cookie = getCookie("GBYPASS"); String cookiehash = cookie.subString(0,32); String cookietime = cookie.after(cookiehash.toCharArray()); String mymagic = magic; mymagic += clientip; mymagic += cookietime; String hashed = (*url).md5(mymagic.toCharArray()); if (hashed != cookiehash) { #ifdef DGDEBUG std::cout << "Cookie GBYPASS not match" << std::endl; #endif return false; } time_t timen = time(NULL); time_t timeu = cookietime.toLong(); if (timeu < timen) { #ifdef DGDEBUG std::cout << "Cookie GBYPASS expired" << std::endl; #endif return false; } return true;}void HTTPHeader::setCookie(const char *cookie, const char *value) { String line = "Set-Cookie: "; line += cookie;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -