|
@@ -61,6 +61,7 @@ extern int api_override;
|
|
|
extern int direct_dat;
|
|
|
extern int fool_janestyle;
|
|
|
extern int talk_to_5ch;
|
|
|
+extern int subject_to_lastmodify;
|
|
|
#ifdef USE_MITM
|
|
|
extern unsigned int mitm_mode;
|
|
|
#endif
|
|
@@ -693,6 +694,10 @@ beginHandleRequest:
|
|
|
statusCode = 404;
|
|
|
}
|
|
|
}
|
|
|
+ else if (subject_to_lastmodify && requestURL.isFamilyOf5chNet() && requestURL.pathEndsWith("/subject.txt") && requestURL.numberOfPathComponents() == 2) {
|
|
|
+ log_printf(1, "Running as subject.txt to lastmodify.txt proxy...\n");
|
|
|
+ statusCode = subjectTxtProxy(requestURL, method, requestHeaders);
|
|
|
+ }
|
|
|
else {
|
|
|
bool isPostRequest = !strcasecmp(method, "POST");
|
|
|
bool isPutRequest = !strcasecmp(method, "PUT");
|
|
@@ -1365,6 +1370,96 @@ BBS2chProxyURL BBS2chProxyConnection::getRawDatURLAndStatus(const BBS2chThreadId
|
|
|
return BBS2chProxyURL(datURL.c_str());
|
|
|
}
|
|
|
|
|
|
+int BBS2chProxyConnection::subjectTxtProxy(BBS2chProxyURL &url, const char *method, BBS2chProxyHttpHeaders &requestHeaders)
|
|
|
+{
|
|
|
+ long statusCode = 0;
|
|
|
+ std::string path = url.getPath();
|
|
|
+ size_t pos = path.find("/subject.txt");
|
|
|
+ path = path.substr(0, pos);
|
|
|
+ path += "/lastmodify.txt";
|
|
|
+ BBS2chProxyURL newURL = BBS2chProxyURL(url, path.c_str());
|
|
|
+ std::vector<char> data;
|
|
|
+ BBS2chProxyHttpHeaders receivedHeaders;
|
|
|
+ if (curl_share) curl_easy_setopt(curl, CURLOPT_SHARE, curl_share);
|
|
|
+ curl_easy_setopt(curl, CURLOPT_URL, newURL.absoluteString().c_str());
|
|
|
+ curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L);
|
|
|
+ curl_easy_setopt(curl, CURLOPT_TIMEOUT, timeout);
|
|
|
+ curl_easy_setopt(curl, CURLOPT_ENCODING, "");
|
|
|
+ curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback_download);
|
|
|
+ curl_easy_setopt(curl, CURLOPT_WRITEDATA, &data);
|
|
|
+ curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, header_callback_download);
|
|
|
+ curl_easy_setopt(curl, CURLOPT_HEADERDATA, &receivedHeaders);
|
|
|
+ curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
|
|
|
+ curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
|
|
|
+ curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
|
|
|
+ if (force_ipv4) curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
|
|
|
+ if (proxy_server) {
|
|
|
+ curl_easy_setopt(curl, CURLOPT_PROXY, proxy_server);
|
|
|
+ curl_easy_setopt(curl, CURLOPT_PROXYPORT, proxy_port);
|
|
|
+ curl_easy_setopt(curl, CURLOPT_PROXYTYPE, proxy_type);
|
|
|
+ }
|
|
|
+ if (user_agent) {
|
|
|
+ curl_easy_setopt(curl, CURLOPT_USERAGENT, user_agent);
|
|
|
+ }
|
|
|
+ else if (requestHeaders.has("User-Agent")) {
|
|
|
+ curl_easy_setopt(curl, CURLOPT_USERAGENT, requestHeaders.get("User-Agent").c_str());
|
|
|
+ }
|
|
|
+ CURLcode res = curl_easy_perform(curl);
|
|
|
+ if (res == CURLE_OK) {
|
|
|
+ curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &statusCode);
|
|
|
+ if (statusCode == 200) {
|
|
|
+ std::string outText;
|
|
|
+ data.push_back('\0');
|
|
|
+ char *ptr = &data.front();
|
|
|
+ while (1) {
|
|
|
+ char *lineStart = ptr;
|
|
|
+ char *lineEnd = strchr(ptr, '\n');
|
|
|
+ char *tmp;
|
|
|
+ if (!lineEnd) break;
|
|
|
+ ptr = strstr(lineStart, "<>");
|
|
|
+ if (!ptr) goto next;
|
|
|
+ ptr = strstr(ptr+2, "<>");
|
|
|
+ if (!ptr) goto next;
|
|
|
+ tmp = strstr(ptr+2, "<>");
|
|
|
+ if (!tmp) goto next;
|
|
|
+ outText += std::string(lineStart, ptr-lineStart);
|
|
|
+ if (*(ptr-1) != ')') {
|
|
|
+ std::string suppl = " (" + std::string(ptr+2, tmp-ptr-2);
|
|
|
+ suppl += ")";
|
|
|
+ size_t len1 = outText.length();
|
|
|
+ size_t len2 = suppl.length();
|
|
|
+ if (len1 < len2 || outText.compare(len1-len2, len2, suppl)) {
|
|
|
+ outText += suppl;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ outText += "\n";
|
|
|
+next:
|
|
|
+ ptr = lineEnd+1;
|
|
|
+ }
|
|
|
+ std::ostringstream ss;
|
|
|
+ socketToClient->sendBasicHeaders(200, "OK");
|
|
|
+ if (receivedHeaders.has("Last-Modified")) {
|
|
|
+ socketToClient->writeString(receivedHeaders.getFull("Last-Modified", true));
|
|
|
+ }
|
|
|
+ socketToClient->writeString("Content-Type: text/plain\r\n");
|
|
|
+ ss << "Content-Length: " << outText.size() << "\r\n\r\n";
|
|
|
+ socketToClient->writeString(ss.str());
|
|
|
+ if (strcasecmp(method, "HEAD")) {
|
|
|
+ socketToClient->writeString(outText);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ log_printf(0,"curl error: %s (%s)\n", curl_easy_strerror(res), newURL.absoluteString().c_str());
|
|
|
+ statusCode = 503;
|
|
|
+ }
|
|
|
+ if (statusCode != 200) {
|
|
|
+ socketToClient->sendResponse(statusCode, "Error");
|
|
|
+ }
|
|
|
+ curl_easy_reset(curl);
|
|
|
+ return statusCode;
|
|
|
+}
|
|
|
+
|
|
|
void BBS2chProxyConnection::compileRegex(void)
|
|
|
{
|
|
|
static int compiled;
|