123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441 |
- #pragma once
- static const char threadTimestampFmt[] = "%Y/%m/%d %H:%M:%S %Z";
- static const char httpTimestampFmt[] = "%a, %d %b %Y %H:%M:%S GMT";
- static 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 int decryptMail(unsigned char *decrypted, char *encrypted)
- {
- char current[5]="0x";
- unsigned char *ptr = decrypted;
- current[2] = encrypted[0];
- current[3] = encrypted[1];
- unsigned int r = strtol(current,NULL,16);
- int len = strlen(encrypted);
- int n = 2;
- for(;n<len;n+=2) {
- current[2] = encrypted[n];
- current[3] = encrypted[n+1];
- unsigned int i = strtol(current,NULL,16);
- *ptr++ = i^r;
- }
- *ptr = 0;
- //fprintf(stderr,"%s->%s\n",encrypted,decrypted);
- return ptr - decrypted;
- }
- 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) return size*nitems;
-
- if(!strncasecmp("Connection",buffer,10)) {
- fprintf(conn->fpw,"Connection: Close\r\n");
- return size*nitems;
- }
- else if(!strncasecmp("Transfer-Encoding",buffer,17)) {
- if(allow_chunked && strstr(buffer+19,"chunked")) {
- conn->chunked = true;
- //fprintf(stderr,"%s",buffer);
- size_t ret = fwrite(buffer,size,nitems,conn->fpw);
- return ret;
- }
- return size*nitems;
- }
- else if(conn->force5ch && !strncasecmp("Set-Cookie:",buffer,11)) {
- char *ptr = (char *)memmem_priv(buffer,size*nitems,"domain=",7);
- if(ptr) {
- char *end = ptr;
- while(*end != ';' && *end != '\r') end++;
- ptr = (char *)memmem_priv(ptr,end-ptr,"5ch.net",7);
- if(ptr) {
- fwrite(buffer,1,ptr-buffer,conn->fpw);
- fputc('2',conn->fpw);
- fwrite(ptr+1,1,size*nitems-(ptr+1-buffer),conn->fpw);
- return size*nitems;
- }
- }
- return fwrite(buffer,1,size*nitems,conn->fpw);
- }
- else {
- #ifdef USE_LUA
- if (conn->bbscgi) {
- if (!strncasecmp("X-MonaKey:", buffer, 10)) {
- const char *ptr = buffer + 10;
- while (*ptr == ' ') ptr++;
- const char *end = ptr;
- while (*end != '\n' && *end != '\r' && *end) end++;
- conn->setMonaKey(std::string(ptr, end-ptr));
- }
- else if (!strncasecmp("X-Chx-Error:", buffer, 12)) {
- const char *ptr = buffer + 12;
- while (*ptr == ' ') ptr++;
- if (*ptr == 'E' && atoi(ptr+1) == 3310) {
- conn->setMonaKey("");
- }
- }
- }
- #endif
- size_t ret = fwrite(buffer,size,nitems,conn->fpw);
- //fprintf(stderr,"%s",buffer);
- if(!memcmp(buffer,"\r\n",2)) {
- fflush(conn->fpw);
- conn->status = 1;
- }
- 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->chunked) fprintf(conn->fpw,"%lx\r\n",size*nitems);
- size_t ret = fwrite(buffer,size,nitems,conn->fpw);
- if(conn->chunked) fprintf(conn->fpw,"\r\n");
- fflush(conn->fpw);
- return ret;
- }
- static size_t header_callback_download(char *buffer, size_t size, size_t nitems, void *userdata)
- {
- DataStorage *data = reinterpret_cast<DataStorage *>(userdata);
- if(!strncasecmp("Connection",buffer,10)) {
- data->appendBytes("Connection: Close\r\n",19);
- return size*nitems;
- }
- else if(!strncasecmp("Transfer-Encoding",buffer,17)) {
- return size*nitems;
- }
- else {
- data->appendBytes(buffer,size*nitems);
- return size*nitems;
- }
- }
- static size_t write_callback_download(char *buffer, size_t size, size_t nitems, void *userdata)
- {
- DataStorage *data = reinterpret_cast<DataStorage *>(userdata);
- size_t downloaded = size*nitems;
- data->appendBytes(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->content_length) {
- size_t bytesToRead = conn->content_length;
- if(size*nitems < conn->content_length) bytesToRead = size*nitems;
- size_t ret = fread(buffer,1,bytesToRead,conn->fpr);
- conn->content_length -= ret;
- return ret;
- }
- return 0;
- }
- static void sendBasicHeaders(int respCode, const char *respMsg, FILE *fpw)
- {
- char date[256];
- time_t now = time(0);
- strftime(date, 256, httpTimestampFmt, gmtime(&now));
- if(0 > fprintf(fpw, "HTTP/1.1 %d %s\r\n",respCode,respMsg)) return;
- if(0 > fprintf(fpw, "Connection: Close\r\n")) return;
- if(0 > fprintf(fpw, "Server: 2ch Proxy\r\n")) return;
- if(0 > fprintf(fpw, "Date: %s\r\n",date)) return;
- fflush(fpw);
- }
- static void sendResponse(int respCode, const char *respMsg, FILE *fpw)
- {
- sendBasicHeaders(respCode, respMsg, fpw);
- if(0 > fprintf(fpw, "Content-Type: text/plain; charset=UTF-8\r\n")) return;
- if(0 > fprintf(fpw, "\r\n")) return;
- if(respCode >= 400) {
- if(0 > fprintf(fpw, " ∧_∧ / ̄ ̄ ̄ ̄ ̄\n")) return;
- if(0 > fprintf(fpw, " ( ´∀`)< %s\n",respMsg)) return;
- if(0 > fprintf(fpw, " ( ) \_____\n")) return;
- if(0 > fprintf(fpw, " │ │ │\n")) return;
- if(0 > fprintf(fpw, " (__)_)\n")) return;
- }
- fflush(fpw);
- }
- #ifdef __WIN32__
- const char * strp_weekdays[] =
- { "sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"};
- const char * strp_monthnames[] =
- { "january", "february", "march", "april", "may", "june", "july", "august", "september", "october", "november", "december"};
- bool strp_atoi(const char * & s, int & result, int low, int high, int offset)
- {
- bool worked = false;
- char * end;
- unsigned long num = strtoul(s, & end, 10);
- if (num >= (unsigned long)low && num <= (unsigned long)high)
- {
- result = (int)(num + offset);
- s = end;
- worked = true;
- }
- return worked;
- }
- char * strptime(const char *s, const char *format, struct tm *tm)
- {
- bool working = true;
- while (working && *format && *s)
- {
- switch (*format)
- {
- case '%':
- {
- ++format;
- switch (*format)
- {
- case 'a':
- case 'A': // weekday name
- tm->tm_wday = -1;
- working = false;
- for (size_t i = 0; i < 7; ++ i)
- {
- size_t len = strlen(strp_weekdays[i]);
- if (!strnicmp(strp_weekdays[i], s, len))
- {
- tm->tm_wday = i;
- s += len;
- working = true;
- break;
- }
- else if (!strnicmp(strp_weekdays[i], s, 3))
- {
- tm->tm_wday = i;
- s += 3;
- working = true;
- break;
- }
- }
- break;
- case 'b':
- case 'B':
- case 'h': // month name
- tm->tm_mon = -1;
- working = false;
- for (size_t i = 0; i < 12; ++ i)
- {
- size_t len = strlen(strp_monthnames[i]);
- if (!strnicmp(strp_monthnames[i], s, len))
- {
- tm->tm_mon = i;
- s += len;
- working = true;
- break;
- }
- else if (!strnicmp(strp_monthnames[i], s, 3))
- {
- tm->tm_mon = i;
- s += 3;
- working = true;
- break;
- }
- }
- break;
- case 'd':
- case 'e': // day of month number
- working = strp_atoi(s, tm->tm_mday, 1, 31, 0);
- break;
- case 'D': // %m/%d/%y
- {
- const char * s_save = s;
- working = strp_atoi(s, tm->tm_mon, 1, 12, -1);
- if (working && *s == '/')
- {
- ++ s;
- working = strp_atoi(s, tm->tm_mday, 1, 31, 0);
- if (working && *s == '/')
- {
- ++ s;
- working = strp_atoi(s, tm->tm_year, 0, 99, 0);
- if (working && tm->tm_year < 69)
- tm->tm_year += 100;
- }
- }
- if (!working)
- s = s_save;
- }
- break;
- case 'H': // hour
- working = strp_atoi(s, tm->tm_hour, 0, 23, 0);
- break;
- case 'I': // hour 12-hour clock
- working = strp_atoi(s, tm->tm_hour, 1, 12, 0);
- break;
- case 'j': // day number of year
- working = strp_atoi(s, tm->tm_yday, 1, 366, -1);
- break;
- case 'm': // month number
- working = strp_atoi(s, tm->tm_mon, 1, 12, -1);
- break;
- case 'M': // minute
- working = strp_atoi(s, tm->tm_min, 0, 59, 0);
- break;
- case 'n': // arbitrary whitespace
- case 't':
- while (isspace((int)*s))
- ++s;
- break;
- case 'p': // am / pm
- if (!strnicmp(s, "am", 2))
- { // the hour will be 1 -> 12 maps to 12 am, 1 am .. 11 am, 12 noon 12 pm .. 11 pm
- if (tm->tm_hour == 12) // 12 am == 00 hours
- tm->tm_hour = 0;
- }
- else if (!strnicmp(s, "pm", 2))
- {
- if (tm->tm_hour < 12) // 12 pm == 12 hours
- tm->tm_hour += 12; // 1 pm -> 13 hours, 11 pm -> 23 hours
- }
- else
- working = false;
- break;
- case 'r': // 12 hour clock %I:%M:%S %p
- {
- const char * s_save = s;
- working = strp_atoi(s, tm->tm_hour, 1, 12, 0);
- if (working && *s == ':')
- {
- ++ s;
- working = strp_atoi(s, tm->tm_min, 0, 59, 0);
- if (working && *s == ':')
- {
- ++ s;
- working = strp_atoi(s, tm->tm_sec, 0, 60, 0);
- if (working && isspace((int)*s))
- {
- ++ s;
- while (isspace((int)*s))
- ++s;
- if (!strnicmp(s, "am", 2))
- { // the hour will be 1 -> 12 maps to 12 am, 1 am .. 11 am, 12 noon 12 pm .. 11 pm
- if (tm->tm_hour == 12) // 12 am == 00 hours
- tm->tm_hour = 0;
- }
- else if (!strnicmp(s, "pm", 2))
- {
- if (tm->tm_hour < 12) // 12 pm == 12 hours
- tm->tm_hour += 12; // 1 pm -> 13 hours, 11 pm -> 23 hours
- }
- else
- working = false;
- }
- }
- }
- if (!working)
- s = s_save;
- }
- break;
- case 'R': // %H:%M
- {
- const char * s_save = s;
- working = strp_atoi(s, tm->tm_hour, 0, 23, 0);
- if (working && *s == ':')
- {
- ++ s;
- working = strp_atoi(s, tm->tm_min, 0, 59, 0);
- }
- if (!working)
- s = s_save;
- }
- break;
- case 'S': // seconds
- working = strp_atoi(s, tm->tm_sec, 0, 60, 0);
- break;
- case 'T': // %H:%M:%S
- {
- const char * s_save = s;
- working = strp_atoi(s, tm->tm_hour, 0, 23, 0);
- if (working && *s == ':')
- {
- ++ s;
- working = strp_atoi(s, tm->tm_min, 0, 59, 0);
- if (working && *s == ':')
- {
- ++ s;
- working = strp_atoi(s, tm->tm_sec, 0, 60, 0);
- }
- }
- if (!working)
- s = s_save;
- }
- break;
- case 'w': // weekday number 0->6 sunday->saturday
- working = strp_atoi(s, tm->tm_wday, 0, 6, 0);
- break;
- case 'Y': // year
- working = strp_atoi(s, tm->tm_year, 1900, 65535, -1900);
- break;
- case 'y': // 2-digit year
- working = strp_atoi(s, tm->tm_year, 0, 99, 0);
- if (working && tm->tm_year < 69)
- tm->tm_year += 100;
- break;
- case '%': // escaped
- if (*s != '%')
- working = false;
- ++s;
- break;
- default:
- working = false;
- }
- }
- break;
- case ' ':
- case '\t':
- case '\r':
- case '\n':
- case '\f':
- case '\v':
- // zero or more whitespaces:
- while (isspace((int)*s))
- ++ s;
- break;
- default:
- // match character
- if (*s != *format)
- working = false;
- else
- ++s;
- break;
- }
- ++format;
- }
- return (working?(char *)s:0);
- }
- #endif
|