← Back to team overview

linuxdcpp-team team mailing list archive

[Branch ~dcplusplus-team/dcplusplus/trunk] Rev 2883: friendly magnet links

 

------------------------------------------------------------
revno: 2883
committer: poy <poy@xxxxxxxxxx>
branch nick: trunk
timestamp: Sun 2012-03-18 18:52:34 +0100
message:
  friendly magnet links
added:
  dcpp/Magnet.cpp
  dcpp/Magnet.h
modified:
  dcpp/ChatMessage.cpp
  win32/WinUtil.cpp
  win32/WinUtil.h


--
lp:dcplusplus
https://code.launchpad.net/~dcplusplus-team/dcplusplus/trunk

Your team Dcplusplus-team is subscribed to branch lp:dcplusplus.
To unsubscribe from this branch go to https://code.launchpad.net/~dcplusplus-team/dcplusplus/trunk/+edit-subscription
=== modified file 'dcpp/ChatMessage.cpp'
--- dcpp/ChatMessage.cpp	2012-03-18 15:43:00 +0000
+++ dcpp/ChatMessage.cpp	2012-03-18 17:52:34 +0000
@@ -21,6 +21,7 @@
 
 #include "Client.h"
 #include "format.h"
+#include "Magnet.h"
 #include "OnlineUser.h"
 #include "SettingsManager.h"
 #include "SimpleXML.h"
@@ -106,13 +107,15 @@
 	/* link formatting - optimize the lookup a bit by using the fact that every link identifier
 	(except www ones) contains a colon. */
 	/// @todo add support for spaces within links enclosed by brackets / quotes (see URI RFC)
-	/// @todo friendly magnet links
-	auto addLink = [&tmp, &xmlTmp, &tags](size_t begin, size_t end) {
-		Tag openingTag = { "<a href=\"" + SimpleXML::escape(tmp.substr(begin, end - begin), xmlTmp, true) + "\">", true, end },
+	auto addLinkStr = [&xmlTmp, &tags](size_t begin, size_t end, const string& link) {
+		Tag openingTag = { "<a href=\"" + SimpleXML::escape(link, xmlTmp, true) + "\">", true, end },
 			closingTag = { "</a>", false, begin };
 		tags[begin] = std::move(openingTag);
 		tags[end] = std::move(closingTag);
 	};
+	auto addLink = [&tmp, &addLinkStr](size_t begin, size_t end) {
+		addLinkStr(begin, end, tmp.substr(begin, end - begin));
+	};
 
 	static const string delimiters = " \t\r\n<>\"";
 
@@ -126,12 +129,28 @@
 
 		if(i > 0 && (
 			(i + 4 < n && tmp[i + 1] == '/' && tmp[i + 2] == '/') || // "http://";, etc
-			(i == begin + 6 && !tmp.compare(begin, 6, "magnet")) ||
-			(i == begin + 6 && !tmp.compare(begin, 6, "mailto"))))
+			(i == begin + 6 && i + 1 <= n && !tmp.compare(begin, 6, "mailto"))))
 		{
 			addLink(begin, end);
 			i = end;
 
+		} else if(i == begin + 6 && i + 2 <= n && !tmp.compare(begin, 6, "magnet") && tmp[i + 1] == '?') {
+			string link = tmp.substr(begin, end - begin), hash, name, key;
+			if(Magnet::parseUri(link, hash, name, key)) {
+
+				if(!name.empty()) {
+					// magnet link: replace with the friendly name
+					tmp.replace(begin, end - begin, name);
+					end += name.size() - link.size();
+				}
+
+				addLinkStr(begin, end, link);
+				i = end;
+
+			} else {
+				++i;
+			}
+
 		} else {
 			++i;
 		}

