From 8dc1d552c0bab7b72371c3a1529e365410c7548c Mon Sep 17 00:00:00 2001 From: Florian Pritz Date: Mon, 17 May 2010 12:03:46 +0200 Subject: add rtorrent-extended Signed-off-by: Florian Pritz --- rtorrent-extended/magnet_uri.patch | 228 +++++++++++++++++++++++++++++++++++++ 1 file changed, 228 insertions(+) create mode 100644 rtorrent-extended/magnet_uri.patch (limited to 'rtorrent-extended/magnet_uri.patch') diff --git a/rtorrent-extended/magnet_uri.patch b/rtorrent-extended/magnet_uri.patch new file mode 100644 index 0000000..32d45f0 --- /dev/null +++ b/rtorrent-extended/magnet_uri.patch @@ -0,0 +1,228 @@ +diff --git a/src/core/download_factory.cc b/src/core/download_factory.cc +index e2d8ee8..49ac3fa 100644 +--- a/src/core/download_factory.cc ++++ b/src/core/download_factory.cc +@@ -69,6 +69,12 @@ is_network_uri(const std::string& uri) { + std::strncmp(uri.c_str(), "ftp://", 6) == 0; + } + ++bool ++is_magnet_uri(const std::string& uri) { ++ return ++ std::strncmp(uri.c_str(), "magnet:?", 8) == 0; ++} ++ + DownloadFactory::DownloadFactory(Manager* m) : + m_manager(m), + m_stream(NULL), +@@ -133,6 +139,13 @@ DownloadFactory::receive_load() { + + m_variables["tied_to_file"] = (int64_t)false; + ++ } else if (is_magnet_uri(m_uri)) { ++ m_stream = new std::stringstream(); ++ *m_stream << "d10:magnet-uri" << m_uri.length() << ":" << m_uri << "e"; ++ ++ m_variables["tied_to_file"] = (int64_t)false; ++ receive_loaded(); ++ + } else { + std::fstream* stream = new std::fstream(rak::path_expand(m_uri).c_str(), std::ios::in | std::ios::binary); + m_stream = stream; +@@ -177,6 +190,16 @@ DownloadFactory::receive_success() { + + torrent::Object* root = download->bencode(); + ++ if (download->download()->is_meta_download()) { ++ torrent::Object& meta = root->insert_key("rtorrent_meta_download", torrent::Object::create_map()); ++ meta.insert_key("start", m_start); ++ meta.insert_key("print_log", m_printLog); ++ ++ torrent::Object::list_type& commands = meta.insert_key("commands", torrent::Object::create_list()).as_list(); ++ for (command_list_type::iterator itr = m_commands.begin(); itr != m_commands.end(); ++itr) ++ commands.push_back(*itr); ++ } ++ + if (!m_session) { + // We only allow session torrents to keep their + // 'rtorrent/libtorrent' sections. The "fast_resume" section +@@ -229,7 +252,7 @@ DownloadFactory::receive_success() { + rpc::call_command("d.set_directory_base", rtorrent->get_key("directory"), rpc::make_target(download)); + + if (!m_session && m_variables["tied_to_file"].as_value()) +- rpc::call_command("d.set_tied_to_file", m_uri, rpc::make_target(download)); ++ rpc::call_command("d.set_tied_to_file", m_uri.empty() ? m_variables["tied_file"] : m_uri, rpc::make_target(download)); + + rpc::call_command("d.set_peer_exchange", rpc::call_command_value("get_peer_exchange"), rpc::make_target(download)); + +diff --git a/src/core/download_factory.h b/src/core/download_factory.h +index 045c9dc..3cc9622 100644 +--- a/src/core/download_factory.h ++++ b/src/core/download_factory.h +@@ -112,6 +112,7 @@ private: + }; + + bool is_network_uri(const std::string& uri); ++bool is_magnet_uri(const std::string& uri); + + } + +diff --git a/src/core/download_list.cc b/src/core/download_list.cc +index 551f873..13df725 100644 +--- a/src/core/download_list.cc ++++ b/src/core/download_list.cc +@@ -37,10 +37,12 @@ + #include "config.h" + + #include ++#include + #include + #include + #include + #include ++#include + #include + #include + #include +@@ -452,6 +454,9 @@ DownloadList::hash_done(Download* download) { + int64_t hashing = rpc::call_command_value("d.get_hashing", rpc::make_target(download)); + rpc::call_command_set_value("d.set_hashing", Download::variable_hashing_stopped, rpc::make_target(download)); + ++ if (download->is_done() && download->download()->is_meta_download()) ++ return process_meta_download(download); ++ + switch (hashing) { + case Download::variable_hashing_initial: + case Download::variable_hashing_rehash: +@@ -543,6 +548,9 @@ void + DownloadList::confirm_finished(Download* download) { + check_contains(download); + ++ if (download->download()->is_meta_download()) ++ return process_meta_download(download); ++ + rpc::call_command("d.set_complete", (int64_t)1, rpc::make_target(download)); + + rpc::call_command("d.set_connection_current", rpc::call_command_void("d.get_connection_seed", rpc::make_target(download)), rpc::make_target(download)); +@@ -576,4 +584,36 @@ DownloadList::confirm_finished(Download* download) { + resume(download, torrent::Download::start_no_create | torrent::Download::start_skip_tracker | torrent::Download::start_keep_baseline); + } + ++void ++DownloadList::process_meta_download(Download* download) { ++ rpc::call_command("d.stop", torrent::Object(), rpc::make_target(download)); ++ rpc::call_command("d.close", torrent::Object(), rpc::make_target(download)); ++ ++ std::string metafile = (*download->file_list()->begin())->frozen_path(); ++ std::fstream file(metafile.c_str(), std::ios::in | std::ios::binary); ++ if (!file.is_open()) { ++ control->core()->push_log("Could not read download metadata."); ++ return; ++ } ++ ++ torrent::Object* bencode = new torrent::Object(torrent::Object::create_map()); ++ file >> bencode->insert_key("info", torrent::Object()); ++ if (file.fail()) { ++ delete bencode; ++ control->core()->push_log("Could not create download, the input is not a valid torrent."); ++ return; ++ } ++ file.close(); ++ ++ // Steal the keys we still need. The old download has no use for them. ++ bencode->insert_key("rtorrent_meta_download", torrent::Object()).swap(download->bencode()->get_key("rtorrent_meta_download")); ++ if (download->bencode()->has_key("announce")) ++ bencode->insert_key("announce", torrent::Object()).swap(download->bencode()->get_key("announce")); ++ if (download->bencode()->has_key("announce-list")) ++ bencode->insert_key("announce-list", torrent::Object()).swap(download->bencode()->get_key("announce-list")); ++ ++ erase_ptr(download); ++ control->core()->try_create_download_from_meta_download(bencode, metafile); ++} ++ + } +diff --git a/src/core/download_list.h b/src/core/download_list.h +index f7828ea..8ecffa0 100644 +--- a/src/core/download_list.h ++++ b/src/core/download_list.h +@@ -161,6 +161,8 @@ private: + + void received_finished(Download* d); + void confirm_finished(Download* d); ++ ++ void process_meta_download(Download* d); + }; + + } +diff --git a/src/core/manager.cc b/src/core/manager.cc +index 62738ca..2a422c8 100644 +--- a/src/core/manager.cc ++++ b/src/core/manager.cc +@@ -39,6 +39,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -52,6 +53,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -395,6 +397,7 @@ Manager::try_create_download(const std::string& uri, int flags, const command_li + if ((flags & create_tied) && + !(flags & create_raw_data) && + !is_network_uri(uri) && ++ !is_magnet_uri(uri) && + !file_status_cache()->insert(uri, 0)) + return; + +@@ -416,6 +419,31 @@ Manager::try_create_download(const std::string& uri, int flags, const command_li + f->commit(); + } + ++void ++Manager::try_create_download_from_meta_download(torrent::Object* bencode, const std::string& metafile) { ++ DownloadFactory* f = new DownloadFactory(this); ++ ++ f->variables()["tied_to_file"] = (int64_t)true; ++ f->variables()["tied_file"] = metafile; ++ ++ torrent::Object& meta = bencode->get_key("rtorrent_meta_download"); ++ torrent::Object::list_type& commands = meta.get_key_list("commands"); ++ for (torrent::Object::list_type::const_iterator itr = commands.begin(); itr != commands.end(); ++itr) ++ f->commands().insert(f->commands().end(), itr->as_string()); ++ ++ f->set_start(meta.get_key_value("start")); ++ f->set_print_log(meta.get_key_value("print_log")); ++ f->slot_finished(sigc::bind(sigc::ptr_fun(&rak::call_delete_func), f)); ++ ++ // Bit of a waste to create the bencode repesentation here ++ // only to have the DownloadFactory decode it. ++ std::stringstream s; ++ s.imbue(std::locale::classic()); ++ s << *bencode; ++ f->load_raw_data(s.str()); ++ f->commit(); ++} ++ + utils::Directory + path_expand_transform(std::string path, const utils::directory_entry& entry) { + return path + entry.d_name; +diff --git a/src/core/manager.h b/src/core/manager.h +index 3b23da3..16902af 100644 +--- a/src/core/manager.h ++++ b/src/core/manager.h +@@ -128,6 +128,7 @@ public: + // Temporary, find a better place for this. + void try_create_download(const std::string& uri, int flags, const command_list_type& commands); + void try_create_download_expand(const std::string& uri, int flags, command_list_type commands = command_list_type()); ++ void try_create_download_from_meta_download(torrent::Object* bencode, const std::string& metafile); + + private: + typedef RangeMap AddressThrottleMap; -- cgit v1.2.3-24-g4f1b