From 427db871922a028bb299dd66c37f3cca4010fd47 Mon Sep 17 00:00:00 2001
From: Thilo Cestonaro <thilo@cestona.ro>
Date: Thu, 14 Apr 2011 10:25:33 +0200
Subject: Support for SOCKS5 and HTTPConnect proxies.

automatic proxy settings detection;
SOCKS5 proxied connection;
HTTPConnect proxied connection;

License: This patch is BSD-licensed, see http://www.opensource.org/licenses/bsd-license.php

diff --git a/BuildTools/SCons/SConstruct b/BuildTools/SCons/SConstruct
index 43b6df0..246092d 100644
--- a/BuildTools/SCons/SConstruct
+++ b/BuildTools/SCons/SConstruct
@@ -193,7 +193,7 @@ if env.get("coverage", 0) :
 	env.Append(LINKFLAGS = ["-fprofile-arcs", "-ftest-coverage"])
 
 if env["PLATFORM"] == "win32" :
-	env.Append(LIBS = ["user32", "crypt32", "dnsapi", "ws2_32", "wsock32"])
+	env.Append(LIBS = ["user32", "crypt32", "dnsapi", "ws2_32", "wsock32", "Advapi32"])
 	env.Append(CCFLAGS = ["/EHsc", "/nologo"])
 	# FIXME: We should find a decent solution for MSVS 10
 	if int(env["MSVS_VERSION"].split(".")[0]) < 10 :
@@ -201,7 +201,7 @@ if env["PLATFORM"] == "win32" :
 		env["SHLINKCOM"] = [env["SHLINKCOM"], 'mt.exe -nologo -manifest ${TARGET}.manifest -outputresource:$TARGET;2']
 
 if env["PLATFORM"] == "darwin" and not env["target"] in ["iphone-device", "iphone-simulator", "xcode"] :
-	env.Append(FRAMEWORKS = ["IOKit", "AppKit"])
+	env.Append(FRAMEWORKS = ["IOKit", "AppKit", "SystemConfiguration"])
 
 # Testing
 env["TEST_TYPE"] = env["test"]
@@ -421,6 +421,22 @@ if env["PLATFORM"] != "win32" and env["PLATFORM"] != "darwin" :
 		env["XSS_FLAGS"] = xss_flags
 	conf.Finish()
 
+# GConf
+env["HAVE_GCONF"] = 0
+if env["PLATFORM"] != "win32" and env["PLATFORM"] != "darwin" :
+	gconf_env = Environment()
+	gconf_env.ParseConfig('pkg-config --cflags gconf-2.0 --libs gconf-2.0')
+	conf = Configure(gconf_env)
+	if conf.CheckCHeader("gconf/gconf-client.h") and conf.CheckLib("gconf-2") :
+		env["HAVE_GCONF"] = 1
+		env["GCONF_FLAGS"] = {
+			"LIBS": gconf_env["LIBS"],
+			"CCFLAGS": gconf_env["CCFLAGS"],
+			"CPPPATH": gconf_env["CPPPATH"],
+			"CPPDEFINES": gconf_env["CPPDEFINES"],
+		}
+	conf.Finish()
+
 # Sparkle
 env["HAVE_SPARKLE"] = 0
 if env["PLATFORM"] == "darwin" :
diff --git a/Swiften/Client/CoreClient.cpp b/Swiften/Client/CoreClient.cpp
index 8e51c8e..348f3b3 100644
--- a/Swiften/Client/CoreClient.cpp
+++ b/Swiften/Client/CoreClient.cpp
@@ -19,17 +19,28 @@
 #include "Swiften/Base/IDGenerator.h"
 #include "Swiften/Client/ClientSessionStanzaChannel.h"
 #include <Swiften/Base/Log.h>
+#include "Swiften/Network/PlatformProxyProvider.h"
+#include "Swiften/Network/SOCKS5ProxiedConnectionFactory.h"
+#include "Swiften/Network/HTTPConnectProxiedConnectionFactory.h"
 
 namespace Swift {
 
-CoreClient::CoreClient(const JID& jid, const std::string& password, NetworkFactories* networkFactories) : jid_(jid), password_(password), networkFactories(networkFactories), useStreamCompression(true), useTLS(UseTLSWhenAvailable), disconnectRequested_(false), certificateTrustChecker(NULL) {
+CoreClient::CoreClient(const JID& jid, const std::string& password, NetworkFactories* networkFactories) : jid_(jid), password_(password), networkFactories(networkFactories), useStreamCompression(true), useTLS(UseTLSWhenAvailable), proxyConnectionFactory_(NULL), disconnectRequested_(false), certificateTrustChecker(NULL) {
 	stanzaChannel_ = new ClientSessionStanzaChannel();
 	stanzaChannel_->onMessageReceived.connect(boost::bind(&CoreClient::handleMessageReceived, this, _1));
 	stanzaChannel_->onPresenceReceived.connect(boost::bind(&CoreClient::handlePresenceReceived, this, _1));
 	stanzaChannel_->onStanzaAcked.connect(boost::bind(&CoreClient::handleStanzaAcked, this, _1));
 	stanzaChannel_->onAvailableChanged.connect(boost::bind(&CoreClient::handleStanzaChannelAvailableChanged, this, _1));
 
+	PlatformProxyProvider proxyProvider;
+
 	iqRouter_ = new IQRouter(stanzaChannel_);
+	if(proxyProvider.getSOCKS5Proxy().isValid()) {
+		proxyConnectionFactory_ = new SOCKS5ProxiedConnectionFactory(networkFactories->getConnectionFactory(), proxyProvider.getSOCKS5Proxy());
+	}
+	else if(proxyProvider.getHTTPConnectProxy().isValid()) {
+		proxyConnectionFactory_ = new HTTPConnectProxiedConnectionFactory(networkFactories->getConnectionFactory(), proxyProvider.getHTTPConnectProxy());
+	}
 	tlsFactories = new PlatformTLSFactories();
 }
 
@@ -38,6 +49,7 @@ CoreClient::~CoreClient() {
 		std::cerr << "Warning: Client not disconnected properly" << std::endl;
 	}
 	delete tlsFactories;
+	delete proxyConnectionFactory_;
 	delete iqRouter_;
 
 	stanzaChannel_->onAvailableChanged.disconnect(boost::bind(&CoreClient::handleStanzaChannelAvailableChanged, this, _1));
@@ -56,7 +68,7 @@ void CoreClient::connect(const std::string& host) {
 	SWIFT_LOG(debug) << "Connecting to host " << host << std::endl;
 	disconnectRequested_ = false;
 	assert(!connector_);
-	connector_ = Connector::create(host, networkFactories->getDomainNameResolver(), networkFactories->getConnectionFactory(), networkFactories->getTimerFactory());
+	connector_ = Connector::create(host, networkFactories->getDomainNameResolver(), proxyConnectionFactory_ != NULL ? proxyConnectionFactory_ : networkFactories->getConnectionFactory(), networkFactories->getTimerFactory());
 	connector_->onConnectFinished.connect(boost::bind(&CoreClient::handleConnectorFinished, this, _1));
 	connector_->setTimeoutMilliseconds(60*1000);
 	connector_->start();
diff --git a/Swiften/Client/CoreClient.h b/Swiften/Client/CoreClient.h
index ceb0b0a..2debb7f 100644
--- a/Swiften/Client/CoreClient.h
+++ b/Swiften/Client/CoreClient.h
@@ -221,6 +221,7 @@ namespace Swift {
 			ClientSessionStanzaChannel* stanzaChannel_;
 			IQRouter* iqRouter_;
 			boost::shared_ptr<Connector> connector_;
+			ConnectionFactory* proxyConnectionFactory_;
 			PlatformTLSFactories* tlsFactories;
 			boost::shared_ptr<Connection> connection_;
 			boost::shared_ptr<BasicSessionStream> sessionStream_;
diff --git a/Swiften/Network/EnvironmentProxyProvider.cpp b/Swiften/Network/EnvironmentProxyProvider.cpp
new file mode 100644
index 0000000..b3bd0f6
--- /dev/null
+++ b/Swiften/Network/EnvironmentProxyProvider.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <iostream>
+
+#include "Swiften/Base/Log.h"
+#include "Swiften/Network/EnvironmentProxyProvider.h"
+
+namespace Swift {
+
+EnvironmentProxyProvider::EnvironmentProxyProvider() {
+	socksProxy = getFromEnv("all_proxy", "socks");
+	httpProxy = getFromEnv("http_proxy", "http");
+	SWIFT_LOG(debug) << "Environment: SOCKS5 => " << socksProxy.toString() << "; HTTP Connect => " << httpProxy.toString() << std::endl;
+}
+
+HostAddressPort EnvironmentProxyProvider::getHTTPConnectProxy() const {
+	return httpProxy;
+}
+
+HostAddressPort EnvironmentProxyProvider::getSOCKS5Proxy() const {
+	return socksProxy;
+}
+
+HostAddressPort EnvironmentProxyProvider::getFromEnv(const char* envVarName, std::string proxyProtocol) {
+	char* envVar = NULL;
+	std::string address;
+	int port = 0;
+
+	envVar = getenv(envVarName);
+
+	proxyProtocol += "://";
+	address = envVar != NULL ? envVar : "0.0.0.0";
+	if(envVar != NULL && address.compare(0, proxyProtocol.length(), proxyProtocol) == 0) {
+		address = address.substr(proxyProtocol.length(), address.length());
+		port = atoi(address.substr(address.find(':') + 1, address.length()).c_str());
+		address = address.substr(0, address.find(':'));
+	}
+
+	return HostAddressPort(HostAddress(address), port);
+}
+
+}
diff --git a/Swiften/Network/EnvironmentProxyProvider.h b/Swiften/Network/EnvironmentProxyProvider.h
new file mode 100644
index 0000000..1743269
--- /dev/null
+++ b/Swiften/Network/EnvironmentProxyProvider.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include "Swiften/Network/ProxyProvider.h"
+
+namespace Swift {
+	class EnvironmentProxyProvider : public ProxyProvider {
+		public:
+			EnvironmentProxyProvider();
+			virtual HostAddressPort getHTTPConnectProxy() const;
+			virtual HostAddressPort getSOCKS5Proxy() const;
+		private:
+			HostAddressPort getFromEnv(const char* envVarName, std::string proxyProtocol);
+			HostAddressPort socksProxy;
+			HostAddressPort httpProxy;
+	};
+}
+
+
diff --git a/Swiften/Network/GConfProxyProvider.cpp b/Swiften/Network/GConfProxyProvider.cpp
new file mode 100644
index 0000000..687bf77
--- /dev/null
+++ b/Swiften/Network/GConfProxyProvider.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <iostream>
+
+#include <gconf/gconf-client.h>
+
+#include "Swiften/Base/Log.h"
+#include "Swiften/Network/GConfProxyProvider.h"
+
+namespace Swift {
+
+GConfProxyProvider::GConfProxyProvider() {
+	socksProxy = getFromGConf("/system/proxy/socks_host", "/system/proxy/socks_port");
+	httpProxy = getFromGConf("/system/http_proxy/host", "/system/http_proxy/port");
+	SWIFT_LOG(debug) << "GConf: SOCKS5 => " << socksProxy.toString() << "; HTTP Connect => " << httpProxy.toString() << std::endl;
+}
+
+HostAddressPort GConfProxyProvider::getHTTPConnectProxy() const {
+	return httpProxy;
+}
+
+HostAddressPort GConfProxyProvider::getSOCKS5Proxy() const {
+	return socksProxy;
+}
+
+HostAddressPort GConfProxyProvider::getFromGConf(const char* gcHost, const char* gcPort) {
+	std::string address;
+	int port = 0;
+	gchar* str;
+
+	GConfClient* client = gconf_client_get_default();
+
+	str = gconf_client_get_string(client, gcHost, NULL);
+	port = static_cast<int> (gconf_client_get_int(client, gcPort, NULL));
+
+	if(str) {
+		address = static_cast<char*> (str);
+		g_free(str);
+	}
+
+	g_object_unref(client);
+	return HostAddressPort(HostAddress(address), port);
+}
+
+}
diff --git a/Swiften/Network/GConfProxyProvider.h b/Swiften/Network/GConfProxyProvider.h
new file mode 100644
index 0000000..15586ad
--- /dev/null
+++ b/Swiften/Network/GConfProxyProvider.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include "Swiften/Network/ProxyProvider.h"
+
+namespace Swift {
+	class GConfProxyProvider : public ProxyProvider {
+		public:
+			GConfProxyProvider();
+			virtual HostAddressPort getHTTPConnectProxy() const;
+			virtual HostAddressPort getSOCKS5Proxy() const;
+		private:
+			HostAddressPort getFromGConf(const char* gcHost, const char* gcPort);
+			HostAddressPort socksProxy;
+			HostAddressPort httpProxy;
+	};
+}
+
+
diff --git a/Swiften/Network/HTTPConnectProxiedConnection.cpp b/Swiften/Network/HTTPConnectProxiedConnection.cpp
new file mode 100644
index 0000000..4e05f29
--- /dev/null
+++ b/Swiften/Network/HTTPConnectProxiedConnection.cpp
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include "Swiften/Network/HTTPConnectProxiedConnection.h"
+
+#include <iostream>
+#include <boost/bind.hpp>
+#include <boost/thread.hpp>
+#include <boost/lexical_cast.hpp>
+#include <math.h>
+
+#include "Swiften/Base/Log.h"
+#include "Swiften/Base/String.h"
+#include "Swiften/Base/ByteArray.h"
+#include "Swiften/Network/HostAddressPort.h"
+
+namespace Swift {
+
+HTTPConnectProxiedConnection::HTTPConnectProxiedConnection(ConnectionFactory* connectionFactory, HostAddressPort proxy)
+: connectionFactory_(connectionFactory), proxy_(proxy), server_(HostAddressPort(HostAddress("0.0.0.0"), 0))
+{
+	connected_ = false;
+}
+
+HTTPConnectProxiedConnection::~HTTPConnectProxiedConnection() {
+	if(connection_) {
+		connection_->onDataRead.disconnect(boost::bind(&HTTPConnectProxiedConnection::handleDataRead, shared_from_this(), _1));
+		connection_->onDisconnected.disconnect(boost::bind(&HTTPConnectProxiedConnection::handleDisconnected, shared_from_this(), _1));
+	}
+
+	if(connected_) {
+		std::cerr << "Warning: Connection was still established." << std::endl;
+	}
+}
+
+void HTTPConnectProxiedConnection::connect(const HostAddressPort& server) {
+	server_ = server;
+	connection_ = connectionFactory_->createConnection();
+	connection_->onConnectFinished.connect(boost::bind(&HTTPConnectProxiedConnection::handleConnectionConnectFinished, shared_from_this(), _1));
+	connection_->onDataRead.connect(boost::bind(&HTTPConnectProxiedConnection::handleDataRead, shared_from_this(), _1));
+	connection_->onDisconnected.connect(boost::bind(&HTTPConnectProxiedConnection::handleDisconnected, shared_from_this(), _1));
+	connection_->connect(proxy_);
+}
+
+void HTTPConnectProxiedConnection::listen() {
+	assert(false);
+	connection_->listen();
+}
+
+void HTTPConnectProxiedConnection::disconnect() {
+	connected_ = false;
+	connection_->disconnect();
+}
+
+void HTTPConnectProxiedConnection::handleDisconnected(const boost::optional<Error>& error) {
+	onDisconnected(error);
+}
+
+void HTTPConnectProxiedConnection::write(const ByteArray& data) {
+	connection_->write(data);
+}
+
+void HTTPConnectProxiedConnection::handleConnectionConnectFinished(bool error) {
+	connection_->onConnectFinished.disconnect(boost::bind(&HTTPConnectProxiedConnection::handleConnectionConnectFinished, shared_from_this(), _1));
+	if(!error) {
+		proxyState_ = ProxyConnecting;
+		std::stringstream connect;
+		connect << "CONNECT " << server_.getAddress().toString() << ":" << server_.getPort() << " HTTP/1.1\r\n\r\n";
+		connection_->write(ByteArray(connect.str()));
+	}
+	else {
+		onConnectFinished(true);
+	}
+}
+
+void HTTPConnectProxiedConnection::handleDataRead(const ByteArray& data) {
+	if (!connected_) {
+		if (proxyState_ == ProxyConnecting) {
+			SWIFT_LOG(debug) << data.toString() << std::endl;
+			std::vector<std::string> tmp = String::split(data.toString(), ' ');
+			if(tmp.size() > 1) {
+				int status = boost::lexical_cast<int> (tmp[1].c_str()); 
+				SWIFT_LOG(debug) << "Proxy Status: " << status << std::endl;
+				if (status / 100 == 2) { // all 2XX states are OK
+					connected_ = true;
+					onConnectFinished(false);
+					return;
+				}
+			}
+
+			std::cerr << "HTTP Proxy returned an error: " << data.toString() << std::endl;
+			return;
+		}
+	}
+	else {
+		onDataRead(data);
+		return;
+	}
+	disconnect();
+	onConnectFinished(true);
+}
+
+HostAddressPort HTTPConnectProxiedConnection::getLocalAddress() const {
+	return connection_->getLocalAddress();
+}
+
+//namespace
+}
diff --git a/Swiften/Network/HTTPConnectProxiedConnection.h b/Swiften/Network/HTTPConnectProxiedConnection.h
new file mode 100644
index 0000000..88b4f66
--- /dev/null
+++ b/Swiften/Network/HTTPConnectProxiedConnection.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include <boost/enable_shared_from_this.hpp>
+
+#include "Swiften/Network/ConnectionFactory.h"
+#include "Swiften/Network/Connection.h"
+#include "Swiften/Network/HostAddressPort.h"
+
+namespace boost {
+	class thread;
+	namespace system {
+		class error_code;
+	}
+}
+
+namespace Swift {
+	class HTTPConnectProxiedConnection : public Connection, public boost::enable_shared_from_this<HTTPConnectProxiedConnection> {
+		public:
+			typedef boost::shared_ptr<HTTPConnectProxiedConnection> ref;
+
+			~HTTPConnectProxiedConnection();
+
+			static ref create(ConnectionFactory* connectionFactory, HostAddressPort proxy) {
+				return ref(new HTTPConnectProxiedConnection(connectionFactory, proxy));
+			}
+
+			virtual void listen();
+			virtual void connect(const HostAddressPort& address);
+			virtual void disconnect();
+			virtual void write(const ByteArray& data);
+
+			virtual HostAddressPort getLocalAddress() const;
+		private:
+			enum {
+				ProxyAuthenticating = 0,
+				ProxyConnecting,
+			} proxyState_;
+
+			HTTPConnectProxiedConnection(ConnectionFactory* connectionFactory, HostAddressPort proxy);
+
+			void handleConnectionConnectFinished(bool error);
+			void handleDataRead(const ByteArray& data);
+			void handleDisconnected(const boost::optional<Error>& error);
+
+		private:
+			bool connected_;
+			ConnectionFactory* connectionFactory_;	
+			HostAddressPort proxy_;
+			HostAddressPort server_;
+			boost::shared_ptr<Connection> connection_;
+	};
+}
diff --git a/Swiften/Network/HTTPConnectProxiedConnectionFactory.cpp b/Swiften/Network/HTTPConnectProxiedConnectionFactory.cpp
new file mode 100644
index 0000000..0212945
--- /dev/null
+++ b/Swiften/Network/HTTPConnectProxiedConnectionFactory.cpp
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include "Swiften/Network/HTTPConnectProxiedConnectionFactory.h"
+#include "Swiften/Network/HTTPConnectProxiedConnection.h"
+
+namespace Swift {
+
+HTTPConnectProxiedConnectionFactory::HTTPConnectProxiedConnectionFactory(ConnectionFactory* connectionFactory, HostAddressPort proxy)
+: connectionFactory_(connectionFactory), proxy_(proxy)
+{
+
+}
+
+boost::shared_ptr<Connection> HTTPConnectProxiedConnectionFactory::createConnection() {
+	return HTTPConnectProxiedConnection::create(connectionFactory_, proxy_);
+}
+
+}
diff --git a/Swiften/Network/HTTPConnectProxiedConnectionFactory.h b/Swiften/Network/HTTPConnectProxiedConnectionFactory.h
new file mode 100644
index 0000000..7aeb337
--- /dev/null
+++ b/Swiften/Network/HTTPConnectProxiedConnectionFactory.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include "Swiften/Network/ConnectionFactory.h"
+#include "Swiften/Network/HTTPConnectProxiedConnection.h"
+#include "Swiften/Network/HostAddressPort.h"
+
+namespace Swift {
+	class HTTPConnectProxiedConnection;
+
+	class HTTPConnectProxiedConnectionFactory : public ConnectionFactory {
+		public:
+			HTTPConnectProxiedConnectionFactory(ConnectionFactory* connectionFactory, HostAddressPort proxy);
+
+			virtual boost::shared_ptr<Connection> createConnection();
+
+		private:
+			ConnectionFactory* connectionFactory_;
+			HostAddressPort proxy_;
+	};
+}
diff --git a/Swiften/Network/HostAddress.cpp b/Swiften/Network/HostAddress.cpp
index 331a233..f734329 100644
--- a/Swiften/Network/HostAddress.cpp
+++ b/Swiften/Network/HostAddress.cpp
@@ -57,4 +57,8 @@ bool HostAddress::isValid() const {
 	return !(address_.is_v4() && address_.to_v4().to_ulong() == 0);
 }
 
+boost::asio::ip::address HostAddress::getRawAddress() const {
+	return address_;
+}
+
 }
diff --git a/Swiften/Network/HostAddress.h b/Swiften/Network/HostAddress.h
index 3e9c8a6..0b3bdda 100644
--- a/Swiften/Network/HostAddress.h
+++ b/Swiften/Network/HostAddress.h
@@ -3,7 +3,6 @@
  * Licensed under the GNU General Public License v3.
  * See Documentation/Licenses/GPLv3.txt for more information.
  */
-
 #pragma once
 
 #include <string>
@@ -18,6 +17,7 @@ namespace Swift {
 			HostAddress(const boost::asio::ip::address& address);
 
 			std::string toString() const;
+			boost::asio::ip::address getRawAddress() const;
 
 			bool operator==(const HostAddress& o) const {
 				return address_ == o.address_;
diff --git a/Swiften/Network/HostAddressPort.h b/Swiften/Network/HostAddressPort.h
index c99ca65..5655f4d 100644
--- a/Swiften/Network/HostAddressPort.h
+++ b/Swiften/Network/HostAddressPort.h
@@ -7,6 +7,7 @@
 #pragma once
 
 #include <boost/asio/ip/tcp.hpp>
+#include <boost/lexical_cast.hpp>
 
 #include "Swiften/Network/HostAddress.h"
 
@@ -37,6 +38,10 @@ namespace Swift {
 			bool isValid() const {
 				return address_.isValid() && port_ > 0;
 			}
+			
+			std::string toString() const {
+				return getAddress().toString() + ":" + boost::lexical_cast<std::string>(getPort());
+			}
 
 		private:
 			HostAddress address_;
diff --git a/Swiften/Network/MacOSXProxyProvider.cpp b/Swiften/Network/MacOSXProxyProvider.cpp
new file mode 100644
index 0000000..babcc7f
--- /dev/null
+++ b/Swiften/Network/MacOSXProxyProvider.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <iostream>
+#include <utility>
+
+#include "Swiften/Network/MacOSXProxyProvider.h"
+#include <SystemConfiguration/SystemConfiguration.h>
+
+namespace Swift {
+
+MacOSXProxyProvider::MacOSXProxyProvider()
+: ProxyProvider()
+{
+	CFDictionaryRef proxies = SCDynamicStoreCopyProxies(NULL);
+	if(proxies != NULL) {
+		socksProxy = getFromDictionary(proxies, kSCPropNetProxiesSOCKSEnable, kSCPropNetProxiesSOCKSProxy, kSCPropNetProxiesSOCKSPort);
+		httpProxy = getFromDictionary(proxies, kSCPropNetProxiesHTTPEnable, kSCPropNetProxiesHTTPProxy, kSCPropNetProxiesHTTPPort);
+	}
+}
+
+HostAddressPort MacOSXProxyProvider::getHTTPConnectProxy() const {
+	return httpProxy;
+}
+
+HostAddressPort MacOSXProxyProvider::getSOCKS5Proxy() const {
+	return socksProxy;
+}
+
+HostAddressPort MacOSXProxyProvider::getFromDictionary(CFDictionaryRef dict, CFStringRef enabledKey, CFStringRef hostKey, CFStringRef portKey) {
+	CFNumberRef numberValue = NULL;
+	HostAddressPort ret = HostAddressPort(HostAddress(), 0);
+
+	if(CFDictionaryGetValueIfPresent(dict, reinterpret_cast<const void*> (enabledKey), reinterpret_cast<const void**> (&numberValue)) == true) {
+		const int i = 0;
+		CFNumberRef zero = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &i);
+		CFComparisonResult result = CFNumberCompare(numberValue, zero, NULL);
+		CFRelease(numberValue);
+
+		if(result != kCFCompareEqualTo) {
+			int port = 0;
+			std::string host = "";
+
+			try {
+				CFNumberRef numberValue = reinterpret_cast<CFNumberRef> (CFDictionaryGetValue(dict, portKey));
+				if(numberValue != NULL) {
+					CFNumberGetValue(numberValue, kCFNumberIntType, &port);
+					CFRelease(numberValue);
+				}
+
+				CFStringRef stringValue = reinterpret_cast<CFStringRef> (CFDictionaryGetValue(dict, hostKey));
+				if(stringValue != NULL) {
+					std::vector<char> buffer;
+ 					// length must be +1 for the ending zero; and the Docu of CFStringGetCString tells it like
+					// if the string is toby the length must be at least 5.
+					CFIndex length = CFStringGetLength(stringValue) + 1;
+					buffer.resize(length);
+					if(CFStringGetCString(stringValue, &buffer[0], length, kCFStringEncodingMacRoman)) {
+						for(std::vector<char>::iterator iter = buffer.begin(); iter != buffer.end(); iter++) {
+							host += *iter;
+						}
+					}
+					CFRelease(stringValue);
+				}
+			}
+			catch(...) {
+				std::cerr << "Exception caught ... " << std::endl;
+			}
+			
+			if(host != "" && port != 0) {
+				ret = HostAddressPort(HostAddress(host), port);
+			}
+		}
+	}
+	return ret;
+}
+
+}
diff --git a/Swiften/Network/MacOSXProxyProvider.h b/Swiften/Network/MacOSXProxyProvider.h
new file mode 100644
index 0000000..1cb001f
--- /dev/null
+++ b/Swiften/Network/MacOSXProxyProvider.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+#include "Swiften/Network/ProxyProvider.h"
+#include <CoreFoundation/CoreFoundation.h>
+
+namespace Swift {
+	class MacOSXProxyProvider : public ProxyProvider {
+		public:
+			MacOSXProxyProvider();
+			virtual HostAddressPort getHTTPConnectProxy() const;
+			virtual HostAddressPort getSOCKS5Proxy() const;
+
+		private:
+			HostAddressPort getFromDictionary(CFDictionaryRef dict, CFStringRef enabledKey, CFStringRef hostKey, CFStringRef portKey);
+			HostAddressPort socksProxy;
+			HostAddressPort httpProxy;
+	};
+}
diff --git a/Swiften/Network/PlatformProxyProvider.h b/Swiften/Network/PlatformProxyProvider.h
new file mode 100644
index 0000000..13b15d2
--- /dev/null
+++ b/Swiften/Network/PlatformProxyProvider.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include "Swiften/Base/Platform.h"
+
+#if defined(SWIFTEN_PLATFORM_MACOSX)
+#include "Swiften/Network/MacOSXProxyProvider.h"
+namespace Swift {
+	typedef MacOSXProxyProvider PlatformProxyProvider;
+}
+#elif defined(SWIFTEN_PLATFORM_WIN32)
+#include "Swiften/Network/WindowsProxyProvider.h"
+namespace Swift {
+	typedef WindowsProxyProvider PlatformProxyProvider;
+}
+#else
+#include "Swiften/Network/UnixProxyProvider.h"
+namespace Swift {
+	typedef UnixProxyProvider PlatformProxyProvider;
+}
+#endif
diff --git a/Swiften/Network/ProxyProvider.cpp b/Swiften/Network/ProxyProvider.cpp
new file mode 100644
index 0000000..fe235b1
--- /dev/null
+++ b/Swiften/Network/ProxyProvider.cpp
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include "ProxyProvider.h"
+
+namespace Swift {
+
+ProxyProvider::ProxyProvider()
+{
+}
+
+ProxyProvider::~ProxyProvider()
+{
+}
+
+}
diff --git a/Swiften/Network/ProxyProvider.h b/Swiften/Network/ProxyProvider.h
new file mode 100644
index 0000000..05bb5a7
--- /dev/null
+++ b/Swiften/Network/ProxyProvider.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+#include <map>
+
+#include "Swiften/Base/Log.h"
+#include "Swiften/Network/HostAddressPort.h"
+#include "Swiften/Base/String.h"
+
+namespace Swift {
+	class ProxyProvider {
+		public:
+			ProxyProvider();
+			virtual ~ProxyProvider();
+			virtual HostAddressPort getHTTPConnectProxy() const = 0;
+			virtual HostAddressPort getSOCKS5Proxy() const = 0;
+	};
+}
+
diff --git a/Swiften/Network/SConscript b/Swiften/Network/SConscript
index 93732d1..426118b 100644
--- a/Swiften/Network/SConscript
+++ b/Swiften/Network/SConscript
@@ -6,6 +6,10 @@ if myenv.get("HAVE_CARES", False) :
    myenv.MergeFlags(myenv.get("CARES_FLAGS", {}))
 
 sourceList = [
+			"HTTPConnectProxiedConnection.cpp",
+			"HTTPConnectProxiedConnectionFactory.cpp",
+			"SOCKS5ProxiedConnection.cpp",
+			"SOCKS5ProxiedConnectionFactory.cpp",
 			"BoostConnection.cpp",
 			"BoostConnectionFactory.cpp",
 			"BoostConnectionServer.cpp",
@@ -30,10 +34,25 @@ sourceList = [
 			"NetworkFactories.cpp",
 			"BoostNetworkFactories.cpp",
 			"Timer.cpp",
-			"BoostTimer.cpp"]
+			"BoostTimer.cpp",
+			"ProxyProvider.cpp"
+	]
+
 if myenv.get("HAVE_CARES", False) :
    sourceList.append("CAresDomainNameResolver.cpp")
 		
+if myenv["PLATFORM"] == "darwin" :
+	myenv.Append(FRAMEWORKS = ["CoreServices", "SystemConfiguration"])
+	sourceList += [ "MacOSXProxyProvider.cpp" ]
+elif myenv["PLATFORM"] == "win32" :
+	sourceList += [ "WindowsProxyProvider.cpp" ]
+else :
+	sourceList += [ "UnixProxyProvider.cpp" ]
+	sourceList += [ "EnvironmentProxyProvider.cpp" ]
+	if myenv.get("HAVE_GCONF", 0) :
+		myenv.Append(CPPDEFINES = "HAVE_GCONF")
+		myenv.MergeFlags(myenv["GCONF_FLAGS"])
+		sourceList += [ "GConfProxyProvider.cpp" ]
 
 objects = myenv.SwiftenObject(sourceList)
 swiften_env.Append(SWIFTEN_OBJECTS = [objects])
diff --git a/Swiften/Network/SOCKS5ProxiedConnection.cpp b/Swiften/Network/SOCKS5ProxiedConnection.cpp
new file mode 100644
index 0000000..d32a0f9
--- /dev/null
+++ b/Swiften/Network/SOCKS5ProxiedConnection.cpp
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include "Swiften/Network/SOCKS5ProxiedConnection.h"
+
+#include <iostream>
+#include <boost/bind.hpp>
+#include <boost/thread.hpp>
+#include <math.h>
+
+#include "Swiften/Base/Log.h"
+#include "Swiften/Base/String.h"
+#include "Swiften/Base/ByteArray.h"
+#include "Swiften/Network/HostAddressPort.h"
+
+namespace Swift {
+
+SOCKS5ProxiedConnection::SOCKS5ProxiedConnection(ConnectionFactory* connectionFactory, HostAddressPort proxy)
+: connectionFactory_(connectionFactory), proxy_(proxy), server_(HostAddressPort(HostAddress("0.0.0.0"), 0))
+{
+	connected_ = false;
+}
+
+SOCKS5ProxiedConnection::~SOCKS5ProxiedConnection() {
+	if(connection_) {
+		connection_->onDataRead.disconnect(boost::bind(&SOCKS5ProxiedConnection::handleDataRead, shared_from_this(), _1));
+		connection_->onDisconnected.disconnect(boost::bind(&SOCKS5ProxiedConnection::handleDisconnected, shared_from_this(), _1));
+	}
+
+	if(connected_) {
+		std::cerr << "Warning: Connection was still established." << std::endl;
+	}
+}
+
+void SOCKS5ProxiedConnection::connect(const HostAddressPort& server) {
+	server_ = server;
+	connection_ = connectionFactory_->createConnection();
+	connection_->onConnectFinished.connect(boost::bind(&SOCKS5ProxiedConnection::handleConnectionConnectFinished, shared_from_this(), _1));
+	connection_->onDataRead.connect(boost::bind(&SOCKS5ProxiedConnection::handleDataRead, shared_from_this(), _1));
+	connection_->onDisconnected.connect(boost::bind(&SOCKS5ProxiedConnection::handleDisconnected, shared_from_this(), _1));
+	SWIFT_LOG(debug) << "Trying to connect via proxy " << proxy_.getAddress().toString() << ":" << proxy_.getPort() << std::endl;
+	SWIFT_LOG(debug) << "to server " << server.getAddress().toString() << ":" << server.getPort() << std::endl;
+	connection_->connect(proxy_);
+}
+
+void SOCKS5ProxiedConnection::listen() {
+	assert(false);
+	connection_->listen();
+}
+
+void SOCKS5ProxiedConnection::disconnect() {
+	connected_ = false;
+	if(connection_)
+		connection_->disconnect();
+}
+
+void SOCKS5ProxiedConnection::handleDisconnected(const boost::optional<Error>& error) {
+	onDisconnected(error);
+}
+
+void SOCKS5ProxiedConnection::write(const ByteArray& data) {
+	if(connection_)
+		connection_->write(data);
+}
+
+void SOCKS5ProxiedConnection::handleConnectionConnectFinished(bool error) {
+	connection_->onConnectFinished.disconnect(boost::bind(&SOCKS5ProxiedConnection::handleConnectionConnectFinished, shared_from_this(), _1));
+	if(!error) {
+		SWIFT_LOG(debug) << "Connection to proxy established, now connect to the server via it." << std::endl;
+		
+		proxyState_ = ProxyAuthenticating;
+		ByteArray socksConnect;
+		socksConnect += 0x05; // VER = SOCKS5 = 0x05
+		socksConnect += 0x01; // Number of authentication methods after this byte.
+		socksConnect += 0x00; // 0x00 == no authentication
+		// buffer.push_back(0x01); // 0x01 == GSSAPI 
+		// buffer.push_back(0x02); // 0x02 ==  Username/Password
+		// rest see RFC 1928 (http://tools.ietf.org/html/rfc1928)
+		connection_->write(socksConnect);
+	}
+	else {
+		onConnectFinished(true);
+	}
+}
+
+void SOCKS5ProxiedConnection::handleDataRead(const ByteArray& data) {
+	ByteArray socksConnect;
+	boost::asio::ip::address rawAddress = server_.getAddress().getRawAddress();
+	assert(rawAddress.is_v4() || rawAddress.is_v6());
+	if (!connected_) {
+		if (proxyState_ == ProxyAuthenticating) {
+			SWIFT_LOG(debug) << "ProxyAuthenticating response received, reply with the connect BYTEs" << std::endl;
+			unsigned char choosenMethod = static_cast<unsigned char> (data[1]);
+			if (data[0] == 0x05 && choosenMethod != 0xFF) {
+				switch(choosenMethod) { // use the correct Method
+					case 0x00:
+						try {
+							proxyState_ = ProxyConnecting;
+							socksConnect += 0x05; // VER = SOCKS5 = 0x05
+							socksConnect += 0x01; // Construct a TCP connection. (CMD)
+							socksConnect += 0x00; // reserved.
+							socksConnect += rawAddress.is_v4() ? 0x01 : 0x04; // IPv4 == 0x01, Hostname == 0x02, IPv6 == 0x04. (ATYP)
+							size_t size = rawAddress.is_v4() ? rawAddress.to_v4().to_bytes().size() : rawAddress.to_v6().to_bytes().size();
+							for (size_t s = 0; s < size; s++) {
+								unsigned char uc;
+								if(rawAddress.is_v4()) {
+									uc = rawAddress.to_v4().to_bytes()[s]; // the address.
+								}
+								else
+									uc = rawAddress.to_v6().to_bytes()[s]; // the address.
+								socksConnect += static_cast<char> (uc);
+						
+							}
+							socksConnect += static_cast<unsigned char> (server_.getPort() >> 8); // highbyte of the port.
+							socksConnect += static_cast<unsigned char> (server_.getPort()); // lowbyte of the port.
+							connection_->write(socksConnect);
+							return;
+						}
+						catch(...) {
+							std::cerr << "exception caught" << std::endl;
+						}
+						connection_->write(socksConnect);
+						break;
+					default:
+						onConnectFinished(true);
+						break;
+				}
+				return;
+			}
+		}
+		else if (proxyState_ == ProxyConnecting) {
+			SWIFT_LOG(debug) << "Connect response received, check if successfully." << std::endl;
+			SWIFT_LOG(debug) << "Errorbyte: 0x" << std::hex << static_cast<int> (data[1]) << std::dec << std::endl;
+			/*
+
+			data.at(1) can be one of the following:
+			0x00 	succeeded
+			0x01 	general SOCKS server failure
+			0x02 	connection not allowed by ruleset
+			0x03 	Network unreachable
+			0x04 	Host unreachable
+			0x05 	Connection refused
+			0x06 	TTL expired
+			0x07 	Command not supported (CMD)
+			0x08 	Address type not supported (ATYP)
+			0x09 bis 0xFF 	unassigned
+			*/
+			if (data[0] == 0x05 && data[1] == 0x0) {
+				SWIFT_LOG(debug) << "Successfully connected the server via the proxy." << std::endl;
+				connected_ = true;
+				onConnectFinished(false);
+				return;
+			}
+			else {
+				std::cerr << "SOCKS Proxy returned an error: " << std::hex << data[1] << std::endl;
+			}
+			return;
+		}
+	}
+	else {
+		onDataRead(data);
+		return;
+	}
+	disconnect();
+	onConnectFinished(true);
+}
+
+HostAddressPort SOCKS5ProxiedConnection::getLocalAddress() const {
+	return connection_->getLocalAddress();
+}
+
+//namespace
+}
diff --git a/Swiften/Network/SOCKS5ProxiedConnection.h b/Swiften/Network/SOCKS5ProxiedConnection.h
new file mode 100644
index 0000000..b222fd7
--- /dev/null
+++ b/Swiften/Network/SOCKS5ProxiedConnection.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include <boost/asio.hpp>
+#include <boost/enable_shared_from_this.hpp>
+
+#include "Swiften/Network/ConnectionFactory.h"
+#include "Swiften/Network/Connection.h"
+#include "Swiften/Network/HostAddressPort.h"
+
+namespace boost {
+	class thread;
+	namespace system {
+		class error_code;
+	}
+}
+
+namespace Swift {
+	class SOCKS5ProxiedConnection : public Connection, public boost::enable_shared_from_this<SOCKS5ProxiedConnection> {
+		public:
+			typedef boost::shared_ptr<SOCKS5ProxiedConnection> ref;
+
+			~SOCKS5ProxiedConnection();
+
+			static ref create(ConnectionFactory* connectionFactory, HostAddressPort proxy) {
+				return ref(new SOCKS5ProxiedConnection(connectionFactory, proxy));
+			}
+
+			virtual void listen();
+			virtual void connect(const HostAddressPort& address);
+			virtual void disconnect();
+			virtual void write(const ByteArray& data);
+
+			virtual HostAddressPort getLocalAddress() const;
+		private:
+			enum {
+				ProxyAuthenticating = 0,
+				ProxyConnecting,
+			} proxyState_;
+
+			SOCKS5ProxiedConnection(ConnectionFactory* connectionFactory, HostAddressPort proxy);
+
+			void handleConnectionConnectFinished(bool error);
+			void handleDataRead(const ByteArray& data);
+			void handleDisconnected(const boost::optional<Error>& error);
+
+		private:
+			bool connected_;
+			ConnectionFactory* connectionFactory_;	
+			HostAddressPort proxy_;
+			HostAddressPort server_;
+			boost::shared_ptr<Connection> connection_;
+	};
+}
diff --git a/Swiften/Network/SOCKS5ProxiedConnectionFactory.cpp b/Swiften/Network/SOCKS5ProxiedConnectionFactory.cpp
new file mode 100644
index 0000000..0be0931
--- /dev/null
+++ b/Swiften/Network/SOCKS5ProxiedConnectionFactory.cpp
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include "Swiften/Network/SOCKS5ProxiedConnectionFactory.h"
+#include "Swiften/Network/SOCKS5ProxiedConnection.h"
+
+namespace Swift {
+
+SOCKS5ProxiedConnectionFactory::SOCKS5ProxiedConnectionFactory(ConnectionFactory* connectionFactory, HostAddressPort proxy)
+: connectionFactory_(connectionFactory), proxy_(proxy)
+{
+
+}
+
+boost::shared_ptr<Connection> SOCKS5ProxiedConnectionFactory::createConnection() {
+	return SOCKS5ProxiedConnection::create(connectionFactory_, proxy_);
+}
+
+}
diff --git a/Swiften/Network/SOCKS5ProxiedConnectionFactory.h b/Swiften/Network/SOCKS5ProxiedConnectionFactory.h
new file mode 100644
index 0000000..a78a9e8
--- /dev/null
+++ b/Swiften/Network/SOCKS5ProxiedConnectionFactory.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include <boost/asio.hpp>
+
+#include "Swiften/Network/ConnectionFactory.h"
+#include "Swiften/Network/SOCKS5ProxiedConnection.h"
+#include "Swiften/Network/HostAddressPort.h"
+
+namespace Swift {
+	class SOCKS5ProxiedConnection;
+
+	class SOCKS5ProxiedConnectionFactory : public ConnectionFactory {
+		public:
+			SOCKS5ProxiedConnectionFactory(ConnectionFactory* connectionFactory, HostAddressPort proxy);
+
+			virtual boost::shared_ptr<Connection> createConnection();
+
+		private:
+			ConnectionFactory* connectionFactory_;
+			HostAddressPort proxy_;
+	};
+}
diff --git a/Swiften/Network/UnixProxyProvider.cpp b/Swiften/Network/UnixProxyProvider.cpp
new file mode 100644
index 0000000..e21b310
--- /dev/null
+++ b/Swiften/Network/UnixProxyProvider.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <iostream>
+
+#include "Swiften/Base/foreach.h"
+#include "Swiften/Network/UnixProxyProvider.h"
+
+namespace Swift {
+
+UnixProxyProvider::UnixProxyProvider() :
+#if defined(HAVE_GCONF)
+	gconfProxyProvider(),
+#endif
+	environmentProxyProvider()
+{
+}
+
+HostAddressPort UnixProxyProvider::getSOCKS5Proxy() const {
+	HostAddressPort proxy;
+#if defined(HAVE_GCONF)
+	proxy = gconfProxyProvider.getSOCKS5Proxy();
+	if(proxy.isValid()) {
+		return proxy;
+	}
+#endif
+	proxy = environmentProxyProvider.getSOCKS5Proxy();
+	if(proxy.isValid()) {
+		return proxy;
+	}
+	return HostAddressPort(HostAddress(), 0);
+}
+
+HostAddressPort UnixProxyProvider::getHTTPConnectProxy() const {
+	HostAddressPort proxy;
+#if defined(HAVE_GCONF)
+	proxy = gconfProxyProvider.getHTTPConnectProxy();
+	if(proxy.isValid()) {
+		return proxy;
+	}
+#endif
+	proxy = environmentProxyProvider.getHTTPConnectProxy();
+	if(proxy.isValid()) {
+		return proxy;
+	}
+	return HostAddressPort(HostAddress(), 0);
+}
+
+
+}
diff --git a/Swiften/Network/UnixProxyProvider.h b/Swiften/Network/UnixProxyProvider.h
new file mode 100644
index 0000000..509cf4b
--- /dev/null
+++ b/Swiften/Network/UnixProxyProvider.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+#if defined(HAVE_GCONF)
+#  include "Swiften/Network/GConfProxyProvider.h"
+#endif
+#include "Swiften/Network/EnvironmentProxyProvider.h"
+
+namespace Swift {
+	class UnixProxyProvider : public ProxyProvider {
+		public:
+			UnixProxyProvider();
+			virtual HostAddressPort getHTTPConnectProxy() const;
+			virtual HostAddressPort getSOCKS5Proxy() const;
+		private:
+#if defined(HAVE_GCONF)
+			GConfProxyProvider gconfProxyProvider;
+#endif
+			EnvironmentProxyProvider environmentProxyProvider;
+	};
+}
diff --git a/Swiften/Network/WindowsProxyProvider.cpp b/Swiften/Network/WindowsProxyProvider.cpp
new file mode 100644
index 0000000..5f6f5d2
--- /dev/null
+++ b/Swiften/Network/WindowsProxyProvider.cpp
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <iostream>
+#include <boost/lexical_cast.hpp>
+
+#include "Swiften/Base/log.h"
+#include "Swiften/Base/foreach.h"
+#include "Swiften/Network/WindowsProxyProvider.h"
+#include "Swiften/Base/ByteArray.h"
+
+#include <windows.h>
+
+namespace Swift {
+
+WindowsProxyProvider::WindowsProxyProvider()
+: ProxyProvider()
+{
+	HKEY hKey = (HKEY)INVALID_HANDLE_VALUE;
+	long result;
+		
+	result = RegOpenKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", 0, KEY_READ, &hKey);
+	if (result == ERROR_SUCCESS && hKey != INVALID_HANDLE_VALUE && proxyEnabled(hKey)) {
+		DWORD dataType = REG_SZ;
+		DWORD dataSize = 0;
+		ByteArray dataBuffer;
+
+		result = RegQueryValueEx(hKey, "ProxyServer", NULL, &dataType, NULL, &dataSize);
+		if(result != ERROR_SUCCESS) {
+			return;
+		}
+		dataBuffer.resize(dataSize);
+		result = RegQueryValueEx(hKey, "ProxyServer", NULL, &dataType, reinterpret_cast<BYTE*>(dataBuffer.getData()), &dataSize);
+		if(result == ERROR_SUCCESS) {
+			std::vector<std::string> proxies = String::split(dataBuffer.toString(), ';');
+			std::pair<std::string, std::string> protocolAndProxy;
+			foreach(std::string proxy, proxies) {
+				if(proxy.find('=') != std::string::npos) {
+					protocolAndProxy = String::getSplittedAtFirst(proxy, '=');
+					SWIFT_LOG(debug) << "Found proxy: " << protocolAndProxy.first << " => " << protocolAndProxy.second << std::endl;
+					if(protocolAndProxy.first.compare("socks") == 0) {
+						socksProxy = getAsHostAddressPort(protocolAndProxy.second);
+					}
+					else if (protocolAndProxy.first.compare("http") == 0) {
+						httpProxy = getAsHostAddressPort(protocolAndProxy.second);
+					}
+				}
+			}
+		}
+	}
+}
+
+HostAddressPort WindowsProxyProvider::getHTTPConnectProxy() const {
+	return httpProxy;
+}
+
+HostAddressPort WindowsProxyProvider::getSOCKS5Proxy() const {
+	return socksProxy;
+}
+
+HostAddressPort WindowsProxyProvider::getAsHostAddressPort(std::string proxy) {
+	HostAddressPort ret(HostAddress(), 0);
+
+	try {
+		std::pair<std::string, std::string> tmp;
+		int port = 0;
+		tmp = String::getSplittedAtFirst(proxy, ':');
+		// .c_str() is needed as tmp.second can include a \0 char which will end in an exception of the lexical cast.
+		// with .c_str() the \0 will not be part of the string which is to be casted
+		port = boost::lexical_cast<int> (tmp.second.c_str());
+		ret = HostAddressPort(HostAddress(tmp.first), port);
+	}
+	catch(...) {
+			std::cerr << "Exception occured while parsing windows proxy \"getHostAddressPort\"." << std::endl;
+	}
+
+	return ret;
+}
+
+
+bool WindowsProxyProvider::proxyEnabled(HKEY hKey) const {
+	bool ret = false;
+	long result;
+	DWORD dataType = REG_DWORD;
+	DWORD dataSize = 0;
+	DWORD data = 0;
+	ByteArray dataBuffer;
+
+	if(hKey == INVALID_HANDLE_VALUE)
+		return ret;
+
+	result = RegQueryValueEx(hKey, "ProxyEnable", NULL, &dataType, NULL, &dataSize);
+	if(result != ERROR_SUCCESS)
+		return ret;
+
+	dataBuffer.resize(dataSize);
+	result = RegQueryValueEx(hKey, "ProxyEnable", NULL, &dataType, reinterpret_cast<BYTE*>(dataBuffer.getData()), &dataSize);
+	if(result != ERROR_SUCCESS)
+		return ret;
+
+	for(size_t t = 0; t < dataBuffer.getSize(); t++) {
+		data += static_cast<int> (dataBuffer[t]) * pow(256, static_cast<double>(t));
+	}
+	return (data == 1);
+}
+
+}
diff --git a/Swiften/Network/WindowsProxyProvider.h b/Swiften/Network/WindowsProxyProvider.h
new file mode 100644
index 0000000..d8d08f0
--- /dev/null
+++ b/Swiften/Network/WindowsProxyProvider.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2010-2011 Thilo Cestonaro
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+#include "Swiften/Network/ProxyProvider.h"
+
+namespace Swift {
+	class WindowsProxyProvider : public ProxyProvider {
+		public:
+			WindowsProxyProvider();
+			virtual HostAddressPort getHTTPConnectProxy() const;
+			virtual HostAddressPort getSOCKS5Proxy() const;
+		private:
+			HostAddressPort getAsHostAddressPort(std::string proxy);
+			bool proxyEnabled(HKEY hKey) const;
+			HostAddressPort socksProxy;
+			HostAddressPort httpProxy;
+	};
+}
diff --git a/Swiften/QA/ProxyProviderTest/.gitignore b/Swiften/QA/ProxyProviderTest/.gitignore
new file mode 100644
index 0000000..9d4b9b8
--- /dev/null
+++ b/Swiften/QA/ProxyProviderTest/.gitignore
@@ -0,0 +1 @@
+ProxyProviderTest
diff --git a/Swiften/QA/ProxyProviderTest/ProxyProviderTest.cpp b/Swiften/QA/ProxyProviderTest/ProxyProviderTest.cpp
new file mode 100644
index 0000000..ddaee01
--- /dev/null
+++ b/Swiften/QA/ProxyProviderTest/ProxyProviderTest.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2010 Thilo Cestonaro
+ * Licensed under the BSD License.
+ * See Documentation/Licenses/BSD.txt for more information.
+ */
+
+#include <iostream>
+
+#include <Swiften/Network/PlatformProxyProvider.h>
+#include <Swiften/Base/foreach.h>
+
+using namespace Swift;
+
+int main(void)
+{
+	int ret = 0;
+	HostAddressPort hap;
+	
+	std::cout << "constructing PlatfromProxyProvider instance ..." << std::endl;
+	PlatformProxyProvider ppp;
+
+	hap = ppp.getSOCKS5Proxy();
+	std::cout << "SOCKS5 Proxy configured: " << hap.isValid() << std::endl;
+	if(hap.isValid()) {
+		std::cout << "SOCKS5 Proxy: " << hap.getAddress().toString() << ":" << hap.getPort() << std::endl;
+	}
+
+	hap = ppp.getHTTPConnectProxy();
+	std::cout << "HTTPConnect Proxy configured: " << hap.isValid() << std::endl;
+	if(hap.isValid()) {
+		std::cout << "HTTPConnect Proxy: " << hap.getAddress().toString() << ":" << hap.getPort() << std::endl;
+	}
+
+	return ret;
+}
diff --git a/Swiften/QA/ProxyProviderTest/SConscript b/Swiften/QA/ProxyProviderTest/SConscript
new file mode 100644
index 0000000..e9c5139
--- /dev/null
+++ b/Swiften/QA/ProxyProviderTest/SConscript
@@ -0,0 +1,11 @@
+import os
+
+Import("env")
+
+myenv = env.Clone()
+myenv.MergeFlags(myenv["SWIFTEN_FLAGS"])
+myenv.MergeFlags(myenv["BOOST_FLAGS"])
+
+myenv.Program("ProxyProviderTest", [
+		"ProxyProviderTest.cpp",
+	])
diff --git a/Swiften/QA/SConscript b/Swiften/QA/SConscript
index 25ba814..41d7206 100644
--- a/Swiften/QA/SConscript
+++ b/Swiften/QA/SConscript
@@ -8,4 +8,5 @@ SConscript(dirs = [
 		"StorageTest",
 		"TLSTest",
 		"ScriptedTests",
+		"ProxyProviderTest",
 	])
diff --git a/Swiften/SConscript b/Swiften/SConscript
index 57c95fc..0a229e8 100644
--- a/Swiften/SConscript
+++ b/Swiften/SConscript
@@ -159,6 +159,9 @@ if env["SCONS_STAGE"] == "build" :
 			"StringCodecs/Hexify.cpp",
 		]
 
+	if myenv["PLATFORM"] != "darwin" and myenv["PLATFORM"] != "win32" and myenv.get("HAVE_GCONF", 0) :
+		env.MergeFlags(env["GCONF_FLAGS"])
+
 	SConscript(dirs = [
 			"Avatars",
 			"Base",
@@ -333,6 +336,8 @@ if env["SCONS_STAGE"] == "build" :
 					continue
 				if file.startswith("CAres") or file.startswith("LibXML") or file.startswith("Expat") or file.startswith("foreach") or file.startswith("Log.h") or file.startswith("format.h") :
 					continue
+				if file.find("ProxyProvider") != -1 :
+					continue
 				swiften_header += "#include <" + include + ">\n"
 				swiften_includes.append(include)
 	for file in ["EventLoop/SimpleEventLoop.h"] :
-- 
cgit v0.10.2-6-g49f6