2 Revize 0dc5be0a98 ... 691ebbb6dc

Autor SHA1 Zpráva Datum
  NanashiNoGombe 691ebbb6dc --subject-to-lastmodify option, which generates subject.txt from lastmodify.txt před 11 měsíci
  NanashiNoGombe 2c28aa6e64 remove unused member variables před 1 rokem
5 změnil soubory, kde provedl 127 přidání a 3 odebrání
  1. 95 0
      BBS2chProxyConnection.cpp
  2. 1 3
      BBS2chProxyConnection.h
  3. 24 0
      BBS2chProxyURL.cpp
  4. 2 0
      BBS2chProxyURL.h
  5. 5 0
      main.cpp

+ 95 - 0
BBS2chProxyConnection.cpp

@@ -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;

+ 1 - 3
BBS2chProxyConnection.h

@@ -35,14 +35,11 @@ class BBS2chProxyConnection {
 	bool isResponseChunked;
 	bool force5ch;
 	bool bbscgi;
-	std::string responseHeaders;
 	IBBS2chProxySocket *socketToClient;
 	bool isClientChunked;
 	bool isClientHttp1_0;
 	CURL *curl;
 	bool isHttps;
-	std::string monaKeyForRequest;
-	std::string userAgentForRequest;
 	int directDatDownloading;
 	int serverPort;
 	static BBS2chProxyAuth auth;
@@ -70,6 +67,7 @@ class BBS2chProxyConnection {
 	int datProxyAPI(const std::string &url, const char *method, BBS2chProxyHttpHeaders &requestHeaders);
 	int bbsmenuProxy(const std::string &url, const char *method, BBS2chProxyHttpHeaders &requestHeaders);
 	int bbsCgiProxy(BBS2chProxyURL &url, BBS2chProxyHttpHeaders &requestHeaders, BBS2chProxyFormData &requestBody, bool talkTo5ch);
+	int subjectTxtProxy(BBS2chProxyURL &url, const char *method, BBS2chProxyHttpHeaders &requestHeaders);
 	int tunnel(const char *addr, int port);
 	BBS2chProxyURL getRawDatURLAndStatus(const BBS2chThreadIdentifier &threadIdentifier, BBS2chProxyHttpHeaders &requestHeaders, bool findKakologOnly, long *status, bool *foundAsKakolog);
 };

+ 24 - 0
BBS2chProxyURL.cpp

@@ -235,6 +235,14 @@ bool BBS2chProxyURL::pathStartsWith(const std::string &prefix) const
 	return _pathAndOthers.compare(0, len2, prefix) == 0;
 }
 
+bool BBS2chProxyURL::pathEndsWith(const std::string &suffix) const
+{
+	size_t len1 = _pathAndOthers.length();
+	size_t len2 = suffix.length();
+	if (len1 < len2) return false;
+	return _pathAndOthers.compare(len1-len2, len2, suffix) == 0;
+}
+
 bool BBS2chProxyURL::hostStartsWith(const std::string &prefix) const
 {
 	size_t len1 = _host.length();
@@ -258,3 +266,19 @@ std::map<std::string, std::string> BBS2chProxyURL::getQuery() const
 	}
 	return fields;
 }
+
+int BBS2chProxyURL::numberOfPathComponents() const
+{
+	size_t idx = 0;
+	int ret = 0;
+	while (idx < _pathAndOthers.size()) {
+		size_t pos = _pathAndOthers.find("/", idx);
+		if (pos == std::string::npos) {
+			ret++;
+			break;
+		}
+		if (pos != idx) ret++;
+		idx = pos + 1;
+	}
+	return ret;
+}

+ 2 - 0
BBS2chProxyURL.h

@@ -32,5 +32,7 @@ public:
 	bool replaceHost(const std::string &fromHost, const std::string &toHost);
 	bool isFamilyOf5chNet() const;
 	bool pathStartsWith(const std::string &prefix) const;
+	bool pathEndsWith(const std::string &suffix) const;
 	bool hostStartsWith(const std::string &prefix) const;
+	int numberOfPathComponents() const;
 };

+ 5 - 0
main.cpp

@@ -78,6 +78,7 @@ int api_override;
 int direct_dat = 0;
 int fool_janestyle = 0;
 int talk_to_5ch = 0;
+int subject_to_lastmodify = 0;
 static pthread_mutex_t lockarray[NUM_LOCKS];
 
 void log_printf(int level, const char *format ...)
@@ -378,6 +379,7 @@ int main(int argc, char *argv[])
 		{"fool-janestyle", 0, NULL, 0},
 		{"keystore", 1, NULL, 0},
 		{"talk-to-5ch", 0, NULL, 0},
+		{"subject-to-lastmodify", 0, NULL, 0},
 #ifdef USE_MITM
 		{"mitm", 1, NULL, 0},
 		{"mitm-ca-cert", 1, NULL, 0},
@@ -622,6 +624,9 @@ int main(int argc, char *argv[])
 				else if(!strcmp(options[option_index].name, "talk-to-5ch")) {
 					talk_to_5ch = 1;
 				}
+				else if(!strcmp(options[option_index].name, "subject-to-lastmodify")) {
+					subject_to_lastmodify = 1;
+				}
 				break;
 			case 'p':
 				for (char *ptr = optarg;;) {