Webdav href in response can be relative

Fixed Webdav base path stripping in cases where href is a relative path. Signed-off-by: 's avatarVincent Petry <PVince81@yahoo.fr>
parent b7d00013
...@@ -468,11 +468,19 @@ CurlStorage::GetInfo(std::string_view uri_utf8, [[maybe_unused]] bool follow) ...@@ -468,11 +468,19 @@ CurlStorage::GetInfo(std::string_view uri_utf8, [[maybe_unused]] bool follow)
gcc_pure gcc_pure
static std::string_view static std::string_view
UriPathOrSlash(const char *uri) noexcept UriPathOrSlash(const char *uri, bool relative) noexcept
{ {
auto path = uri_get_path(uri); auto path = uri_get_path(uri);
if (path.data() == nullptr) if (path.data() == nullptr)
path = "/"; path = "/";
else if (relative) {
// search after first slash
path = path.substr(1);
auto slash = path.find('/');
if (slash != std::string_view::npos)
path = path.substr(slash);
}
return path; return path;
} }
...@@ -481,13 +489,15 @@ UriPathOrSlash(const char *uri) noexcept ...@@ -481,13 +489,15 @@ UriPathOrSlash(const char *uri) noexcept
*/ */
class HttpListDirectoryOperation final : public PropfindOperation { class HttpListDirectoryOperation final : public PropfindOperation {
const std::string base_path; const std::string base_path;
const std::string base_path_relative;
MemoryStorageDirectoryReader::List entries; MemoryStorageDirectoryReader::List entries;
public: public:
HttpListDirectoryOperation(CurlGlobal &curl, const char *uri) HttpListDirectoryOperation(CurlGlobal &curl, const char *uri)
:PropfindOperation(curl, uri, 1), :PropfindOperation(curl, uri, 1),
base_path(CurlUnescape(GetEasy(), UriPathOrSlash(uri))) {} base_path(CurlUnescape(GetEasy(), UriPathOrSlash(uri, false))),
base_path_relative(CurlUnescape(GetEasy(), UriPathOrSlash(uri, true))) {}
std::unique_ptr<StorageDirectoryReader> Perform() { std::unique_ptr<StorageDirectoryReader> Perform() {
DeferStart(); DeferStart();
...@@ -506,6 +516,7 @@ private: ...@@ -506,6 +516,7 @@ private:
*/ */
gcc_pure gcc_pure
StringView HrefToEscapedName(const char *href) const noexcept { StringView HrefToEscapedName(const char *href) const noexcept {
StringView relative_path;
StringView path = uri_get_path(href); StringView path = uri_get_path(href);
if (path == nullptr) if (path == nullptr)
return nullptr; return nullptr;
...@@ -513,17 +524,23 @@ private: ...@@ -513,17 +524,23 @@ private:
/* kludge: ignoring case in this comparison to avoid /* kludge: ignoring case in this comparison to avoid
false negatives if the web server uses a different false negatives if the web server uses a different
case */ case */
path = StringAfterPrefixIgnoreCase(path, base_path.c_str()); relative_path = StringAfterPrefixIgnoreCase(path, base_path.c_str());
if (path == nullptr || path.empty()) if (relative_path == nullptr || relative_path.empty()) {
// try relative base path
relative_path = StringAfterPrefixIgnoreCase(path, base_path_relative.c_str());
}
if (relative_path == nullptr || relative_path.empty()) {
return nullptr; return nullptr;
}
const char *slash = path.Find('/'); const char *slash = relative_path.Find('/');
if (slash == nullptr) if (slash == nullptr)
/* regular file */ /* regular file */
return path; return relative_path;
else if (slash == &path.back()) else if (slash == &relative_path.back())
/* trailing slash: collection; strip the slash */ /* trailing slash: collection; strip the slash */
return {path.data, slash}; return {relative_path.data, slash};
else else
/* strange, better ignore it */ /* strange, better ignore it */
return nullptr; return nullptr;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment