1 //                                                       -*- C++ -*-
2 // This file is part of the aMule Project.
3 //
4 // Copyright (c) 2003-2011 aMule Team ( admin@amule.org / http://www.amule.org )
5 // Copyright (c) 2007-2011 Dévai Tamás ( gonosztopi@amule.org )
6 //
7 // Any parts of this program derived from the xMule, lMule or eMule project,
8 // or contributed by third-party developers are copyrighted by their
9 // respective authors.
10 //
11 // This program is free software; you can redistribute it and/or modify
12 // it under the terms of the GNU General Public License as published by
13 // the Free Software Foundation; either version 2 of the License, or
14 // (at your option) any later version.
15 //
16 // This program is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 // GNU General Public License for more details.
20 //
21 // You should have received a copy of the GNU General Public License
22 // along with this program; if not, write to the Free Software
23 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA
24 //
25 
26 #include "MagnetURI.h"
27 
28 
29 #ifdef USE_STD_STRING
30 #	ifdef _T
31 #		undef	_T
32 #	endif
33 #	ifdef _C
34 #		undef _C
35 #	endif
36 #	define	_T(str)	str
37 #	define	_C(ch)	ch
38 #else
39 	// wx/chartype.h defines _T
40 #	define	_C(ch)	wxChar(ch)
41 #endif
42 
43 
CMagnetURI(const STRING & uri)44 CMagnetURI::CMagnetURI(const STRING& uri)
45 {
46 	if (uri.compare(0, 7, _T("magnet:")) == 0) {
47 		size_t start = uri.find(_C('?'));
48 		if (start == STRING::npos) start = uri.length();
49 		while (start < uri.length() - 1) {
50 			size_t end = uri.find(_C('&'), start + 1);
51 			if (end == STRING::npos) end = uri.length();
52 			size_t pos = uri.find(_C('='), start + 1);
53 			if (pos == STRING::npos) pos = uri.length();
54 			if (pos < end) {
55 				m_fields.push_back(Field_Type(uri.substr(start + 1, pos - start - 1), uri.substr(pos + 1, end - pos - 1)));
56 			}
57 			start = end;
58 		}
59 	}
60 }
61 
GetLink() const62 STRING CMagnetURI::GetLink() const
63 {
64 	STRING retval(_T("magnet:"));
65 
66 	for (List_Type::const_iterator it = m_fields.begin(); it != m_fields.end(); ++it) {
67 		if (it == m_fields.begin()) {
68 			retval.append(1, _C('?'));
69 		} else {
70 			retval.append(1, _C('&'));
71 		}
72 		retval.append(it->first);
73 		retval.append(1, _C('='));
74 		retval.append(it->second);
75 	}
76 	return retval;
77 }
78 
GetField(const STRING & name) const79 CMagnetURI::Value_List CMagnetURI::GetField(const STRING& name) const
80 {
81 	Value_List retval;
82 
83 	for (List_Type::const_iterator it = m_fields.begin(); it != m_fields.end(); ++it) {
84 		if (it->first.compare(name) == 0) {
85 			retval.push_back(it->second);
86 		}
87 	}
88 	return retval;
89 }
90 
91 
CanConvertToED2K() const92 bool CMagnetED2KConverter::CanConvertToED2K() const
93 {
94 	bool has_urn = false;
95 	bool has_xl = false;
96 
97 	for (List_Type::const_iterator it = m_fields.begin(); it != m_fields.end(); ++it) {
98 		if (it->first.compare(_T("xl")) == 0) {
99 			has_xl = true;
100 			continue;
101 		}
102 		if (it->first.compare(_T("xt")) == 0) {
103 			if ((it->second.compare(0, 9, _T("urn:ed2k:")) == 0) ||
104 			    (it->second.compare(0, 13, _T("urn:ed2khash:")) == 0))
105 			{
106 				has_urn = true;
107 				continue;
108 			}
109 		}
110 		if (has_urn && has_xl) break;
111 	}
112 	return has_urn && has_xl;
113 }
114 
GetED2KLink() const115 STRING CMagnetED2KConverter::GetED2KLink() const
116 {
117 	if (CanConvertToED2K()) {
118 		STRING dn;
119 		STRING hash;
120 		STRING len(GetField(_T("xl")).front());
121 
122 		Value_List dn_val = GetField(_T("dn"));
123 		if (!dn_val.empty()) {
124 			dn = dn_val.front();
125 		} else {
126 			// This should never happen. Has anyone seen a link without a file name?
127 			// Just in case, assign a reasonable(?) name to that unnamed file.
128 			dn = _T("FileName.ext");
129 		}
130 		Value_List urn_list = GetField(_T("xt"));
131 		// Use the first ed2k-hash found.
132 		for (Value_List::iterator it = urn_list.begin(); it != urn_list.end(); ++it) {
133 			if (it->compare(0, 9, _T("urn:ed2k:")) == 0) {
134 				hash = it->substr(9);
135 				break;
136 			} else if (it->compare(0, 13, _T("urn:ed2khash:")) == 0) {
137 				hash = it->substr(13);
138 				break;
139 			}
140 		}
141 		return STRING(_T("ed2k://|file|")).append(dn).append(1, _C('|')).append(len).append(1, _C('|')).append(hash).append(_T("|/"));
142 	} else {
143 		return STRING();
144 	}
145 }
146