From 5616ff49792238b451486f41b187744866d20056 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Sat, 8 May 2010 10:01:56 +0200
Subject: Added DIGEST-MD5 properties.


diff --git a/Swiften/Base/ByteArray.h b/Swiften/Base/ByteArray.h
index 4cedd9a..21cfb87 100644
--- a/Swiften/Base/ByteArray.h
+++ b/Swiften/Base/ByteArray.h
@@ -74,6 +74,11 @@ namespace Swift {
 				return *this;
 			}
 
+			ByteArray& operator+=(char c) {
+				data_.push_back(c);
+				return *this;
+			}
+
 			friend bool operator==(const ByteArray& a, const ByteArray& b) {
 				return a.data_ == b.data_;
 			}
diff --git a/Swiften/SASL/DIGESTMD5Properties.cpp b/Swiften/SASL/DIGESTMD5Properties.cpp
new file mode 100644
index 0000000..23dc097
--- /dev/null
+++ b/Swiften/SASL/DIGESTMD5Properties.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include "Swiften/SASL/DIGESTMD5Properties.h"
+
+namespace Swift {
+
+DIGESTMD5Properties::DIGESTMD5Properties() {
+}
+
+DIGESTMD5Properties DIGESTMD5Properties::parse(const ByteArray&) {
+	DIGESTMD5Properties result;
+	return result;
+}
+
+ByteArray DIGESTMD5Properties::serialize() const {
+	ByteArray result;
+	for(DIGESTMD5PropertiesMap::const_iterator i = properties.begin(); i != properties.end(); ++i) {
+		if (i != properties.begin()) {
+			result += ',';
+		}
+		result += i->first;
+		result += '=';
+		if (isQuoted(i->first)) {
+			result += "\"" + i->second + "\"";
+		}
+		else {
+			result += i->second;
+		}
+	}
+	return result;
+}
+
+void DIGESTMD5Properties::setValue(const String& key, const String& value) {
+	properties.insert(DIGESTMD5PropertiesMap::value_type(key, ByteArray(value)));
+}
+
+bool DIGESTMD5Properties::isQuoted(const String& p) {
+	return p == "authzid" || p == "cnonce" || p == "digest-uri" || p == "nonce" || p == "realm" || p == "username";
+}
+
+}
diff --git a/Swiften/SASL/DIGESTMD5Properties.h b/Swiften/SASL/DIGESTMD5Properties.h
new file mode 100644
index 0000000..a92f99b
--- /dev/null
+++ b/Swiften/SASL/DIGESTMD5Properties.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <map>
+
+#include "Swiften/Base/String.h"
+#include "Swiften/Base/ByteArray.h"
+
+namespace Swift {
+	class DIGESTMD5Properties {
+		public:
+			DIGESTMD5Properties();
+			
+			void setValue(const String& key, const String& value);
+
+			ByteArray serialize() const;
+
+			static DIGESTMD5Properties parse(const ByteArray&);
+
+		private:
+			static bool isQuoted(const String& property);
+
+		private:
+			typedef std::multimap<String, ByteArray> DIGESTMD5PropertiesMap;
+			DIGESTMD5PropertiesMap properties;
+	};
+}
diff --git a/Swiften/SASL/SConscript b/Swiften/SASL/SConscript
index 22b242e..778a414 100644
--- a/Swiften/SASL/SConscript
+++ b/Swiften/SASL/SConscript
@@ -1,4 +1,4 @@
-Import("swiften_env")
+Import("swiften_env", "env")
 
 myenv = swiften_env.Clone()
 myenv.MergeFlags(swiften_env["LIBIDN_FLAGS"])
@@ -8,5 +8,12 @@ objects = myenv.StaticObject([
 		"PLAINClientAuthenticator.cpp",
 		"PLAINMessage.cpp",
 		"SCRAMSHA1ClientAuthenticator.cpp",
+		"DIGESTMD5Properties.cpp",
 	])
 swiften_env.Append(SWIFTEN_OBJECTS = [objects])
+env.Append(UNITTEST_SOURCES = [
+			File("UnitTest/PLAINMessageTest.cpp"),
+			File("UnitTest/PLAINClientAuthenticatorTest.cpp"),
+			File("UnitTest/SCRAMSHA1ClientAuthenticatorTest.cpp"),
+			File("UnitTest/DIGESTMD5PropertiesTest.cpp"),
+	])
diff --git a/Swiften/SASL/UnitTest/DIGESTMD5PropertiesTest.cpp b/Swiften/SASL/UnitTest/DIGESTMD5PropertiesTest.cpp
new file mode 100644
index 0000000..0c1543a
--- /dev/null
+++ b/Swiften/SASL/UnitTest/DIGESTMD5PropertiesTest.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+
+#include "Swiften/SASL/DIGESTMD5Properties.h"
+
+using namespace Swift;
+
+class DIGESTMD5PropertiesTest : public CppUnit::TestFixture {
+		CPPUNIT_TEST_SUITE(DIGESTMD5PropertiesTest);
+		CPPUNIT_TEST(testParse);
+		CPPUNIT_TEST(testSerialize);
+		CPPUNIT_TEST_SUITE_END();
+
+	public:
+		void testParse() {
+			DIGESTMD5Properties properties = DIGESTMD5Properties::parse(ByteArray(
+					"realm=\"myrealm1\",realm=\"myrealm2\",nonce=\"mynonce\","
+					"algorithm=\"md5-sess\""));
+		}
+
+		void testSerialize() {
+			DIGESTMD5Properties properties;
+			properties.setValue("authzid", "myauthzid");
+			properties.setValue("charset", "utf-8");
+			properties.setValue("cnonce", "mycnonce");
+			properties.setValue("digest-uri", "mydigesturi");
+			properties.setValue("nc", "1");
+			properties.setValue("nonce", "mynonce");
+			properties.setValue("qop", "auth");
+			properties.setValue("realm", "myrealm");
+			properties.setValue("response", "myresponse");
+			properties.setValue("username", "myuser");
+
+			ByteArray result = properties.serialize();
+			ByteArray expected("authzid=\"myauthzid\",charset=utf-8,cnonce=\"mycnonce\",digest-uri=\"mydigesturi\",nc=1,nonce=\"mynonce\",qop=auth,realm=\"myrealm\",response=myresponse,username=\"myuser\"");
+			CPPUNIT_ASSERT_EQUAL(expected.toString(), result.toString());
+		}
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(DIGESTMD5PropertiesTest);
diff --git a/Swiften/SConscript b/Swiften/SConscript
index a95635a..257f056 100644
--- a/Swiften/SConscript
+++ b/Swiften/SConscript
@@ -193,9 +193,6 @@ if env["SCONS_STAGE"] == "build" :
 			File("Roster/UnitTest/OfflineRosterFilterTest.cpp"),
 			File("Roster/UnitTest/RosterTest.cpp"),
 			File("Roster/UnitTest/XMPPRosterTest.cpp"),
-			File("SASL/UnitTest/PLAINMessageTest.cpp"),
-			File("SASL/UnitTest/PLAINClientAuthenticatorTest.cpp"),
-			File("SASL/UnitTest/SCRAMSHA1ClientAuthenticatorTest.cpp"),
 			File("Serializer/PayloadSerializers/UnitTest/PayloadsSerializer.cpp"),
 			File("Serializer/PayloadSerializers/UnitTest/CapsInfoSerializerTest.cpp"),
 			File("Serializer/PayloadSerializers/UnitTest/DiscoInfoSerializerTest.cpp"),
-- 
cgit v0.10.2-6-g49f6