Selaa lähdekoodia

UI: Add function to get remote file

Similar to the OBS1 file where you can optionally get the signature if
available in the header (for auto-updating)
jp9000 8 vuotta sitten
vanhempi
sitoutus
33e4494014
2 muutettua tiedostoa jossa 121 lisäystä ja 3 poistoa
  1. 110 3
      UI/remote-text.cpp
  2. 11 0
      UI/remote-text.hpp

+ 110 - 3
UI/remote-text.cpp

@@ -22,6 +22,9 @@
 
 using namespace std;
 
+static auto curl_deleter = [] (CURL *curl) {curl_easy_cleanup(curl);};
+using Curl = unique_ptr<CURL, decltype(curl_deleter)>;
+
 static size_t string_write(char *ptr, size_t size, size_t nmemb, string &str)
 {
 	size_t total = size * nmemb;
@@ -45,9 +48,6 @@ void RemoteTextThread::run()
 		contentTypeString += contentType;
 	}
 
-	auto curl_deleter = [] (CURL *curl) {curl_easy_cleanup(curl);};
-	using Curl = unique_ptr<CURL, decltype(curl_deleter)>;
-
 	Curl curl{curl_easy_init(), curl_deleter};
 	if (curl) {
 		struct curl_slist *header = nullptr;
@@ -91,3 +91,110 @@ void RemoteTextThread::run()
 		curl_slist_free_all(header);
 	}
 }
+
+static size_t header_write(char *ptr, size_t size, size_t nmemb,
+		vector<string> &list)
+{
+	string str;
+
+	size_t total = size * nmemb;
+	if (total)
+		str.append(ptr, total);
+
+	if (str.back() == '\n')
+		str.resize(str.size() - 1);
+	if (str.back() == '\r')
+		str.resize(str.size() - 1);
+
+	list.push_back(std::move(str));
+	return total;
+}
+
+bool GetRemoteFile(
+	const char *url,
+	std::string &str,
+	std::string &error,
+	long *responseCode,
+	const char *contentType,
+	const char *postData,
+	std::vector<std::string> extraHeaders,
+	std::string *signature)
+{
+	vector<string> header_in_list;
+	char error_in[CURL_ERROR_SIZE];
+	CURLcode code = CURLE_FAILED_INIT;
+
+	error_in[0] = 0;
+
+	string versionString("User-Agent: obs-basic ");
+	versionString += App()->GetVersionString();
+
+	string contentTypeString;
+	if (contentType) {
+		contentTypeString += "Content-Type: ";
+		contentTypeString += contentType;
+	}
+
+	Curl curl{curl_easy_init(), curl_deleter};
+	if (curl) {
+		struct curl_slist *header = nullptr;
+
+		header = curl_slist_append(header,
+				versionString.c_str());
+
+		if (!contentTypeString.empty()) {
+			header = curl_slist_append(header,
+					contentTypeString.c_str());
+		}
+
+		for (std::string &h : extraHeaders)
+			header = curl_slist_append(header, h.c_str());
+
+		curl_easy_setopt(curl.get(), CURLOPT_URL, url);
+		curl_easy_setopt(curl.get(), CURLOPT_HTTPHEADER,
+				header);
+		curl_easy_setopt(curl.get(), CURLOPT_ERRORBUFFER,
+				error_in);
+		curl_easy_setopt(curl.get(), CURLOPT_WRITEFUNCTION,
+				string_write);
+		curl_easy_setopt(curl.get(), CURLOPT_WRITEDATA,
+				&str);
+		if (signature) {
+			curl_easy_setopt(curl.get(), CURLOPT_HEADERFUNCTION,
+					header_write);
+			curl_easy_setopt(curl.get(), CURLOPT_HEADERDATA,
+					&header_in_list);
+		}
+
+#if LIBCURL_VERSION_NUM >= 0x072400
+		// A lot of servers don't yet support ALPN
+		curl_easy_setopt(curl.get(), CURLOPT_SSL_ENABLE_ALPN, 0);
+#endif
+
+		if (postData) {
+			curl_easy_setopt(curl.get(), CURLOPT_POSTFIELDS,
+					postData);
+		}
+
+		code = curl_easy_perform(curl.get());
+		if (responseCode)
+			curl_easy_getinfo(curl.get(), CURLINFO_RESPONSE_CODE,
+					responseCode);
+
+		if (code != CURLE_OK) {
+			error = error_in;
+		} else if (signature) {
+			for (string &h : header_in_list) {
+				string name = h.substr(0, 13);
+				if (name == "X-Signature: ") {
+					*signature = h.substr(13);
+					break;
+				}
+			}
+		}
+
+		curl_slist_free_all(header);
+	}
+
+	return code == CURLE_OK;
+}

+ 11 - 0
UI/remote-text.hpp

@@ -18,6 +18,7 @@
 #pragma once
 
 #include <QThread>
+#include <vector>
 #include <string>
 
 class RemoteTextThread : public QThread {
@@ -40,3 +41,13 @@ public:
 		: url(url_), contentType(contentType_), postData(postData_)
 	{}
 };
+
+bool GetRemoteFile(
+	const char *url,
+	std::string &str,
+	std::string &error,
+	long *responseCode = nullptr,
+	const char *contentType = nullptr,
+	const char *postData = nullptr,
+	std::vector<std::string> extraHeaders = std::vector<std::string>(),
+	std::string *signature = nullptr);