From 52bd37a759acc7edbd616c745ff64ac70ae41b9c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Sat, 8 May 2010 17:11:22 +0200
Subject: Added DIGESTMD5Properties parsing.


diff --git a/Swiften/SASL/DIGESTMD5Properties.cpp b/Swiften/SASL/DIGESTMD5Properties.cpp
index 23dc097..0853f90 100644
--- a/Swiften/SASL/DIGESTMD5Properties.cpp
+++ b/Swiften/SASL/DIGESTMD5Properties.cpp
@@ -8,11 +8,83 @@
 
 namespace Swift {
 
+namespace {
+	bool insideQuotes(const ByteArray& v) {
+		if (v.getSize() == 0) {
+			return false;
+		}
+		else if (v.getSize() == 1) {
+			return v[0] == '"';
+		}
+		else if (v[0] == '"') {
+			return !v[v.getSize() - 1] == '"';
+		}
+		else {
+			return false;
+		}
+	}
+
+	ByteArray stripQuotes(const ByteArray& v) {
+		const char* data = v.getData();
+		size_t size = v.getSize();
+		if (v[0] == '"') {
+			data++;
+			size--;
+		}
+		if (v[v.getSize() - 1] == '"') {
+			size--;
+		}
+		return ByteArray(data, size);
+	}
+}
+
 DIGESTMD5Properties::DIGESTMD5Properties() {
 }
 
-DIGESTMD5Properties DIGESTMD5Properties::parse(const ByteArray&) {
+DIGESTMD5Properties DIGESTMD5Properties::parse(const ByteArray& data) {
 	DIGESTMD5Properties result;
+	bool inKey = true;
+	ByteArray currentKey;
+	ByteArray currentValue;
+	for (size_t i = 0; i < data.getSize(); ++i) {
+		char c = data[i];
+		if (inKey) {
+			if (c == '=') {
+				inKey = false;
+			}
+			else {
+				currentKey += c;
+			}
+		}
+		else {
+			if (c == ',' && !insideQuotes(currentValue)) {
+				String key = currentKey.toString();
+				if (isQuoted(key)) {
+					result.setValue(key, stripQuotes(currentValue).toString());
+				}
+				else {
+					result.setValue(key, currentValue.toString());
+				}
+				inKey = true;
+				currentKey = ByteArray();
+				currentValue = ByteArray();
+			}
+			else {
+				currentValue += c;
+			}
+		}
+	}
+
+	if (!currentKey.isEmpty()) {
+		String key = currentKey.toString();
+		if (isQuoted(key)) {
+			result.setValue(key, stripQuotes(currentValue).toString());
+		}
+		else {
+			result.setValue(key, currentValue.toString());
+		}
+	}
+
 	return result;
 }
 
@@ -34,6 +106,16 @@ ByteArray DIGESTMD5Properties::serialize() const {
 	return result;
 }
 
+boost::optional<String> DIGESTMD5Properties::getValue(const String& key) {
+	DIGESTMD5PropertiesMap::const_iterator i = properties.find(key);
+	if (i != properties.end()) {
+		return i->second.toString();
+	}
+	else {
+		return boost::optional<String>();
+	}
+}
+
 void DIGESTMD5Properties::setValue(const String& key, const String& value) {
 	properties.insert(DIGESTMD5PropertiesMap::value_type(key, ByteArray(value)));
 }
diff --git a/Swiften/SASL/DIGESTMD5Properties.h b/Swiften/SASL/DIGESTMD5Properties.h
index a92f99b..4d3a4fe 100644
--- a/Swiften/SASL/DIGESTMD5Properties.h
+++ b/Swiften/SASL/DIGESTMD5Properties.h
@@ -7,6 +7,7 @@
 #pragma once
 
 #include <map>
+#include <boost/optional.hpp>
 
 #include "Swiften/Base/String.h"
 #include "Swiften/Base/ByteArray.h"
@@ -16,6 +17,8 @@ namespace Swift {
 		public:
 			DIGESTMD5Properties();
 			
+			boost::optional<String> getValue(const String& key);
+
 			void setValue(const String& key, const String& value);
 
 			ByteArray serialize() const;
diff --git a/Swiften/SASL/UnitTest/DIGESTMD5PropertiesTest.cpp b/Swiften/SASL/UnitTest/DIGESTMD5PropertiesTest.cpp
index 0c1543a..1b2c121 100644
--- a/Swiften/SASL/UnitTest/DIGESTMD5PropertiesTest.cpp
+++ b/Swiften/SASL/UnitTest/DIGESTMD5PropertiesTest.cpp
@@ -21,7 +21,16 @@ class DIGESTMD5PropertiesTest : public CppUnit::TestFixture {
 		void testParse() {
 			DIGESTMD5Properties properties = DIGESTMD5Properties::parse(ByteArray(
 					"realm=\"myrealm1\",realm=\"myrealm2\",nonce=\"mynonce\","
-					"algorithm=\"md5-sess\""));
+					"algorithm=md5-sess,charset=utf-8"));
+
+			CPPUNIT_ASSERT(properties.getValue("realm"));
+			CPPUNIT_ASSERT_EQUAL(String("myrealm1"), *properties.getValue("realm"));
+			CPPUNIT_ASSERT(properties.getValue("nonce"));
+			CPPUNIT_ASSERT_EQUAL(String("mynonce"), *properties.getValue("nonce"));
+			CPPUNIT_ASSERT(properties.getValue("algorithm"));
+			CPPUNIT_ASSERT_EQUAL(String("md5-sess"), *properties.getValue("algorithm"));
+			CPPUNIT_ASSERT(properties.getValue("charset"));
+			CPPUNIT_ASSERT_EQUAL(String("utf-8"), *properties.getValue("charset"));
 		}
 
 		void testSerialize() {
-- 
cgit v0.10.2-6-g49f6