From 5f6543647862b5ae1d5abdddd0612e6cf9f23c8f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Wed, 27 Oct 2010 21:12:46 +0200
Subject: Changed linkifcation algorithm.


diff --git a/SwifTools/Linkify.cpp b/SwifTools/Linkify.cpp
index 0ebe832..0dfa7b5 100644
--- a/SwifTools/Linkify.cpp
+++ b/SwifTools/Linkify.cpp
@@ -7,17 +7,46 @@
 #include "SwifTools/Linkify.h"
 
 #include <boost/regex.hpp>
+#include <sstream>
+#include <iostream>
 
 namespace Swift {
 
-static const boost::regex linkifyRegexp("(https?://([@:\\-\\w\\.]+)+(:\\d+)?(/([=%~\\-\\w/_#@\\.\\+]*(\\?\\S+)?)?)?)");
+static boost::regex linkifyRegexp("^https?://.*");
 
 String Linkify::linkify(const String& input) {
-	return String(boost::regex_replace(
-			input.getUTF8String(), 
-			linkifyRegexp, 
-			"<a href=\"\\1\">\\1</a>", 
-			boost::match_default|boost::format_all));
+	std::ostringstream result;
+	std::vector<char> currentURL;
+	bool inURL = false;
+	for (size_t i = 0; i < input.getUTF8Size(); ++i) {
+		char c = input[i];
+		if (inURL) {
+			if (c >= 33 && c != '\\' && c != '"') {
+				currentURL.push_back(c);
+			}
+			else {
+				String url(&currentURL[0], currentURL.size());
+				result << "<a href=\"" << url << "\">" <<  url << "</a>";
+				currentURL.clear();
+				inURL = false;
+				result << c;
+			}
+		}
+		else {
+			if (boost::regex_match(input.getSubstring(i, 8).getUTF8String(), linkifyRegexp)) {
+				currentURL.push_back(c);
+				inURL = true;
+			}
+			else {
+				result << c;
+			}
+		}
+	}
+	if (currentURL.size() > 0) {
+		String url(&currentURL[0], currentURL.size());
+		result << "<a href=\"" << url << "\">" <<  url << "</a>";
+	}
+	return String(result.str());
 }
 
 }
diff --git a/SwifTools/UnitTest/LinkifyTest.cpp b/SwifTools/UnitTest/LinkifyTest.cpp
index 1418957..9655b87 100644
--- a/SwifTools/UnitTest/LinkifyTest.cpp
+++ b/SwifTools/UnitTest/LinkifyTest.cpp
@@ -14,6 +14,7 @@ using namespace Swift;
 class LinkifyTest : public CppUnit::TestFixture {
 		CPPUNIT_TEST_SUITE(LinkifyTest);
 		CPPUNIT_TEST(testLinkify_URLWithResource);
+		CPPUNIT_TEST(testLinkify_HTTPSURLWithResource);
 		CPPUNIT_TEST(testLinkify_URLWithEmptyResource);
 		CPPUNIT_TEST(testLinkify_BareURL);
 		CPPUNIT_TEST(testLinkify_URLSurroundedByWhitespace);
@@ -26,6 +27,7 @@ class LinkifyTest : public CppUnit::TestFixture {
 		CPPUNIT_TEST(testLinkify_Equal);
 		CPPUNIT_TEST(testLinkify_Authentication);
 		CPPUNIT_TEST(testLinkify_At);
+		CPPUNIT_TEST(testLinkify_Amps);
 		CPPUNIT_TEST_SUITE_END();
 
 	public:
@@ -37,6 +39,14 @@ class LinkifyTest : public CppUnit::TestFixture {
 					result);
 		}
 
+		void testLinkify_HTTPSURLWithResource() {
+			String result = Linkify::linkify("https://swift.im/blog");
+
+			CPPUNIT_ASSERT_EQUAL(
+					String("<a href=\"https://swift.im/blog\">https://swift.im/blog</a>"),
+					result);
+		}
+
 		void testLinkify_URLWithEmptyResource() {
 			String result = Linkify::linkify("http://swift.im/");
 
@@ -133,6 +143,14 @@ class LinkifyTest : public CppUnit::TestFixture {
 					String("<a href=\"http://swift.im/foo@bar\">http://swift.im/foo@bar</a>"),
 					result);
 		}
+
+		void testLinkify_Amps() {
+			String result = Linkify::linkify("http://swift.im/foo&bar&baz");
+
+			CPPUNIT_ASSERT_EQUAL(
+					String("<a href=\"http://swift.im/foo&bar&baz\">http://swift.im/foo&bar&baz</a>"),
+					result);
+		}
 };
 
 CPPUNIT_TEST_SUITE_REGISTRATION(LinkifyTest);
-- 
cgit v0.10.2-6-g49f6