diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/FileEntry.cc | 5 | ||||
| -rw-r--r-- | src/FileEntry.h | 10 | ||||
| -rw-r--r-- | src/FtpNegotiationCommand.cc | 10 | ||||
| -rw-r--r-- | src/HttpResponseCommand.cc | 7 | ||||
| -rw-r--r-- | src/Metalink2RequestGroup.cc | 3 | ||||
| -rw-r--r-- | src/RpcMethodImpl.cc | 33 | ||||
| -rw-r--r-- | src/bittorrent_helper.cc | 24 | ||||
| -rw-r--r-- | src/util.cc | 7 | ||||
| -rw-r--r-- | src/util.h | 2 |
9 files changed, 77 insertions, 24 deletions
diff --git a/src/FileEntry.cc b/src/FileEntry.cc index fb4c713e..9fb08d03 100644 --- a/src/FileEntry.cc +++ b/src/FileEntry.cc @@ -572,6 +572,11 @@ void FileEntry::setOriginalName(std::string originalName) originalName_ = std::move(originalName); } +void FileEntry::setSuffixPath(std::string suffixPath) +{ + suffixPath_ = std::move(suffixPath); +} + bool FileEntry::emptyRequestUri() const { return uris_.empty() && inFlightRequests_.empty() && requestPool_.empty(); diff --git a/src/FileEntry.h b/src/FileEntry.h index 9e760a83..5f381d0c 100644 --- a/src/FileEntry.h +++ b/src/FileEntry.h @@ -85,6 +85,9 @@ private: std::string path_; std::string contentType_; std::string originalName_; + // path_ without parent directory component. This is primarily used + // to change directory (PREF_DIR option). + std::string suffixPath_; Timer lastFasterReplace_; int maxConnectionPerServer_; @@ -264,6 +267,13 @@ public: return originalName_; } + void setSuffixPath(std::string suffixPath); + + const std::string& getSuffixPath() const + { + return suffixPath_; + } + bool removeUri(const std::string& uri); bool emptyRequestUri() const; diff --git a/src/FtpNegotiationCommand.cc b/src/FtpNegotiationCommand.cc index 16237fe0..062db5e7 100644 --- a/src/FtpNegotiationCommand.cc +++ b/src/FtpNegotiationCommand.cc @@ -361,11 +361,13 @@ bool FtpNegotiationCommand::onFileSizeDetermined(int64_t totalLength) { getFileEntry()->setLength(totalLength); if(getFileEntry()->getPath().empty()) { + auto suffixPath = util::createSafePath + (util::percentDecode(std::begin(getRequest()->getFile()), + std::end(getRequest()->getFile()))); + getFileEntry()->setPath - (util::createSafePath - (getOption()->get(PREF_DIR), - util::percentDecode(getRequest()->getFile().begin(), - getRequest()->getFile().end()))); + (util::applyDir(getOption()->get(PREF_DIR), suffixPath)); + getFileEntry()->setSuffixPath(suffixPath); } getRequestGroup()->preDownloadProcessing(); if(totalLength == 0) { diff --git a/src/HttpResponseCommand.cc b/src/HttpResponseCommand.cc index 34ae1cc8..9e9477ab 100644 --- a/src/HttpResponseCommand.cc +++ b/src/HttpResponseCommand.cc @@ -249,8 +249,11 @@ bool HttpResponseCommand::executeInternal() int64_t totalLength = httpResponse->getEntityLength(); fe->setLength(totalLength); if (fe->getPath().empty()) { - fe->setPath(util::createSafePath(getOption()->get(PREF_DIR), - httpResponse->determineFilename())); + auto suffixPath = + util::createSafePath(httpResponse->determineFilename()); + + fe->setPath(util::applyDir(getOption()->get(PREF_DIR), suffixPath)); + fe->setSuffixPath(suffixPath); } fe->setContentType(httpResponse->getContentType()); grp->preDownloadProcessing(); diff --git a/src/Metalink2RequestGroup.cc b/src/Metalink2RequestGroup.cc index 6463aae6..9eb509b9 100644 --- a/src/Metalink2RequestGroup.cc +++ b/src/Metalink2RequestGroup.cc @@ -265,6 +265,8 @@ Metalink2RequestGroup::createRequestGroup entry->file->getPath())); dctx->getFirstFileEntry()->setUris(uris); dctx->getFirstFileEntry()->setMaxConnectionPerServer(maxConn); + dctx->getFirstFileEntry()->setSuffixPath(entry->file->getPath()); + if(option->getAsBool(PREF_METALINK_ENABLE_UNIQUE_PROTOCOL)) { dctx->getFirstFileEntry()->setUniqueProtocol(true); } @@ -307,6 +309,7 @@ Metalink2RequestGroup::createRequestGroup fe->setUniqueProtocol(true); } fe->setOriginalName(entry->metaurls[0]->name); + fe->setSuffixPath(entry->file->getPath()); fileEntries.push_back(fe); if(offset > std::numeric_limits<int64_t>::max() - entry->file->getLength()) { diff --git a/src/RpcMethodImpl.cc b/src/RpcMethodImpl.cc index e7ef98c0..375f4e3d 100644 --- a/src/RpcMethodImpl.cc +++ b/src/RpcMethodImpl.cc @@ -1473,22 +1473,35 @@ void changeOption } } if(option.defined(PREF_DIR) || option.defined(PREF_OUT)) { - if(dctx->getFileEntries().size() == 1 -#ifdef ENABLE_BITTORRENT - && !dctx->hasAttribute(CTX_ATTR_BT) -#endif // ENABLE_BITTORRENT - ) { + if(!group->getMetadataInfo()) { + + assert(dctx->getFileEntries().size() == 1); auto& fileEntry = dctx->getFirstFileEntry(); - if(grOption->blank(PREF_OUT)) { - // We need to reset length to 0, so that we pretend that file - // name is unknown and it should be determined at next run. - fileEntry->setLength(0); + if(!grOption->blank(PREF_OUT)) { + fileEntry->setPath + (util::applyDir(grOption->get(PREF_DIR), grOption->get(PREF_OUT))); + fileEntry->setSuffixPath(A2STR::NIL); + } else if(fileEntry->getSuffixPath().empty()) { fileEntry->setPath(A2STR::NIL); } else { 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())); } } } diff --git a/src/bittorrent_helper.cc b/src/bittorrent_helper.cc index 4f2309f8..23cfdbbb 100644 --- a/src/bittorrent_helper.cc +++ b/src/bittorrent_helper.cc @@ -278,11 +278,15 @@ void extractFileEntries (util::percentEncode))); std::vector<std::string> uris; createUri(urlList.begin(), urlList.end(),std::back_inserter(uris),pePath); - std::shared_ptr<FileEntry> fileEntry - (new FileEntry(util::applyDir(option->get(PREF_DIR), - util::escapePath(utf8Path)), - fileLengthData->i(), offset, uris)); + + auto suffixPath = util::escapePath(utf8Path); + + auto fileEntry = + std::make_shared<FileEntry>(util::applyDir(option->get(PREF_DIR), + suffixPath), + fileLengthData->i(), offset, uris); fileEntry->setOriginalName(utf8Path); + fileEntry->setSuffixPath(suffixPath); fileEntry->setMaxConnectionPerServer(maxConn); fileEntries.push_back(fileEntry); offset += fileEntry->getLength(); @@ -316,11 +320,15 @@ void extractFileEntries uris.push_back(elem); } } - std::shared_ptr<FileEntry> fileEntry - (new FileEntry(util::applyDir(option->get(PREF_DIR), - util::escapePath(utf8Name)), - totalLength, 0, uris)); + + auto suffixPath = util::escapePath(utf8Name); + + auto fileEntry = + std::make_shared<FileEntry>(util::applyDir(option->get(PREF_DIR), + suffixPath), + totalLength, 0, uris); fileEntry->setOriginalName(utf8Name); + fileEntry->setSuffixPath(suffixPath); fileEntry->setMaxConnectionPerServer(maxConn); fileEntries.push_back(fileEntry); } diff --git a/src/util.cc b/src/util.cc index 0f8bce55..7ead5964 100644 --- a/src/util.cc +++ b/src/util.cc @@ -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) { return util::isUtf8(s)?s:util::percentEncode(s); @@ -791,6 +791,8 @@ void executeHookByOptName 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); // Create string safely. If str is NULL, returns empty string. |