=== added file 'dcpp/Magnet.cpp'
--- dcpp/Magnet.cpp	1970-01-01 00:00:00 +0000
+++ dcpp/Magnet.cpp	2012-03-18 17:52:34 +0000
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2001-2012 Jacek Sieka, arnetheduck on gmail point com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "stdinc.h"
+#include "Magnet.h"
+
+#include "StringTokenizer.h"
+#include "Text.h"
+#include "Util.h"
+
+namespace dcpp {
+
+using std::map;
+
+bool Magnet::parseUri(const string& uri, string& hash, string& name, string& key) {
+	if(Util::strnicmp(uri.c_str(), "magnet:?", 8)) {
+		return false;
+	}
+
+	// official types that are of interest to us
+	//  xt = exact topic
+	//  xs = exact substitute
+	//  as = acceptable substitute
+	//  dn = display name
+
+	StringTokenizer<string> mag(uri.substr(8), '&');
+	map<string, string> hashes;
+	string type, param;
+	for(auto& idx: mag.getTokens()) {
+
+		// break into pairs
+		auto pos = idx.find('=');
+		if(pos != string::npos) {
+			type = Text::toLower(Util::encodeURI(idx.substr(0, pos), true));
+			param = Util::encodeURI(idx.substr(pos + 1), true);
+		} else {
+			type = Util::encodeURI(idx, true);
+			param.clear();
+		}
+
+		// extract what is of value
+		if(param.size() == 85 && Util::strnicmp(param.c_str(), "urn:bitprint:", 13) == 0) {
+			hashes[type] = param.substr(46);
+		} else if(param.size() == 54 && Util::strnicmp(param.c_str(), "urn:tree:tiger:", 15) == 0) {
+			hashes[type] = param.substr(15);
+		} else if(param.size() == 55 && Util::strnicmp(param.c_str(), "urn:tree:tiger/:", 16) == 0) {
+			hashes[type] = param.substr(16);
+		} else if(param.size() == 59 && Util::strnicmp(param.c_str(), "urn:tree:tiger/1024:", 20) == 0) {
+			hashes[type] = param.substr(20);
+		} else if(type.size() == 2 && Util::strnicmp(type.c_str(), "dn", 2) == 0) {
+			name = param;
+		} else if(type.size() == 2 && Util::strnicmp(type.c_str(), "kt", 2) == 0) {
+			key = param;
+		}
+	}
+
+	// pick the most authoritative hash out of all of them.
+	if(hashes.find("xt") != hashes.end()) {
+		hash = hashes["xt"];
+	} else if(hashes.find("xs") != hashes.end()) {
+		hash = hashes["xs"];
+	} else if(hashes.find("as") != hashes.end()) {
+		hash = hashes["as"];
+	}
+
+	if(!hash.empty() || !key.empty()) {
+		return true;
+	}
+	return false;
+}
+
+} // namespace dcpp

=== added file 'dcpp/Magnet.h'
--- dcpp/Magnet.h	1970-01-01 00:00:00 +0000
+++ dcpp/Magnet.h	2012-03-18 17:52:34 +0000
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2001-2012 Jacek Sieka, arnetheduck on gmail point com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef DCPLUSPLUS_DCPP_MAGNET_H
+#define DCPLUSPLUS_DCPP_MAGNET_H
+
+#include "forward.h"
+
+#include <string>
+
+namespace dcpp {
+
+using std::string;
+
+struct Magnet {
+	static bool parseUri(const string& uri, string& hash, string& name, string& key);
+};
+
+} // namespace dcpp
+
+#endif

=== modified file 'win32/WinUtil.cpp'
--- win32/WinUtil.cpp	2012-03-11 18:06:18 +0000
+++ win32/WinUtil.cpp	2012-03-18 17:52:34 +0000
@@ -30,6 +30,7 @@
 #include <dcpp/File.h>
 #include <dcpp/HashManager.h>
 #include <dcpp/LogManager.h>
+#include <dcpp/Magnet.h>
 #include <dcpp/QueueManager.h>
 #include <dcpp/SettingsManager.h>
 #include <dcpp/ShareManager.h>
