📄 httpheader.cpp
字号:
line += "="; line += value; line += "; path=/\r"; header.push_back(line); #ifdef DGDEBUG std::cout << "Setting cookie:" << line << std::endl; #endif // no expiry specified so ends with the browser session}// I'm not proud of this... --ErnestString HTTPHeader::getCookie(const char *cookie) { String line;// std::deque<String> cookies; for (int i = 0; i < (signed)header.size(); i++) { if (header[i].startsWith("Cookie:")) { line = header[i].after("ie: "); if (line.contains(cookie)) { // We know we have the cookie line = line.after(cookie); line.lop(); // Get rid of the '=' if (line.contains(";")) { line = line.before(";"); } } // break; // Technically there should be only one Cookie: header, but... } } line.removeWhiteSpace(); #ifdef DGDEBUG std::cout << "Found GBYPASS cookie:" << line << std::endl; #endif return line;}String HTTPHeader::decode(String s) { if (s.length() < 3) { return s; } #ifdef DGDEBUG std::cout << "decoding url" << std::endl; #endif RegExp re; #ifdef DGDEBUG std::cout << "matches:" << re.numberOfMatches() << std::endl; #endif if (!re.matched()) {return s;} // exit if not found #ifdef DGDEBUG std::cout << "removing %XX" << std::endl; #endif int match; int offset; int pos = 0; int size = s.length(); String result; String n; for (match = 0; match < re.numberOfMatches(); match++) { offset = re.offset(match); if (offset > pos) { result += s.subString(pos, offset-pos); } n = re.result(match).c_str(); n.lop(); // remove % result += hexToChar(n); pos = offset + 3; } if (size > pos) { result += s.subString(pos, size-pos); } else { n = "%" + n; } return result;}String HTTPHeader::hexToChar(String n) { if (n.length() < 2) { return n; } char* buf = new char[2]; unsigned int a, b; unsigned char c; a = n[0]; b = n[1]; if (a >= 'a' && a <= 'f') { a -= 87; } else if (a >= 'A' && a <= 'F') { a -= 55; } else if (a >= '0' && a <= '9') { a -= 48; } if (b >= 'a' && b <= 'f') { b -= 87; } else if (b >= 'A' && b <= 'F') { b -= 55; } else if (b >= '0' && b <= '9') { b -= 48; } c = a * 16 + b; if ( (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || (c == '-') ) { buf[0] = c; buf[1] = '\0'; n = buf; } else { n = "%" + n; } return n;}String HTTPHeader::requesttype() { // GET,HEAD,PUT,etc - what? return header[0].before(" ");}void HTTPHeader::out(Socket *sock) throw(exception) { String l; // for amalgamating to avoid conflict with the Nagel algorithm for(int i = 0; i < (signed)header.size(); i++) { l += header[i] + "\n"; } l += "\r\n"; // send header to the output stream // need exception for bad write if (!(*sock).writeToSocket(l.toCharArray(), l.length(), 0, timeout)) { throw exception(); } if (postdata.buffer_length > 0) { postdata.out(sock); }}void HTTPHeader::in(Socket *sock) { // the RFCs don't specify a max header line length so this should be // dynamic really. Pointed out (well reminded actually) by Daniel Robbins char buff[8192]; // setup a buffer to hold the incomming HTTP line String line; // temp store to hold the line after processing line="----"; // so we get past the first while while (line.length() > 3) { // loop until the stream is // failed or we get to the end of the header (a line by itself) (*sock).getline(buff, 8192, timeout); // get a line of header from the stream // getline will throw an exception if there is an error which will // only be caught by HandleConnection() line = buff; // convert the line to a String header.push_back(line); // stick the line in the deque that // holds the header } header.pop_back(); // remove the final blank line of a header checkheader(); // sort out a few bits in the header int length; String requestMethod = header[0].before(" "); if (!requestMethod.contains("/") && (length = contentlength()) > 0) { // if it's a request (not reply) with content, grab the data and store it postdata.read(sock, length); // get the DataBuffer to read the data }}bool HTTPHeader::isRedirection() { // The 1st line of the header for a redirection is thus: // HTTP/1.(0|1) 3xx if (header.size() < 1) {return false;} // sometimes get called b 4 read String answer = header[0].after(" ").before(" "); if (answer[0] == '3' && answer.length() == 3) { return true; } return false;}// squid adds this so if more support it it may be useful one dayvoid HTTPHeader::addXForwardedFor(std::string clientip) { std::string line = "X-Forwarded-For: " + clientip + "\r"; header.push_back(String(line.c_str()));}void HTTPHeader::setTimeout(int t) { timeout = t;}// If basic authentication is enabled DG is able to decode the username// and password from the header - however we are only interested in the// usernamestd::string HTTPHeader::getauthuser() { String t = getauth(); t = t.before(":"); t.toLower(); return std::string(t.toCharArray());}String HTTPHeader::getauth() { String line; for (int i = 0; i < (signed)header.size(); i++) { if (header[i].startsWith("Proxy-Authorization: Basic ") || header[i].startsWith("Proxy-Authorization: basic ")) { line = header[i].after("asic "); line = decodeb64(line).c_str(); // its base64 MIME encoded break; } } return line;}std::string HTTPHeader::decodeb64(String line) { // decode a block of b64 MIME long four = 0; int d; std::string result = ""; int len = line.length() - 4; for (int i = 0; i < len; i += 4) { four = 0; d = decode1b64(line[i + 0]); four = four | d; d = decode1b64(line[i + 1]); four = (four << 6) | d; d = decode1b64(line[i + 2]); four = (four << 6) | d; d = decode1b64(line[i + 3]); four = (four << 6) | d; d = (four & 0xFF0000) >> 16; result += (char)d; d = (four & 0xFF00) >> 8; result += (char)d; d = four & 0xFF; result += (char)d; } return result;}int HTTPHeader::decode1b64(char c) { unsigned char i = '\0'; switch (c) { case '+': i = 62; break; case '/': i = 63; break; case '=': i = 0; break; default: // must be A-Z, a-z or 0-9 i = '9' - c; if (i > 0x3F) { // under 9 i = 'Z' - c; if (i > 0x3F) { // over Z i = 'z' - c; if (i > 0x3F) { // over z so invalid i = 0x80; // so set the high bit } else { // a-z i = c - 71; } } else { // A-Z i = c - 65; } } else { // 0-9 i = c + 4; } break; } return (int)i;}bool HTTPHeader::isCompressed() { for (int i = 0; i < (signed)header.size(); i++) { if (header[i].startsWith("Content-Encoding:")) { if (header[i].indexOf("identity") != -1) { // http1.1 says this // should not be here, but not must not return false; } #ifdef DGDEBUG std::cout << "is compressed" << std::endl; #endif return true; // i.e. encoded with something other than clear } } return false;}String HTTPHeader::contentEncoding() { String ce; for (int i = 0; i < (signed)header.size(); i++) { if (header[i].startsWith("Content-Encoding:")) { ce = header[i].after("Content-Encoding: "); ce.toLower(); return ce; } } return ""; // we need a default don't we?}String HTTPHeader::modifyEncodings(String e) { // There are 4 types of encoding: gzip, deflate, compress and identity // deflate is in zlib format // compress is in unix compress format // identity is uncompressed and supported by all browsers (obviously) // we do not support compress e.toLower(); String o = "Accept-Encoding: identity"; #if ZLIB_VERNUM < 0x1210 #warning 'Accept-Encoding: gzip' is disabled #else if (e.contains("gzip")) { o += ",gzip"; } #endif if (e.contains("deflate")) { o += ",deflate"; } return o;}void HTTPHeader::removeEncoding(int newlen) { for (int i = 0; i < (signed)header.size(); i++) { if (header[i].startsWith("Content-Length:")) { header[i] = "Content-Length: " + String(newlen); } if (header[i].startsWith("Content-Encoding:")) { header[i] = "X-DansGuardian-Removed: Content-Encoding"; } }}void HTTPHeader::setContentLength(int newlen) { for (int i = 0; i < (signed)header.size(); i++) { if (header[i].startsWith("Content-Length:")) { header[i] = "Content-Length: " + String(newlen); } }}bool HTTPHeader::isPostUpload() { if (header[0].before(" ") != "POST") { return false; } bool answer = false; int postlen = postdata.buffer_length; int i; if (postlen < 14) { // min length for there to be a match return false; } char* postdatablock = new char[postlen + 64]; // extra 64 for search try { postdata.copytomemory(postdatablock); for(i = 0; i < postlen; i++) { // make lowercase char by char if (isupper(postdatablock[i])) { postdatablock[i] = tolower(postdatablock[i]); } } RegExp mysearch; std::string dis = "content-type: "; // signifies file upload char* p = new char[32]; try { for(i = 0; i < (signed)dis.length(); i++) { p[i] = dis[i]; // copy it to the block of memory } char* pend = p + dis.length(); // pointer for search char* postdatablockend = postdatablock + postlen; char* res = mysearch.search(postdatablock, postdatablockend, p, pend); if (res != postdatablockend) { answer = true; } } catch (exception& e) {}; delete[] p; } catch (exception& e) {}; delete[] postdatablock; return answer;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -