summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/FileEntry.cc5
-rw-r--r--src/FileEntry.h10
-rw-r--r--src/FtpNegotiationCommand.cc10
-rw-r--r--src/HttpResponseCommand.cc7
-rw-r--r--src/Metalink2RequestGroup.cc3
-rw-r--r--src/RpcMethodImpl.cc33
-rw-r--r--src/bittorrent_helper.cc24
-rw-r--r--src/util.cc7
-rw-r--r--src/util.h2
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);
diff --git a/src/util.h b/src/util.h
index 9e6744e5..a3a30c44 100644
--- a/src/util.h
+++ b/src/util.h
@@ -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.