Skip to content

Commit

Permalink
Add CondaURL::pretty_str (#2830)
Browse files Browse the repository at this point in the history
  • Loading branch information
AntoinePrv authored Sep 15, 2023
1 parent 7560073 commit ddbeb53
Show file tree
Hide file tree
Showing 6 changed files with 265 additions and 32 deletions.
42 changes: 35 additions & 7 deletions libmamba/include/mamba/specs/conda_url.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,19 @@ namespace mamba::specs

public:

using Base::StripScheme;
using Base::HidePassword;
using Base::Encode;
using Base::Decode;
using StripScheme = util::detail::StripScheme;
using HideConfidential = util::detail::HideConfidential;
using Encode = util::detail::Encode;
using Decode = util::detail::Decode;

using Base::https;
using Base::localhost;
inline static constexpr std::string_view token_prefix = "/t/";

[[nodiscard]] static auto parse(std::string_view url) -> CondaURL;

/** Create a local URL. */
CondaURL() = default;
explicit CondaURL(util::URL&& url);
explicit CondaURL(const util::URL& url);

using Base::scheme;
using Base::set_scheme;
Expand All @@ -51,6 +51,7 @@ namespace mamba::specs
using Base::clear_port;
using Base::authority;
using Base::path;
using Base::pretty_path;
using Base::set_path;
using Base::clear_path;
using Base::append_path;
Expand Down Expand Up @@ -132,10 +133,37 @@ namespace mamba::specs
/** Clear the package and return true if it exists, otherwise return ``false``. */
auto clear_package() -> bool;

using Base::str;

/**
* Return the full decoded url.
*
* Due to decoding, the outcome may not be understood by parser and usable to reach an
* asset.
* @param strip_scheme If true, remove the scheme and "localhost" on file URI.
* @param rstrip_path If non-null, remove the given charaters at the end of the path.
* @param hide_confidential If true, hide password and tokens in the decoded string.
*/
[[nodiscard]] auto pretty_str(
StripScheme strip_scheme = StripScheme::no,
char rstrip_path = 0,
HideConfidential hide_confidential = HideConfidential::no
) const -> std::string;


private:

explicit CondaURL(URL&& url);
void set_platform_no_check_input(std::string_view platform);

friend auto operator==(const CondaURL&, const CondaURL&) -> bool;
};

/** Compare two CondaURL. */
auto operator==(const CondaURL& a, const CondaURL& b) -> bool;
auto operator!=(const CondaURL& a, const CondaURL& b) -> bool;

/** A functional equivalent to ``CondaURL::append_path``. */
auto operator/(const CondaURL& url, std::string_view subpath) -> CondaURL;
auto operator/(CondaURL&& url, std::string_view subpath) -> CondaURL;
}
#endif
65 changes: 49 additions & 16 deletions libmamba/include/mamba/util/url.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,43 @@

namespace mamba::util
{
namespace detail
{
// Working around MSVC limitation on private inheritance + using directive

enum class StripScheme : bool
{
no,
yes
};

enum class HideConfidential : bool
{
no,
yes
};

struct Encode
{
inline static constexpr struct yes_type
{
} yes = {};
inline static constexpr struct no_type
{
} no = {};
};

struct Decode
{
inline static constexpr struct yes_type
{
} yes = {};
inline static constexpr struct no_type
{
} no = {};
};
}

/**
* Class representing a URL.
*
Expand All @@ -21,20 +58,10 @@ namespace mamba::util
{
public:

// clang-format off
enum class StripScheme : bool { no, yes };
enum class HidePassword : bool { no, yes };
struct Encode
{
inline static constexpr struct yes_type {} yes = {};
inline static constexpr struct no_type {} no = {};
};
struct Decode
{
inline static constexpr struct yes_type {} yes = {};
inline static constexpr struct no_type {} no = {};
};
// clang-format on
using StripScheme = detail::StripScheme;
using HideConfidential = detail::HideConfidential;
using Encode = detail::Encode;
using Decode = detail::Decode;

inline static constexpr std::string_view https = "https";
inline static constexpr std::string_view localhost = "localhost";
Expand Down Expand Up @@ -197,14 +224,20 @@ namespace mamba::util
* asset.
* @param strip_scheme If true, remove the scheme and "localhost" on file URI.
* @param rstrip_path If non-null, remove the given charaters at the end of the path.
* @param hide_password If true, hide password in the decoded string.
* @param hide_confidential If true, hide password in the decoded string.
*/
[[nodiscard]] auto pretty_str(
StripScheme strip_scheme = StripScheme::no,
char rstrip_path = 0,
HidePassword hide_password = HidePassword::no
HideConfidential hide_confidential = HideConfidential::no
) const -> std::string;

protected:

[[nodiscard]] auto
pretty_str_path(StripScheme strip_scheme = StripScheme::no, char rstrip_path = 0) const
-> std::string;

private:

std::string m_scheme = std::string(https);
Expand Down
80 changes: 77 additions & 3 deletions libmamba/src/specs/conda_url.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@ namespace mamba::specs
{
}

CondaURL::CondaURL(const util::URL& url)
: CondaURL(URL(url))
{
}

auto CondaURL::parse(std::string_view url) -> CondaURL
{
return CondaURL(URL::parse(url));
Expand All @@ -98,6 +103,23 @@ namespace mamba::specs
return std::string_view(l_path).substr(pos + token_prefix.size(), token_len);
}

namespace
{
void set_token_no_check_input_impl(
std::string& path,
std::size_t pos,
std::size_t len,
std::string_view token
)
{
static constexpr auto npos = std::string_view::npos;

assert(CondaURL::token_prefix.size() < len);
const auto token_len = (len != npos) ? len - CondaURL::token_prefix.size() : npos;
path.replace(pos + CondaURL::token_prefix.size(), token_len, token);
}
}

void CondaURL::set_token(std::string_view token)
{
static constexpr auto npos = std::string_view::npos;
Expand All @@ -113,10 +135,8 @@ namespace mamba::specs
fmt::format(R"(No token template in orignial path "{}")", path(Decode::no))
);
}
assert(token_prefix.size() < len);
std::string l_path = clear_path(); // percent encoded
const auto token_len = (len != npos) ? len - token_prefix.size() : npos;
l_path.replace(pos + token_prefix.size(), token_len, token);
set_token_no_check_input_impl(l_path, pos, len, token);
set_path(std::move(l_path), Encode::no);
}

Expand Down Expand Up @@ -284,4 +304,58 @@ namespace mamba::specs
}
return false;
}

auto
CondaURL::pretty_str(StripScheme strip_scheme, char rstrip_path, HideConfidential hide_confifential) const
-> std::string
{
std::string computed_path = pretty_str_path(strip_scheme, rstrip_path);

if (hide_confifential == HideConfidential::yes)
{
const auto [pos, len] = find_token_and_prefix(computed_path);
if ((pos < std::string::npos) && (len > 0))
{
set_token_no_check_input_impl(computed_path, pos, len, "*****");
}
}

return util::concat(
(strip_scheme == StripScheme::no) ? scheme() : "",
(strip_scheme == StripScheme::no) ? "://" : "",
user(Decode::yes),
password(Decode::no).empty() ? "" : ":",
(hide_confifential == HideConfidential::no) ? password(Decode::yes) : "*****",
user(Decode::no).empty() ? "" : "@",
host(Decode::yes),
port().empty() ? "" : ":",
port(),
computed_path,
query().empty() ? "" : "?",
query(),
fragment().empty() ? "" : "#",
fragment()
);
}

auto operator==(const CondaURL& a, const CondaURL& b) -> bool
{
return static_cast<const util::URL&>(a) == static_cast<const util::URL&>(b);
}

auto operator!=(const CondaURL& a, const CondaURL& b) -> bool
{
return !(a == b);
}

auto operator/(const CondaURL& url, std::string_view subpath) -> CondaURL
{
return CondaURL(url) / subpath;
}

auto operator/(CondaURL&& url, std::string_view subpath) -> CondaURL
{
url.append_path(subpath);
return std::move(url);
}
}
13 changes: 9 additions & 4 deletions libmamba/src/util/url.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -484,8 +484,7 @@ namespace mamba::util
);
}

auto URL::pretty_str(StripScheme strip_scheme, char rstrip_path, HidePassword hide_password) const
-> std::string
auto URL::pretty_str_path(StripScheme strip_scheme, char rstrip_path) const -> std::string
{
std::string computed_path = {};
// When stripping file scheme, not showing leading '/' for Windows path with drive
Expand All @@ -498,18 +497,24 @@ namespace mamba::util
computed_path = path(Decode::yes);
}
computed_path = util::rstrip(computed_path, rstrip_path);
return computed_path;
}

auto
URL::pretty_str(StripScheme strip_scheme, char rstrip_path, HideConfidential hide_confidential) const
-> std::string
{
return util::concat(
(strip_scheme == StripScheme::no) ? m_scheme : "",
(strip_scheme == StripScheme::no) ? "://" : "",
user(Decode::yes),
m_password.empty() ? "" : ":",
(hide_password == HidePassword::no) ? password(Decode::yes) : "*****",
(hide_confidential == HideConfidential::no) ? password(Decode::yes) : "*****",
m_user.empty() ? "" : "@",
host(Decode::yes),
m_port.empty() ? "" : ":",
m_port,
computed_path,
pretty_str_path(strip_scheme, rstrip_path),
m_query.empty() ? "" : "?",
m_query,
m_fragment.empty() ? "" : "#",
Expand Down
Loading

0 comments on commit ddbeb53

Please sign in to comment.