@@ -1421,81 +1422,20 @@
 		Util::strnicmp(str.c_str(), _T("mailto:";), 7) == 0) {
 		openLink(str);
 		return true;
+
 	} else if(host == "magnet") {
-		parseMagnetUri(str);
-		return true;
-	}
-
-	return false;
-}
-
-void WinUtil::parseMagnetUri(const tstring& aUrl, bool /*aOverride*/) {
-	// official types that are of interest to us
-	//  xt = exact topic
-	//  xs = exact substitute
-	//  as = acceptable substitute
-	//  dn = display name
-	if(Util::strnicmp(aUrl.c_str(), _T("magnet:?"), 8) == 0) {
-		LogManager::getInstance()->message(str(F_("MAGNET Link detected: %1%") % Text::fromT(aUrl)));
-		StringTokenizer<tstring> mag(aUrl.substr(8), _T('&'));
-		typedef map<tstring, tstring> MagMap;
-		MagMap hashes;
-		tstring fname, fhash, type, param, fkey;
-		for(auto& idx: mag.getTokens()) {
-			// break into pairs
-			string::size_type pos = idx.find(_T('='));
-			if(pos != string::npos) {
-				type = Text::toT(Text::toLower(Util::encodeURI(Text::fromT(idx.substr(0, pos)), true)));
-				param = Text::toT(Util::encodeURI(Text::fromT(idx.substr(pos + 1)), true));
-			} else {
-				type = Text::toT(Util::encodeURI(Text::fromT(idx), true));
-				param.clear();
-			}
-			// extract what is of value
-			if(param.length() == 85 && Util::strnicmp(param.c_str(), _T("urn:bitprint:"), 13) == 0) {
-				hashes[type] = param.substr(46);
-			} else if(param.length() == 54 && Util::strnicmp(param.c_str(), _T("urn:tree:tiger:"), 15) == 0) {
-				hashes[type] = param.substr(15);
-			} else if(param.length() == 55 && Util::strnicmp(param.c_str(), _T("urn:tree:tiger/:"), 16) == 0) {
-				hashes[type] = param.substr(16);
-			} else if(param.length() == 59 && Util::strnicmp(param.c_str(), _T("urn:tree:tiger/1024:"), 20) == 0) {
-				hashes[type] = param.substr(20);
-			} else if(type.length() == 2 && Util::strnicmp(type.c_str(), _T("dn"), 2) == 0) {
-				fname = param;
-			} else if(type.length() == 2 && Util::strnicmp(type.c_str(), _T("kt"), 2) == 0) {
-				fkey = param;
-			}
-		}
-		// pick the most authoritative hash out of all of them.
-		if(hashes.find(_T("as")) != hashes.end()) {
-			fhash = hashes[_T("as")];
-		}
-		if(hashes.find(_T("xs")) != hashes.end()) {
-			fhash = hashes[_T("xs")];
-		}
-		if(hashes.find(_T("xt")) != hashes.end()) {
-			fhash = hashes[_T("xt")];
-		}
-		if(!fhash.empty() || !fkey.empty()) {
-			// ok, we have a hash, and maybe a filename.
-			//if(!BOOLSETTING(MAGNET_ASK)) {
-			//	switch(SETTING(MAGNET_ACTION)) {
-			//		case SettingsManager::MAGNET_AUTO_DOWNLOAD:
-			//			break;
-			//		case SettingsManager::MAGNET_AUTO_SEARCH:
-			//			SearchFrame::openWindow(mainWindow->getTabView(), fhash, SearchManager::TYPE_TTH);
-			//			break;
-			//	};
-			//} else {
-			// use aOverride to force the display of the dialog.  used for auto-updating
-			MagnetDlg(mainWindow, fhash, fname, fkey).run();
-			//}
+		string hash, name, key;
+		if(Magnet::parseUri(Text::fromT(str), hash, name, key)) {
+			MagnetDlg(mainWindow, Text::toT(hash), Text::toT(name), Text::toT(key)).run();
 		} else {
 			dwt::MessageBox(mainWindow).show(
 				T_("A MAGNET link was given to DC++, but it didn't contain a valid file hash for use on the Direct Connect network.  No action will be taken."),
 				T_("MAGNET Link detected"), dwt::MessageBox::BOX_OK, dwt::MessageBox::BOX_ICONEXCLAMATION);
 		}
+		return true;
 	}
+
+	return false;
 }
 
 namespace {

=== modified file 'win32/WinUtil.h'
--- win32/WinUtil.h	2012-03-11 16:34:55 +0000
+++ win32/WinUtil.h	2012-03-18 17:52:34 +0000
@@ -293,7 +293,6 @@
 	static bool getUCParams(dwt::Widget* parent, const UserCommand& cmd, ParamMap& params) noexcept;
 
 	static bool parseLink(const tstring& aString);
-	static void parseMagnetUri(const tstring& /*aUrl*/, bool aOverride = false);
 
 	static void help(dwt::Control* widget);
 	static void helpId(dwt::Control* widget, unsigned id);