Support PREF_DIR change for Metalink files

Reworked previous commit adeead6f03, and
now support changing PREF_DIR for Metalink downloads.
pull/235/merge
Tatsuhiro Tsujikawa 2014-06-04 21:45:12 +09:00
parent adeead6f03
commit 4f3c526dcd
11 changed files with 87 additions and 24 deletions

View File

@ -572,6 +572,11 @@ void FileEntry::setOriginalName(std::string originalName)
originalName_ = std::move(originalName); originalName_ = std::move(originalName);
} }
void FileEntry::setSuffixPath(std::string suffixPath)
{
suffixPath_ = std::move(suffixPath);
}
bool FileEntry::emptyRequestUri() const bool FileEntry::emptyRequestUri() const
{ {
return uris_.empty() && inFlightRequests_.empty() && requestPool_.empty(); return uris_.empty() && inFlightRequests_.empty() && requestPool_.empty();

View File

@ -85,6 +85,9 @@ private:
std::string path_; std::string path_;
std::string contentType_; std::string contentType_;
std::string originalName_; std::string originalName_;
// path_ without parent directory component. This is primarily used
// to change directory (PREF_DIR option).
std::string suffixPath_;
Timer lastFasterReplace_; Timer lastFasterReplace_;
int maxConnectionPerServer_; int maxConnectionPerServer_;
@ -264,6 +267,13 @@ public:
return originalName_; return originalName_;
} }
void setSuffixPath(std::string suffixPath);
const std::string& getSuffixPath() const
{
return suffixPath_;
}
bool removeUri(const std::string& uri); bool removeUri(const std::string& uri);
bool emptyRequestUri() const; bool emptyRequestUri() const;

View File

@ -361,11 +361,13 @@ bool FtpNegotiationCommand::onFileSizeDetermined(int64_t totalLength)
{ {
getFileEntry()->setLength(totalLength); getFileEntry()->setLength(totalLength);
if(getFileEntry()->getPath().empty()) { if(getFileEntry()->getPath().empty()) {
auto suffixPath = util::createSafePath
(util::percentDecode(std::begin(getRequest()->getFile()),
std::end(getRequest()->getFile())));
getFileEntry()->setPath getFileEntry()->setPath
(util::createSafePath (util::applyDir(getOption()->get(PREF_DIR), suffixPath));
(getOption()->get(PREF_DIR), getFileEntry()->setSuffixPath(suffixPath);
util::percentDecode(getRequest()->getFile().begin(),
getRequest()->getFile().end())));
} }
getRequestGroup()->preDownloadProcessing(); getRequestGroup()->preDownloadProcessing();
if(totalLength == 0) { if(totalLength == 0) {

View File

@ -249,8 +249,11 @@ bool HttpResponseCommand::executeInternal()
int64_t totalLength = httpResponse->getEntityLength(); int64_t totalLength = httpResponse->getEntityLength();
fe->setLength(totalLength); fe->setLength(totalLength);
if (fe->getPath().empty()) { if (fe->getPath().empty()) {
fe->setPath(util::createSafePath(getOption()->get(PREF_DIR), auto suffixPath =
httpResponse->determineFilename())); util::createSafePath(httpResponse->determineFilename());
fe->setPath(util::applyDir(getOption()->get(PREF_DIR), suffixPath));
fe->setSuffixPath(suffixPath);
} }
fe->setContentType(httpResponse->getContentType()); fe->setContentType(httpResponse->getContentType());
grp->preDownloadProcessing(); grp->preDownloadProcessing();

View File

@ -265,6 +265,8 @@ Metalink2RequestGroup::createRequestGroup
entry->file->getPath())); entry->file->getPath()));
dctx->getFirstFileEntry()->setUris(uris); dctx->getFirstFileEntry()->setUris(uris);
dctx->getFirstFileEntry()->setMaxConnectionPerServer(maxConn); dctx->getFirstFileEntry()->setMaxConnectionPerServer(maxConn);
dctx->getFirstFileEntry()->setSuffixPath(entry->file->getPath());
if(option->getAsBool(PREF_METALINK_ENABLE_UNIQUE_PROTOCOL)) { if(option->getAsBool(PREF_METALINK_ENABLE_UNIQUE_PROTOCOL)) {
dctx->getFirstFileEntry()->setUniqueProtocol(true); dctx->getFirstFileEntry()->setUniqueProtocol(true);
} }
@ -307,6 +309,7 @@ Metalink2RequestGroup::createRequestGroup
fe->setUniqueProtocol(true); fe->setUniqueProtocol(true);
} }
fe->setOriginalName(entry->metaurls[0]->name); fe->setOriginalName(entry->metaurls[0]->name);
fe->setSuffixPath(entry->file->getPath());
fileEntries.push_back(fe); fileEntries.push_back(fe);
if(offset > if(offset >
std::numeric_limits<int64_t>::max() - entry->file->getLength()) { std::numeric_limits<int64_t>::max() - entry->file->getLength()) {

View File

@ -1473,22 +1473,35 @@ void changeOption
} }
} }
if(option.defined(PREF_DIR) || option.defined(PREF_OUT)) { if(option.defined(PREF_DIR) || option.defined(PREF_OUT)) {
if(dctx->getFileEntries().size() == 1 if(!group->getMetadataInfo()) {
#ifdef ENABLE_BITTORRENT
&& !dctx->hasAttribute(CTX_ATTR_BT) assert(dctx->getFileEntries().size() == 1);
#endif // ENABLE_BITTORRENT
) {
auto& fileEntry = dctx->getFirstFileEntry(); auto& fileEntry = dctx->getFirstFileEntry();
if(grOption->blank(PREF_OUT)) { if(!grOption->blank(PREF_OUT)) {
// We need to reset length to 0, so that we pretend that file fileEntry->setPath
// name is unknown and it should be determined at next run. (util::applyDir(grOption->get(PREF_DIR), grOption->get(PREF_OUT)));
fileEntry->setLength(0); fileEntry->setSuffixPath(A2STR::NIL);
} else if(fileEntry->getSuffixPath().empty()) {
fileEntry->setPath(A2STR::NIL); fileEntry->setPath(A2STR::NIL);
} else { } else {
fileEntry->setPath fileEntry->setPath
(util::applyDir(grOption->get(PREF_DIR), grOption->get(PREF_OUT))); (util::applyDir(grOption->get(PREF_DIR),
fileEntry->getSuffixPath()));
}
} else if(group->getMetadataInfo()
#ifdef ENABLE_BITTORRENT
&& !dctx->hasAttribute(CTX_ATTR_BT)
#endif // ENABLE_BITTORRENT
) {
// In case of Metalink
for(auto& fileEntry : dctx->getFileEntries()) {
// PREF_OUT is not applicable to Metalink. We have always
// suffixPath set.
fileEntry->setPath
(util::applyDir(grOption->get(PREF_DIR),
fileEntry->getSuffixPath()));
} }
} }
} }

View File

@ -278,11 +278,15 @@ void extractFileEntries
(util::percentEncode))); (util::percentEncode)));
std::vector<std::string> uris; std::vector<std::string> uris;
createUri(urlList.begin(), urlList.end(),std::back_inserter(uris),pePath); createUri(urlList.begin(), urlList.end(),std::back_inserter(uris),pePath);
std::shared_ptr<FileEntry> fileEntry
(new FileEntry(util::applyDir(option->get(PREF_DIR), auto suffixPath = util::escapePath(utf8Path);
util::escapePath(utf8Path)),
fileLengthData->i(), offset, uris)); auto fileEntry =
std::make_shared<FileEntry>(util::applyDir(option->get(PREF_DIR),
suffixPath),
fileLengthData->i(), offset, uris);
fileEntry->setOriginalName(utf8Path); fileEntry->setOriginalName(utf8Path);
fileEntry->setSuffixPath(suffixPath);
fileEntry->setMaxConnectionPerServer(maxConn); fileEntry->setMaxConnectionPerServer(maxConn);
fileEntries.push_back(fileEntry); fileEntries.push_back(fileEntry);
offset += fileEntry->getLength(); offset += fileEntry->getLength();
@ -316,11 +320,15 @@ void extractFileEntries
uris.push_back(elem); uris.push_back(elem);
} }
} }
std::shared_ptr<FileEntry> fileEntry
(new FileEntry(util::applyDir(option->get(PREF_DIR), auto suffixPath = util::escapePath(utf8Name);
util::escapePath(utf8Name)),
totalLength, 0, uris)); auto fileEntry =
std::make_shared<FileEntry>(util::applyDir(option->get(PREF_DIR),
suffixPath),
totalLength, 0, uris);
fileEntry->setOriginalName(utf8Name); fileEntry->setOriginalName(utf8Name);
fileEntry->setSuffixPath(suffixPath);
fileEntry->setMaxConnectionPerServer(maxConn); fileEntry->setMaxConnectionPerServer(maxConn);
fileEntries.push_back(fileEntry); fileEntries.push_back(fileEntry);
} }

View File

@ -1878,6 +1878,13 @@ std::string createSafePath
); );
} }
std::string createSafePath(const std::string& filename)
{
return util::isUtf8(filename) ?
util::fixTaintedBasename(filename) :
util::escapePath(util::percentEncode(filename));
}
std::string encodeNonUtf8(const std::string& s) std::string encodeNonUtf8(const std::string& s)
{ {
return util::isUtf8(s)?s:util::percentEncode(s); return util::isUtf8(s)?s:util::percentEncode(s);

View File

@ -791,6 +791,8 @@ void executeHookByOptName
std::string createSafePath(const std::string& dir, const std::string& filename); std::string createSafePath(const std::string& dir, const std::string& filename);
std::string createSafePath(const std::string& filename);
std::string encodeNonUtf8(const std::string& s); std::string encodeNonUtf8(const std::string& s);
// Create string safely. If str is NULL, returns empty string. // Create string safely. If str is NULL, returns empty string.

View File

@ -198,6 +198,8 @@ void BittorrentHelperTest::testGetFileEntriesSingle() {
fileEntry1->getPath()); fileEntry1->getPath());
CPPUNIT_ASSERT_EQUAL(std::string("aria2-0.8.2.tar.bz2"), CPPUNIT_ASSERT_EQUAL(std::string("aria2-0.8.2.tar.bz2"),
fileEntry1->getOriginalName()); fileEntry1->getOriginalName());
CPPUNIT_ASSERT_EQUAL(std::string("aria2-0.8.2.tar.bz2"),
fileEntry1->getSuffixPath());
CPPUNIT_ASSERT_EQUAL(10, fileEntry1->getMaxConnectionPerServer()); CPPUNIT_ASSERT_EQUAL(10, fileEntry1->getMaxConnectionPerServer());
} }
@ -355,6 +357,8 @@ void BittorrentHelperTest::testGetFileEntries_multiFileUrlList() {
const std::shared_ptr<FileEntry>& fileEntry1 = *itr; const std::shared_ptr<FileEntry>& fileEntry1 = *itr;
CPPUNIT_ASSERT_EQUAL(std::string("./aria2-test@/aria2@/src@/aria2c@"), CPPUNIT_ASSERT_EQUAL(std::string("./aria2-test@/aria2@/src@/aria2c@"),
fileEntry1->getPath()); fileEntry1->getPath());
CPPUNIT_ASSERT_EQUAL(std::string("aria2-test@/aria2@/src@/aria2c@"),
fileEntry1->getSuffixPath());
const std::deque<std::string>& uris1 = fileEntry1->getRemainingUris(); const std::deque<std::string>& uris1 = fileEntry1->getRemainingUris();
CPPUNIT_ASSERT_EQUAL((size_t)2, uris1.size()); CPPUNIT_ASSERT_EQUAL((size_t)2, uris1.size());
CPPUNIT_ASSERT_EQUAL(std::string("http://localhost/dist/aria2-test%40/aria2%40/src%40/aria2c%40"), CPPUNIT_ASSERT_EQUAL(std::string("http://localhost/dist/aria2-test%40/aria2%40/src%40/aria2c%40"),
@ -434,6 +438,9 @@ void BittorrentHelperTest::testLoadFromMemory_multiFileNonUtf8Path()
CPPUNIT_ASSERT_EQUAL CPPUNIT_ASSERT_EQUAL
(std::string("./%1B%24B%25O%25m%21%3C%1B%28B/path/%90%A2%8AE"), (std::string("./%1B%24B%25O%25m%21%3C%1B%28B/path/%90%A2%8AE"),
fe->getPath()); fe->getPath());
CPPUNIT_ASSERT_EQUAL
(std::string("%1B%24B%25O%25m%21%3C%1B%28B/path/%90%A2%8AE"),
fe->getSuffixPath());
CPPUNIT_ASSERT_EQUAL CPPUNIT_ASSERT_EQUAL
(std::string("./%1B%24B%25O%25m%21%3C%1B%28B"), dctx->getBasePath()); (std::string("./%1B%24B%25O%25m%21%3C%1B%28B"), dctx->getBasePath());
} }
@ -452,6 +459,7 @@ void BittorrentHelperTest::testLoadFromMemory_singleFileNonUtf8Path()
const std::shared_ptr<FileEntry>& fe = dctx->getFirstFileEntry(); const std::shared_ptr<FileEntry>& fe = dctx->getFirstFileEntry();
CPPUNIT_ASSERT_EQUAL(std::string("./%90%A2%8AE"), fe->getPath()); CPPUNIT_ASSERT_EQUAL(std::string("./%90%A2%8AE"), fe->getPath());
CPPUNIT_ASSERT_EQUAL(std::string("%90%A2%8AE"), fe->getSuffixPath());
} }
void BittorrentHelperTest::testLoadFromMemory() void BittorrentHelperTest::testLoadFromMemory()

View File

@ -163,6 +163,8 @@ void Metalink2RequestGroupTest::testGenerate_groupByMetaurl()
CPPUNIT_ASSERT_EQUAL((size_t)2, fileEntries.size()); CPPUNIT_ASSERT_EQUAL((size_t)2, fileEntries.size());
CPPUNIT_ASSERT_EQUAL(std::string("./file1"), fileEntries[0]->getPath()); CPPUNIT_ASSERT_EQUAL(std::string("./file1"), fileEntries[0]->getPath());
CPPUNIT_ASSERT_EQUAL(std::string("file1"), fileEntries[0]->getOriginalName()); CPPUNIT_ASSERT_EQUAL(std::string("file1"), fileEntries[0]->getOriginalName());
CPPUNIT_ASSERT_EQUAL(std::string("file1"),
fileEntries[0]->getSuffixPath());
CPPUNIT_ASSERT_EQUAL((size_t)1, fileEntries[0]->getRemainingUris().size()); CPPUNIT_ASSERT_EQUAL((size_t)1, fileEntries[0]->getRemainingUris().size());
CPPUNIT_ASSERT_EQUAL(std::string("http://file1p1"), CPPUNIT_ASSERT_EQUAL(std::string("http://file1p1"),
fileEntries[0]->getRemainingUris()[0]); fileEntries[0]->getRemainingUris()[0]);