Skip to content

Commit

Permalink
Improve relative path resolution (retry)
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelsternberg authored and tschak909 committed Oct 1, 2024
1 parent 16c9d26 commit febf356
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 20 deletions.
3 changes: 2 additions & 1 deletion lib/utils/peoples_url_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <vector>

#include "../../include/debug.h"
#include "utils.h"

#include "string_utils.h"

Expand Down Expand Up @@ -92,7 +93,7 @@ void PeoplesUrlParser::cleanPath() {
// while(mstr::endsWith(path,"/")) {
// path=mstr::dropLast(path, 1);
// }
mstr::replaceAll(path, "//", "/");
path = util_get_canonical_path(path);
}

void PeoplesUrlParser::processPath() {
Expand Down
47 changes: 28 additions & 19 deletions lib/utils/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -790,16 +790,19 @@ void util_replaceAll(std::string &str, const std::string &from, const std::strin
}

/**
* Resolve prefix containing relative references (../ or ./)
* Resolve path containing relative references (../ or ./)
* to canonical path.
* @param prefix FujiNet path such as TNFS://myhost/path/to/here/
* @param path FujiNet path such as TNFS://myhost/path/to/here/
* or tnfs://myhost/some/filename.ext
*/
std::string util_get_canonical_path(std::string prefix)
std::string util_get_canonical_path(std::string path)
{
bool is_last_slash = (path.back() == '/') ? true : false;

std::size_t proto_host_len;

// stack to store the file's names.
std::stack<string> st;
std::stack<std::string> st;

// temporary string which stores the extracted
// directory name or commands("." / "..")
Expand All @@ -811,35 +814,41 @@ std::string util_get_canonical_path(std::string prefix)
std::string res;

// advance beyond protocol and hostname
proto_host_len = prefix.find("://");
proto_host_len = path.find("://");

if (proto_host_len > 0)
// If protocol delimiter "://" is found, skip over the protocol
if (proto_host_len < std::string::npos)
{
proto_host_len += 3;
proto_host_len = prefix.find("/", proto_host_len) + 1;
proto_host_len += 3; // "://" is 3 chars
proto_host_len = path.find("/", proto_host_len) + 1;
res.append(path.substr(0, proto_host_len));
}
else
{
proto_host_len = 0; // no protocol prefix and hostname
// Preserve an absolute path if one is provided in the input
if (!path.empty() && path[0] == '/')
res = "/";
}

res.append(prefix.substr(0, proto_host_len));

int len_prefix = prefix.length();
int len_path = path.length();

// for (int i = proto_host_len-1; i < len_prefix; i++)
for (int i = proto_host_len; i < len_prefix; i++)
for (int i = proto_host_len; i < len_path; i++)
{
// we will clear the temporary string
// every time to accommodate new directory
// name or command.
dir.clear();

// skip all the multiple '/' Eg. "/////""
while (prefix[i] == '/')
while (path[i] == '/')
i++;

// stores directory's name("a", "b" etc.)
// or commands("."/"..") into dir
while (i < len_prefix && prefix[i] != '/')
while (i < len_path && path[i] != '/')
{
dir.push_back(prefix[i]);
dir.push_back(path[i]);
i++;
}

Expand All @@ -865,7 +874,7 @@ std::string util_get_canonical_path(std::string prefix)

// a temporary stack (st1) which will contain
// the reverse of original stack(st).
std::stack<string> st1;
std::stack<std::string> st1;
while (!st.empty())
{
st1.push(st.top());
Expand All @@ -888,7 +897,7 @@ std::string util_get_canonical_path(std::string prefix)
}

// Append trailing slash if not already there
if ((res.length() > 0) && (res[res.length() - 1] != '/'))
if ((res.length() > 0) && (res.back() != '/') && is_last_slash)
res.append("/");

return res;
Expand Down Expand Up @@ -1058,4 +1067,4 @@ char* util_strndup(const char* s, size_t n) {
int get_value_or_default(const std::map<int, int>& map, int key, int default_value) {
auto it = map.find(key);
return it != map.end() ? it->second : default_value;
}
}

0 comments on commit febf356

Please sign in to comment.