From 1698b2c7b1b6b474425842e57f89a33a68442e04 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Wed, 16 Feb 2011 00:44:23 +0900 Subject: [PATCH] Save downloads added by aria2.addTorrent or aria2.addMetalink in --save-session file. Uploaded data are saved as file named hex string of sha1 hash of uploaded data plus extension(".torrent" for torrent and ".metalink" for metalink). For example, 0a3893293e27ac0490424c06de4d09242215f0a6.torrent. The directory where these files are saved is specified by --dir option. These file paths are written in --save-session file. --- src/XmlRpcMethodImpl.cc | 48 +++++++++++++++++++++++++++++++++++++--- test/XmlRpcMethodTest.cc | 46 ++++++++++++++++++++++++++++---------- 2 files changed, 79 insertions(+), 15 deletions(-) diff --git a/src/XmlRpcMethodImpl.cc b/src/XmlRpcMethodImpl.cc index c416cfff..4e2a9007 100644 --- a/src/XmlRpcMethodImpl.cc +++ b/src/XmlRpcMethodImpl.cc @@ -70,6 +70,8 @@ # include "Peer.h" # include "BtRuntime.h" # include "BtAnnounce.h" +# include "MessageDigest.h" +# include "message_digest_helper.h" #endif // ENABLE_BITTORRENT namespace aria2 { @@ -244,6 +246,18 @@ SharedHandle AddUriXmlRpcMethod::process } } +namespace { + +std::string getHexSha1(const std::string& s) +{ + unsigned char hash[20]; + message_digest::digest(hash, sizeof(hash), MessageDigest::sha1(), + s.data(), s.size()); + return util::toHex(hash, sizeof(hash)); +} + +} // namespace + #ifdef ENABLE_BITTORRENT SharedHandle AddTorrentXmlRpcMethod::process (const XmlRpcRequest& req, DownloadEngine* e) @@ -263,9 +277,21 @@ SharedHandle AddTorrentXmlRpcMethod::process bool posGiven = false; getPosParam(req, 3, posGiven, pos); + std::string filename = util::applyDir + (requestOption->get(PREF_DIR), getHexSha1(torrentParam->s())+".torrent"); std::vector > result; - createRequestGroupForBitTorrent(result, requestOption, - uris, torrentParam->s()); + // Save uploaded data in order to save this download in + // --save-session file. + if(util::saveAs(filename, torrentParam->s(), true)) { + A2_LOG_INFO(fmt("Uploaded torrent data was saved as %s", filename.c_str())); + requestOption->put(PREF_TORRENT_FILE, filename); + createRequestGroupForBitTorrent(result, requestOption, uris); + } else { + A2_LOG_INFO(fmt("Uploaded torrent data was not saved." + " Failed to write file %s", filename.c_str())); + createRequestGroupForBitTorrent(result, requestOption, + uris, torrentParam->s()); + } if(!result.empty()) { return addRequestGroup(result.front(), e, posGiven, pos); @@ -291,8 +317,24 @@ SharedHandle AddMetalinkXmlRpcMethod::process bool posGiven = false; getPosParam(req, 2, posGiven, pos); + // TODO RFC5854 Metalink has the extension .meta4. We use .metalink + // for both v3 and RFC5854 Metalink. aria2 can detect which of which + // by reading content rather than extension. + std::string filename = util::applyDir + (requestOption->get(PREF_DIR), getHexSha1(metalinkParam->s())+".metalink"); std::vector > result; - createRequestGroupForMetalink(result, requestOption, metalinkParam->s()); + // Save uploaded data in order to save this download in + // --save-session file. + if(util::saveAs(filename, metalinkParam->s(), true)) { + A2_LOG_INFO(fmt("Uploaded metalink data was saved as %s", + filename.c_str())); + requestOption->put(PREF_METALINK_FILE, filename); + createRequestGroupForMetalink(result, requestOption); + } else { + A2_LOG_INFO(fmt("Uploaded metalink data was not saved." + " Failed to write file %s", filename.c_str())); + createRequestGroupForMetalink(result, requestOption, metalinkParam->s()); + } SharedHandle gids = List::g(); if(!result.empty()) { if(posGiven) { diff --git a/test/XmlRpcMethodTest.cc b/test/XmlRpcMethodTest.cc index f33b42cc..c15f689f 100644 --- a/test/XmlRpcMethodTest.cc +++ b/test/XmlRpcMethodTest.cc @@ -85,8 +85,9 @@ public: { RequestGroup::resetGIDCounter(); option_.reset(new Option()); - option_->put(PREF_DIR, "/tmp"); + option_->put(PREF_DIR, A2_TEST_OUT_DIR"/aria2_XmlRpcMethodTest"); option_->put(PREF_SEGMENT_SIZE, "1048576"); + File(option_->get(PREF_DIR)).mkdirs(); e_.reset (new DownloadEngine(SharedHandle(new SelectEventPoll()))); e_->setOption(option_.get()); @@ -255,6 +256,8 @@ void XmlRpcMethodTest::testAddUri_withBadPosition() #ifdef ENABLE_BITTORRENT void XmlRpcMethodTest::testAddTorrent() { + File(e_->getOption()->get(PREF_DIR)+ + "/0a3893293e27ac0490424c06de4d09242215f0a6.torrent").remove(); AddTorrentXmlRpcMethod m; XmlRpcRequest req(AddTorrentXmlRpcMethod::getMethodName(), List::g()); req.params->append(readFile(A2_TEST_DIR"/single.torrent")); @@ -263,13 +266,16 @@ void XmlRpcMethodTest::testAddTorrent() req.params->append(uris); { XmlRpcResponse res = m.execute(req, e_.get()); + CPPUNIT_ASSERT + (File(e_->getOption()->get(PREF_DIR)+ + "/0a3893293e27ac0490424c06de4d09242215f0a6.torrent").exists()); CPPUNIT_ASSERT_EQUAL(0, res.code); CPPUNIT_ASSERT_EQUAL(std::string("1"), asString(res.param)->s()); SharedHandle group = e_->getRequestGroupMan()->findReservedGroup(1); CPPUNIT_ASSERT(group); - CPPUNIT_ASSERT_EQUAL(std::string("/tmp/aria2-0.8.2.tar.bz2"), + CPPUNIT_ASSERT_EQUAL(e_->getOption()->get(PREF_DIR)+"/aria2-0.8.2.tar.bz2", group->getFirstFilePath()); CPPUNIT_ASSERT_EQUAL((size_t)1, group->getDownloadContext()->getFirstFileEntry()-> @@ -279,15 +285,20 @@ void XmlRpcMethodTest::testAddTorrent() getRemainingUris()[0]); } // with options + std::string dir = A2_TEST_OUT_DIR"/aria2_XmlRpcMethodTest_testAddTorrent"; + File(dir).mkdirs(); SharedHandle opt = Dict::g(); - opt->put(PREF_DIR, "/sink"); + opt->put(PREF_DIR, dir); + File(dir+"/0a3893293e27ac0490424c06de4d09242215f0a6.torrent").remove(); req.params->append(opt); { XmlRpcResponse res = m.execute(req, e_.get()); CPPUNIT_ASSERT_EQUAL(0, res.code); - CPPUNIT_ASSERT_EQUAL(std::string("/sink/aria2-0.8.2.tar.bz2"), - e_->getRequestGroupMan()->findReservedGroup(2)-> - getFirstFilePath()); + CPPUNIT_ASSERT_EQUAL + (dir+"/aria2-0.8.2.tar.bz2", + e_->getRequestGroupMan()->findReservedGroup(2)->getFirstFilePath()); + CPPUNIT_ASSERT + (File(dir+"/0a3893293e27ac0490424c06de4d09242215f0a6.torrent").exists()); } } @@ -335,6 +346,8 @@ void XmlRpcMethodTest::testAddTorrent_withPosition() #ifdef ENABLE_METALINK void XmlRpcMethodTest::testAddMetalink() { + File(e_->getOption()->get(PREF_DIR)+ + "/c908634fbc257fd56f0114912c2772aeeb4064f4.metalink").remove(); AddMetalinkXmlRpcMethod m; XmlRpcRequest req(AddMetalinkXmlRpcMethod::getMethodName(), List::g()); req.params->append(readFile(A2_TEST_DIR"/2files.metalink")); @@ -345,28 +358,36 @@ void XmlRpcMethodTest::testAddMetalink() CPPUNIT_ASSERT_EQUAL((size_t)2, resParams->size()); CPPUNIT_ASSERT_EQUAL(std::string("1"), asString(resParams->get(0))->s()); CPPUNIT_ASSERT_EQUAL(std::string("2"), asString(resParams->get(1))->s()); + CPPUNIT_ASSERT + (File(e_->getOption()->get(PREF_DIR)+ + "/c908634fbc257fd56f0114912c2772aeeb4064f4.metalink").exists()); SharedHandle tar = e_->getRequestGroupMan()->findReservedGroup(1); CPPUNIT_ASSERT(tar); - CPPUNIT_ASSERT_EQUAL(std::string("/tmp/aria2-5.0.0.tar.bz2"), + CPPUNIT_ASSERT_EQUAL(e_->getOption()->get(PREF_DIR)+"/aria2-5.0.0.tar.bz2", tar->getFirstFilePath()); SharedHandle deb = e_->getRequestGroupMan()->findReservedGroup(2); CPPUNIT_ASSERT(deb); - CPPUNIT_ASSERT_EQUAL(std::string("/tmp/aria2-5.0.0.deb"), + CPPUNIT_ASSERT_EQUAL(e_->getOption()->get(PREF_DIR)+"/aria2-5.0.0.deb", deb->getFirstFilePath()); } // with options + std::string dir = A2_TEST_OUT_DIR"/aria2_XmlRpcMethodTest_testAddMetalink"; + File(dir).mkdirs(); SharedHandle opt = Dict::g(); - opt->put(PREF_DIR, "/sink"); + opt->put(PREF_DIR, dir); + File(dir+"/c908634fbc257fd56f0114912c2772aeeb4064f4.metalink").remove(); req.params->append(opt); { XmlRpcResponse res = m.execute(req, e_.get()); CPPUNIT_ASSERT_EQUAL(0, res.code); - CPPUNIT_ASSERT_EQUAL(std::string("/sink/aria2-5.0.0.tar.bz2"), + CPPUNIT_ASSERT_EQUAL(dir+"/aria2-5.0.0.tar.bz2", e_->getRequestGroupMan()->findReservedGroup(3)-> getFirstFilePath()); + CPPUNIT_ASSERT + (File(dir+"/c908634fbc257fd56f0114912c2772aeeb4064f4.metalink").exists()); } } @@ -405,7 +426,7 @@ void XmlRpcMethodTest::testAddMetalink_withPosition() XmlRpcResponse res2 = m2.execute(req2, e_.get()); CPPUNIT_ASSERT_EQUAL(0, res2.code); - CPPUNIT_ASSERT_EQUAL(std::string("/tmp/aria2-5.0.0.tar.bz2"), + CPPUNIT_ASSERT_EQUAL(e_->getOption()->get(PREF_DIR)+"/aria2-5.0.0.tar.bz2", e_->getRequestGroupMan()->getReservedGroups()[0]-> getFirstFilePath()); } @@ -779,7 +800,8 @@ void XmlRpcMethodTest::testGatherProgressCommon() (asList(file->get("uris"))->get(0)) ->get("uri")) ->s()); - CPPUNIT_ASSERT_EQUAL(std::string("/tmp"), asString(entry->get("dir"))->s()); + CPPUNIT_ASSERT_EQUAL(e_->getOption()->get(PREF_DIR), + asString(entry->get("dir"))->s()); keys.push_back("gid"); entry = Dict::g();