updated on Thu Jan 26 16:09:46 UTC 2012
[aur-mirror.git] / rtorrent-extended / ex_magnet_uri.patch
blob19fb5f2881b7ef1abd0e14955be32d31c1a9ae7e
1 diff --git a/src/core/download_factory.cc b/src/core/download_factory.cc
2 index e2d8ee8..49ac3fa 100644
3 --- a/src/core/download_factory.cc
4 +++ b/src/core/download_factory.cc
5 @@ -69,6 +69,12 @@ is_network_uri(const std::string& uri) {
6 std::strncmp(uri.c_str(), "ftp://", 6) == 0;
9 +bool
10 +is_magnet_uri(const std::string& uri) {
11 + return
12 + std::strncmp(uri.c_str(), "magnet:?", 8) == 0;
15 DownloadFactory::DownloadFactory(Manager* m) :
16 m_manager(m),
17 m_stream(NULL),
18 @@ -133,6 +139,13 @@ DownloadFactory::receive_load() {
20 m_variables["tied_to_file"] = (int64_t)false;
22 + } else if (is_magnet_uri(m_uri)) {
23 + m_stream = new std::stringstream();
24 + *m_stream << "d10:magnet-uri" << m_uri.length() << ":" << m_uri << "e";
26 + m_variables["tied_to_file"] = (int64_t)false;
27 + receive_loaded();
29 } else {
30 std::fstream* stream = new std::fstream(rak::path_expand(m_uri).c_str(), std::ios::in | std::ios::binary);
31 m_stream = stream;
32 @@ -177,6 +190,16 @@ DownloadFactory::receive_success() {
34 torrent::Object* root = download->bencode();
36 + if (download->download()->is_meta_download()) {
37 + torrent::Object& meta = root->insert_key("rtorrent_meta_download", torrent::Object::create_map());
38 + meta.insert_key("start", m_start);
39 + meta.insert_key("print_log", m_printLog);
41 + torrent::Object::list_type& commands = meta.insert_key("commands", torrent::Object::create_list()).as_list();
42 + for (command_list_type::iterator itr = m_commands.begin(); itr != m_commands.end(); ++itr)
43 + commands.push_back(*itr);
44 + }
46 if (!m_session) {
47 // We only allow session torrents to keep their
48 // 'rtorrent/libtorrent' sections. The "fast_resume" section
49 @@ -229,7 +252,7 @@ DownloadFactory::receive_success() {
50 rpc::call_command("d.set_directory_base", rtorrent->get_key("directory"), rpc::make_target(download));
52 if (!m_session && m_variables["tied_to_file"].as_value())
53 - rpc::call_command("d.set_tied_to_file", m_uri, rpc::make_target(download));
54 + rpc::call_command("d.set_tied_to_file", m_uri.empty() ? m_variables["tied_file"] : m_uri, rpc::make_target(download));
56 rpc::call_command("d.set_peer_exchange", rpc::call_command_value("get_peer_exchange"), rpc::make_target(download));
58 diff --git a/src/core/download_factory.h b/src/core/download_factory.h
59 index 045c9dc..3cc9622 100644
60 --- a/src/core/download_factory.h
61 +++ b/src/core/download_factory.h
62 @@ -112,6 +112,7 @@ private:
65 bool is_network_uri(const std::string& uri);
66 +bool is_magnet_uri(const std::string& uri);
70 diff --git a/src/core/download_list.cc b/src/core/download_list.cc
71 index 551f873..13df725 100644
72 --- a/src/core/download_list.cc
73 +++ b/src/core/download_list.cc
74 @@ -37,10 +37,12 @@
75 #include "config.h"
77 #include <algorithm>
78 +#include <fstream>
79 #include <iostream>
80 #include <sigc++/adaptors/bind.h>
81 #include <rak/functional.h>
82 #include <rak/string_manip.h>
83 +#include <torrent/data/file.h>
84 #include <torrent/exceptions.h>
85 #include <torrent/download.h>
86 #include <torrent/hash_string.h>
87 @@ -452,6 +454,9 @@ DownloadList::hash_done(Download* download) {
88 int64_t hashing = rpc::call_command_value("d.get_hashing", rpc::make_target(download));
89 rpc::call_command_set_value("d.set_hashing", Download::variable_hashing_stopped, rpc::make_target(download));
91 + if (download->is_done() && download->download()->is_meta_download())
92 + return process_meta_download(download);
94 switch (hashing) {
95 case Download::variable_hashing_initial:
96 case Download::variable_hashing_rehash:
97 @@ -543,6 +548,9 @@ void
98 DownloadList::confirm_finished(Download* download) {
99 check_contains(download);
101 + if (download->download()->is_meta_download())
102 + return process_meta_download(download);
104 rpc::call_command("d.set_complete", (int64_t)1, rpc::make_target(download));
106 rpc::call_command("d.set_connection_current", rpc::call_command_void("d.get_connection_seed", rpc::make_target(download)), rpc::make_target(download));
107 @@ -576,4 +584,36 @@ DownloadList::confirm_finished(Download* download) {
108 resume(download, torrent::Download::start_no_create | torrent::Download::start_skip_tracker | torrent::Download::start_keep_baseline);
111 +void
112 +DownloadList::process_meta_download(Download* download) {
113 + rpc::call_command("d.stop", torrent::Object(), rpc::make_target(download));
114 + rpc::call_command("d.close", torrent::Object(), rpc::make_target(download));
116 + std::string metafile = (*download->file_list()->begin())->frozen_path();
117 + std::fstream file(metafile.c_str(), std::ios::in | std::ios::binary);
118 + if (!file.is_open()) {
119 + control->core()->push_log("Could not read download metadata.");
120 + return;
123 + torrent::Object* bencode = new torrent::Object(torrent::Object::create_map());
124 + file >> bencode->insert_key("info", torrent::Object());
125 + if (file.fail()) {
126 + delete bencode;
127 + control->core()->push_log("Could not create download, the input is not a valid torrent.");
128 + return;
130 + file.close();
132 + // Steal the keys we still need. The old download has no use for them.
133 + bencode->insert_key("rtorrent_meta_download", torrent::Object()).swap(download->bencode()->get_key("rtorrent_meta_download"));
134 + if (download->bencode()->has_key("announce"))
135 + bencode->insert_key("announce", torrent::Object()).swap(download->bencode()->get_key("announce"));
136 + if (download->bencode()->has_key("announce-list"))
137 + bencode->insert_key("announce-list", torrent::Object()).swap(download->bencode()->get_key("announce-list"));
139 + erase_ptr(download);
140 + control->core()->try_create_download_from_meta_download(bencode, metafile);
144 diff --git a/src/core/download_list.h b/src/core/download_list.h
145 index f7828ea..8ecffa0 100644
146 --- a/src/core/download_list.h
147 +++ b/src/core/download_list.h
148 @@ -161,6 +161,8 @@ private:
150 void received_finished(Download* d);
151 void confirm_finished(Download* d);
153 + void process_meta_download(Download* d);
157 diff --git a/src/core/manager.cc b/src/core/manager.cc
158 index 62738ca..2a422c8 100644
159 --- a/src/core/manager.cc
160 +++ b/src/core/manager.cc
161 @@ -39,6 +39,7 @@
162 #include <cstdio>
163 #include <cstring>
164 #include <fstream>
165 +#include <sstream>
166 #include <unistd.h>
167 #include <sys/select.h>
168 #include <rak/address_info.h>
169 @@ -52,6 +53,7 @@
170 #include <torrent/connection_manager.h>
171 #include <torrent/error.h>
172 #include <torrent/exceptions.h>
173 +#include <torrent/object_stream.h>
174 #include <torrent/resume.h>
175 #include <torrent/tracker_list.h>
176 #include <torrent/throttle.h>
177 @@ -395,6 +397,7 @@ Manager::try_create_download(const std::string& uri, int flags, const command_li
178 if ((flags & create_tied) &&
179 !(flags & create_raw_data) &&
180 !is_network_uri(uri) &&
181 + !is_magnet_uri(uri) &&
182 !file_status_cache()->insert(uri, 0))
183 return;
185 @@ -416,6 +419,31 @@ Manager::try_create_download(const std::string& uri, int flags, const command_li
186 f->commit();
189 +void
190 +Manager::try_create_download_from_meta_download(torrent::Object* bencode, const std::string& metafile) {
191 + DownloadFactory* f = new DownloadFactory(this);
193 + f->variables()["tied_to_file"] = (int64_t)true;
194 + f->variables()["tied_file"] = metafile;
196 + torrent::Object& meta = bencode->get_key("rtorrent_meta_download");
197 + torrent::Object::list_type& commands = meta.get_key_list("commands");
198 + for (torrent::Object::list_type::const_iterator itr = commands.begin(); itr != commands.end(); ++itr)
199 + f->commands().insert(f->commands().end(), itr->as_string());
201 + f->set_start(meta.get_key_value("start"));
202 + f->set_print_log(meta.get_key_value("print_log"));
203 + f->slot_finished(sigc::bind(sigc::ptr_fun(&rak::call_delete_func<core::DownloadFactory>), f));
205 + // Bit of a waste to create the bencode repesentation here
206 + // only to have the DownloadFactory decode it.
207 + std::stringstream s;
208 + s.imbue(std::locale::classic());
209 + s << *bencode;
210 + f->load_raw_data(s.str());
211 + f->commit();
214 utils::Directory
215 path_expand_transform(std::string path, const utils::directory_entry& entry) {
216 return path + entry.d_name;
217 diff --git a/src/core/manager.h b/src/core/manager.h
218 index 3b23da3..16902af 100644
219 --- a/src/core/manager.h
220 +++ b/src/core/manager.h
221 @@ -128,6 +128,7 @@ public:
222 // Temporary, find a better place for this.
223 void try_create_download(const std::string& uri, int flags, const command_list_type& commands);
224 void try_create_download_expand(const std::string& uri, int flags, command_list_type commands = command_list_type());
225 + void try_create_download_from_meta_download(torrent::Object* bencode, const std::string& metafile);
227 private:
228 typedef RangeMap<uint32_t, torrent::ThrottlePair> AddressThrottleMap;
229 diff --git a/src/core/view.cc b/src/core/view.cc
230 index 8e2d997..f3b4f0d 100644
231 --- a/src/core/view.cc
232 +++ b/src/core/view.cc
233 @@ -90,6 +90,7 @@ struct view_downloads_filter : std::unary_function<Download*, bool> {
234 case torrent::Object::TYPE_STRING: return !result.as_string().empty();
235 case torrent::Object::TYPE_LIST: return !result.as_list().empty();
236 case torrent::Object::TYPE_MAP: return !result.as_map().empty();
237 + case torrent::Object::TYPE_SSTRING:return !result.as_sstring().empty();
240 // The default filter action is to return true, to not filter