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();