aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/arch/win32/ArchInternetWindows.cpp
diff options
context:
space:
mode:
authorLibravatarUnit 193 <unit193@ubuntu.com>2018-04-25 18:07:30 -0400
committerLibravatarUnit 193 <unit193@ubuntu.com>2018-04-25 18:07:30 -0400
commit9b1b081cfdb1c0fb6457278775e0823f8bc10f62 (patch)
treece8840148d8445055ba9e4f12263b2208f234c16 /src/lib/arch/win32/ArchInternetWindows.cpp
Import Upstream version 2.0.0+dfsgupstream/2.0.0+dfsg
Diffstat (limited to 'src/lib/arch/win32/ArchInternetWindows.cpp')
-rw-r--r--src/lib/arch/win32/ArchInternetWindows.cpp224
1 files changed, 224 insertions, 0 deletions
diff --git a/src/lib/arch/win32/ArchInternetWindows.cpp b/src/lib/arch/win32/ArchInternetWindows.cpp
new file mode 100644
index 0000000..7f69c7f
--- /dev/null
+++ b/src/lib/arch/win32/ArchInternetWindows.cpp
@@ -0,0 +1,224 @@
+/*
+ * barrier -- mouse and keyboard sharing utility
+ * Copyright (C) 2014-2016 Symless Ltd.
+ *
+ * This package is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * found in the file LICENSE that should have accompanied this file.
+ *
+ * This package is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "arch/win32/ArchInternetWindows.h"
+#include "arch/win32/XArchWindows.h"
+#include "arch/Arch.h"
+#include "common/Version.h"
+
+#include <sstream>
+#include <Wininet.h>
+#include <Shlwapi.h>
+
+struct WinINetUrl {
+ String m_scheme;
+ String m_host;
+ String m_path;
+ INTERNET_PORT m_port;
+ DWORD m_flags;
+};
+
+class WinINetRequest {
+public:
+ WinINetRequest(const String& url);
+ ~WinINetRequest();
+
+ String send();
+ void openSession();
+ void connect();
+ void openRequest();
+
+private:
+ HINTERNET m_session;
+ HINTERNET m_connect;
+ HINTERNET m_request;
+ WinINetUrl m_url;
+ bool m_used;
+};
+
+//
+// ArchInternetWindows
+//
+
+String
+ArchInternetWindows::get(const String& url)
+{
+ WinINetRequest request(url);
+ return request.send();
+}
+
+String
+ArchInternetWindows::urlEncode(const String& url)
+{
+ TCHAR buffer[1024];
+ DWORD bufferSize = sizeof(buffer);
+
+ if (UrlEscape(url.c_str(), buffer, &bufferSize, URL_ESCAPE_UNSAFE) != S_OK) {
+ throw XArch(new XArchEvalWindows());
+ }
+
+ String result(buffer);
+
+ // the win32 url encoding funcitons are pretty useless (to us) and only
+ // escape "unsafe" chars, but not + or =, so we need to replace these
+ // manually (and probably many other chars).
+ barrier::string::findReplaceAll(result, "+", "%2B");
+ barrier::string::findReplaceAll(result, "=", "%3D");
+
+ return result;
+}
+
+//
+// WinINetRequest
+//
+
+static WinINetUrl parseUrl(const String& url);
+
+WinINetRequest::WinINetRequest(const String& url) :
+ m_session(NULL),
+ m_connect(NULL),
+ m_request(NULL),
+ m_used(false),
+ m_url(parseUrl(url))
+{
+}
+
+WinINetRequest::~WinINetRequest()
+{
+ if (m_request != NULL) {
+ InternetCloseHandle(m_request);
+ }
+
+ if (m_connect != NULL) {
+ InternetCloseHandle(m_connect);
+ }
+
+ if (m_session != NULL) {
+ InternetCloseHandle(m_session);
+ }
+}
+
+String
+WinINetRequest::send()
+{
+ if (m_used) {
+ throw XArch("class is one time use.");
+ }
+ m_used = true;
+
+ openSession();
+ connect();
+ openRequest();
+
+ String headers("Content-Type: text/html");
+ if (!HttpSendRequest(m_request, headers.c_str(), (DWORD)headers.length(), NULL, NULL)) {
+ throw XArch(new XArchEvalWindows());
+ }
+
+ std::stringstream result;
+ CHAR buffer[1025];
+ DWORD read = 0;
+
+ while (InternetReadFile(m_request, buffer, sizeof(buffer) - 1, &read) && (read != 0)) {
+ buffer[read] = 0;
+ result << buffer;
+ read = 0;
+ }
+
+ return result.str();
+}
+
+void
+WinINetRequest::openSession()
+{
+ std::stringstream userAgent;
+ userAgent << "Barrier ";
+ userAgent << kVersion;
+
+ m_session = InternetOpen(
+ userAgent.str().c_str(),
+ INTERNET_OPEN_TYPE_PRECONFIG,
+ NULL,
+ NULL,
+ NULL);
+
+ if (m_session == NULL) {
+ throw XArch(new XArchEvalWindows());
+ }
+}
+
+void
+WinINetRequest::connect()
+{
+ m_connect = InternetConnect(
+ m_session,
+ m_url.m_host.c_str(),
+ m_url.m_port,
+ NULL,
+ NULL,
+ INTERNET_SERVICE_HTTP,
+ NULL,
+ NULL);
+
+ if (m_connect == NULL) {
+ throw XArch(new XArchEvalWindows());
+ }
+}
+
+void
+WinINetRequest::openRequest()
+{
+ m_request = HttpOpenRequest(
+ m_connect,
+ "GET",
+ m_url.m_path.c_str(),
+ HTTP_VERSION,
+ NULL,
+ NULL,
+ m_url.m_flags,
+ NULL);
+
+ if (m_request == NULL) {
+ throw XArch(new XArchEvalWindows());
+ }
+}
+
+// nb: i tried to use InternetCrackUrl here, but couldn't quite get that to
+// work. here's some (less robust) code to split the url into components.
+// this works fine with simple urls, but doesn't consider the full url spec.
+static WinINetUrl
+parseUrl(const String& url)
+{
+ WinINetUrl parsed;
+
+ size_t schemeEnd = url.find("://");
+ size_t hostEnd = url.find('/', schemeEnd + 3);
+
+ parsed.m_scheme = url.substr(0, schemeEnd);
+ parsed.m_host = url.substr(schemeEnd + 3, hostEnd - (schemeEnd + 3));
+ parsed.m_path = url.substr(hostEnd);
+
+ parsed.m_port = INTERNET_DEFAULT_HTTP_PORT;
+ parsed.m_flags = 0;
+
+ if (parsed.m_scheme.find("https") != String::npos) {
+ parsed.m_port = INTERNET_DEFAULT_HTTPS_PORT;
+ parsed.m_flags = INTERNET_FLAG_SECURE;
+ }
+
+ return parsed;
+}