Skip to content

Commit febf356

Browse files
michaelsternbergtschak909
authored andcommitted
Improve relative path resolution (retry)
1 parent 16c9d26 commit febf356

File tree

2 files changed

+30
-20
lines changed

2 files changed

+30
-20
lines changed

lib/utils/peoples_url_parser.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include <vector>
2727

2828
#include "../../include/debug.h"
29+
#include "utils.h"
2930

3031
#include "string_utils.h"
3132

@@ -92,7 +93,7 @@ void PeoplesUrlParser::cleanPath() {
9293
// while(mstr::endsWith(path,"/")) {
9394
// path=mstr::dropLast(path, 1);
9495
// }
95-
mstr::replaceAll(path, "//", "/");
96+
path = util_get_canonical_path(path);
9697
}
9798

9899
void PeoplesUrlParser::processPath() {

lib/utils/utils.cpp

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -790,16 +790,19 @@ void util_replaceAll(std::string &str, const std::string &from, const std::strin
790790
}
791791

792792
/**
793-
* Resolve prefix containing relative references (../ or ./)
793+
* Resolve path containing relative references (../ or ./)
794794
* to canonical path.
795-
* @param prefix FujiNet path such as TNFS://myhost/path/to/here/
795+
* @param path FujiNet path such as TNFS://myhost/path/to/here/
796+
* or tnfs://myhost/some/filename.ext
796797
*/
797-
std::string util_get_canonical_path(std::string prefix)
798+
std::string util_get_canonical_path(std::string path)
798799
{
800+
bool is_last_slash = (path.back() == '/') ? true : false;
801+
799802
std::size_t proto_host_len;
800803

801804
// stack to store the file's names.
802-
std::stack<string> st;
805+
std::stack<std::string> st;
803806

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

813816
// advance beyond protocol and hostname
814-
proto_host_len = prefix.find("://");
817+
proto_host_len = path.find("://");
815818

816-
if (proto_host_len > 0)
819+
// If protocol delimiter "://" is found, skip over the protocol
820+
if (proto_host_len < std::string::npos)
817821
{
818-
proto_host_len += 3;
819-
proto_host_len = prefix.find("/", proto_host_len) + 1;
822+
proto_host_len += 3; // "://" is 3 chars
823+
proto_host_len = path.find("/", proto_host_len) + 1;
824+
res.append(path.substr(0, proto_host_len));
825+
}
826+
else
827+
{
828+
proto_host_len = 0; // no protocol prefix and hostname
829+
// Preserve an absolute path if one is provided in the input
830+
if (!path.empty() && path[0] == '/')
831+
res = "/";
820832
}
821833

822-
res.append(prefix.substr(0, proto_host_len));
823-
824-
int len_prefix = prefix.length();
834+
int len_path = path.length();
825835

826-
// for (int i = proto_host_len-1; i < len_prefix; i++)
827-
for (int i = proto_host_len; i < len_prefix; i++)
836+
for (int i = proto_host_len; i < len_path; i++)
828837
{
829838
// we will clear the temporary string
830839
// every time to accommodate new directory
831840
// name or command.
832841
dir.clear();
833842

834843
// skip all the multiple '/' Eg. "/////""
835-
while (prefix[i] == '/')
844+
while (path[i] == '/')
836845
i++;
837846

838847
// stores directory's name("a", "b" etc.)
839848
// or commands("."/"..") into dir
840-
while (i < len_prefix && prefix[i] != '/')
849+
while (i < len_path && path[i] != '/')
841850
{
842-
dir.push_back(prefix[i]);
851+
dir.push_back(path[i]);
843852
i++;
844853
}
845854

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

866875
// a temporary stack (st1) which will contain
867876
// the reverse of original stack(st).
868-
std::stack<string> st1;
877+
std::stack<std::string> st1;
869878
while (!st.empty())
870879
{
871880
st1.push(st.top());
@@ -888,7 +897,7 @@ std::string util_get_canonical_path(std::string prefix)
888897
}
889898

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

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

0 commit comments

Comments
 (0)