123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238 |
- #pragma once
- void *
- memmem_priv(const void *l, size_t l_len, const void *s, size_t s_len)
- {
- register char *cur, *last;
- const char *cl = (const char *)l;
- const char *cs = (const char *)s;
-
- /* we need something to compare */
- if (l_len == 0 || s_len == 0)
- return NULL;
-
- /* "s" must be smaller or equal to "l" */
- if (l_len < s_len)
- return NULL;
-
- /* special case where s_len == 1 */
- if (s_len == 1)
- return (void *)memchr(l, (int)*cs, l_len);
-
- /* the last position where its possible to find "s" in "l" */
- last = (char *)cl + l_len - s_len;
-
- for (cur = (char *)cl; cur <= last; cur++)
- if (cur[0] == cs[0] && memcmp(cur, cs, s_len) == 0)
- return cur;
-
- return NULL;
- }
- static size_t header_callback_proxy(char *buffer, size_t size, size_t nitems, void *userdata)
- {
- BBS2chProxyConnection *conn = reinterpret_cast<BBS2chProxyConnection *>(userdata);
- if(conn->status > 0) return size*nitems;
- else if(conn->status == -1) {
- if(!memcmp(buffer,"\r\n",2)) {
- conn->status = 0;
- }
- return size*nitems;
- }
- PBBS2chProxyHttpHeaderEntry parsedHeader = BBS2chProxyHttpHeaders::parse(buffer, size*nitems);
- if (parsedHeader.get()) { // Looks like a header
- const std::string &headerName = parsedHeader->getLowercasedName();
- //fprintf(stderr, "%s\n", parsedHeader->getFull().c_str());
- if (headerName == "connection") {
- conn->socketToClient->writeString("Connection: Close\r\n");
- return size*nitems;
- }
- else if (headerName == "transfer-encoding") {
- if (parsedHeader->contains("chunked")) {
- if (allow_chunked && !conn->isClientHttp1_0) {
- conn->isResponseChunked = true;
- size_t ret = conn->socketToClient->write(buffer, size*nitems);
- return ret;
- }
- return size*nitems;
- }
- }
- else if (conn->force5ch && headerName == "set-cookie") {
- const char *ptr = (const char *)memmem_priv(buffer, size*nitems, "domain=", 7);
- if (ptr) {
- const char *end = ptr;
- while(*end != ';' && *end != '\r') end++;
- ptr = (const char *)memmem_priv(ptr, end-ptr, "5ch.net", 7);
- if (ptr) {
- conn->socketToClient->write(buffer, ptr-buffer);
- conn->socketToClient->write("2", 1);
- conn->socketToClient->write(ptr+1, size*nitems-(ptr+1-buffer));
- return size*nitems;
- }
- }
- }
- else if (conn->directDatDownloading && headerName == "content-type") {
- conn->socketToClient->writeString("Content-Type: text/plain\r\n");
- return size*nitems;
- }
- return conn->socketToClient->write(buffer, size*nitems);
- }
- else {
- bool shouldSendExtraHeaders = false;
- if (!strncasecmp("HTTP/", buffer, 5)) {
- const char *ptr = buffer + 5;
- const char *end = buffer + size*nitems;
- while (ptr < end && *ptr != ' ') ptr++;
- while (ptr < end && *ptr == ' ') ptr++;
- if (ptr < end) {
- int code = atoi(ptr);
- if (code == 100) {
- conn->status = -1;
- return size*nitems;
- } else if (code < 400) {
- shouldSendExtraHeaders = true;
- }
- }
- }
- if (!memcmp(buffer, "\r\n", 2)) {
- conn->status = 1;
- }
- size_t ret = conn->socketToClient->write(buffer, size*nitems);
- if (shouldSendExtraHeaders && conn->directDatDownloading == 2) {
- conn->socketToClient->writeString("Thread-Status: 1\r\n");
- conn->socketToClient->writeString("User-Status: 3\r\n");
- }
- return ret;
- }
- }
- static size_t write_callback_proxy(char *buffer, size_t size, size_t nitems, void *userdata)
- {
- BBS2chProxyConnection *conn = reinterpret_cast<BBS2chProxyConnection *>(userdata);
- if(conn->isResponseChunked) {
- char buf[64];
- snprintf(buf, 64, "%lx\r\n", size*nitems);
- conn->socketToClient->write(buf, strlen(buf));
- }
- size_t ret = conn->socketToClient->write(buffer, size*nitems);
- if(conn->isResponseChunked) conn->socketToClient->writeString("\r\n");
- return ret;
- }
- static size_t header_callback_download(char *buffer, size_t size, size_t nitems, void *userdata)
- {
- BBS2chProxyHttpHeaders *headers = static_cast<BBS2chProxyHttpHeaders *>(userdata);
- PBBS2chProxyHttpHeaderEntry parsedHeader = BBS2chProxyHttpHeaders::parse(buffer, size*nitems);
- if (parsedHeader.get()) { // Looks like a header
- const std::string &headerName = parsedHeader->getLowercasedName();
- if (headerName == "connection") {
- if (headers) headers->add(parsedHeader->getName(), "close");
- return size*nitems;
- }
- else if (headerName == "transfer-encoding") {
- if (parsedHeader->contains("chunked")) {
- return size*nitems;
- }
- }
- if (headers) headers->add(parsedHeader->getName(), parsedHeader->getValue());
- }
- else if (headers) headers->setStatusLine(buffer, size*nitems);
- return size*nitems;
- }
- static size_t write_callback_download(char *buffer, size_t size, size_t nitems, void *userdata)
- {
- std::vector<char> *data = static_cast<std::vector<char> *>(userdata);
- size_t downloaded = size*nitems;
- if (data) data->insert(data->end(), buffer, buffer+downloaded);
- return downloaded;
- }
- static size_t read_callback_proxy(char *buffer, size_t size, size_t nitems, void *userdata)
- {
- BBS2chProxyConnection *conn = reinterpret_cast<BBS2chProxyConnection *>(userdata);
- if (size*nitems < 1) return 0;
- if (conn->isClientChunked) {
- size_t chunkSize;
- char tmp[64];
- if (!conn->content_length) {
- if (!conn->socketToClient->readLine(tmp, 64)) return 0;
- chunkSize = strtol(tmp, NULL, 16);
- if (chunkSize == 0) {
- return 0;
- }
- }
- else {
- chunkSize = conn->content_length;
- conn->content_length = 0;
- }
- if (chunkSize <= size*nitems) {
- size_t ret = conn->socketToClient->read(buffer, chunkSize);
- if (ret <= 0) return 0;
- conn->socketToClient->readLine(tmp, 64);
- return ret;
- }
- else {
- size_t ret = conn->socketToClient->read(buffer, size*nitems);
- if (ret <= 0) return 0;
- conn->content_length = chunkSize - ret;
- return ret;
- }
- }
- else if (conn->content_length) {
- size_t bytesToRead = conn->content_length;
- if (size*nitems < conn->content_length) bytesToRead = size*nitems;
- size_t ret = conn->socketToClient->read(buffer, bytesToRead);
- conn->content_length -= ret;
- return ret;
- }
- return 0;
- }
- double getCurrentTime(void)
- {
- #ifdef _WIN32
- FILETIME ft;
- GetSystemTimeAsFileTime(&ft);
- unsigned long long now = ft.dwHighDateTime;
- now <<= 32;
- now |= ft.dwLowDateTime;
- return (double)(now * 1e-7 - 11644473600.0);
- #else
- struct timeval tv;
- gettimeofday(&tv, NULL);
- return (double)(tv.tv_sec + tv.tv_usec * 1e-6);
- #endif
- }
- static size_t readChunkedBodyIntoBuffer(char **bufferOut, IBBS2chProxySocket *socket)
- {
- size_t contentLength = 0;
- size_t bufferLength = 128;
- size_t chunkSize = 0;
- char tmp[64];
- char *buffer = (char *)malloc(bufferLength);
- while (1) {
- if (!chunkSize) {
- if (!socket->readLine(tmp, 64)) break;
- chunkSize = strtol(tmp, NULL, 16);
- if (chunkSize == 0) {
- break;
- }
- if (chunkSize + contentLength >= bufferLength) {
- bufferLength = chunkSize + contentLength + 1;
- buffer = (char *)realloc(buffer, bufferLength);
- }
- }
- size_t ret = socket->read(buffer+contentLength, chunkSize);
- if (ret > 0) contentLength += ret;
- if (ret < chunkSize) break;
- if (!socket->readLine(tmp, 64)) break;
- chunkSize = 0;
- }
- buffer[contentLength] = 0;
- if (bufferOut) *bufferOut = buffer;
- else free(buffer);
- return contentLength;
- }
|