All the main methods now return a string_piece, which made the `_piece` functions redundant. Chromium changes: https://chromium.googlesource.com/chromium/src/+/566074ac1aee3a91cbec0d2eac3120b7dd71860b commit 566074ac1aee3a91cbec0d2eac3120b7dd71860b Author: Charlie Harrison <csharrison@chromium.org> Date: Mon Oct 6 19:18:05 2025 -0700 Remove GURL::*_piece() method There are no more users of this deprecated and misnamed API. This completes phase 1.5 of crbug.com/448174617. Bug: 448174617 Change-Id: I82918ec4ec10b68729c31cb36487c7cb02ad0b56 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7008912 Reviewed-by: Daniel Cheng <dcheng@chromium.org> Commit-Queue: Daniel Cheng <dcheng@chromium.org> Owners-Override: Charlie Harrison <csharrison@chromium.org> Owners-Override: Daniel Cheng <dcheng@chromium.org> Cr-Commit-Position: refs/heads/main@{#1525986}
152 lines
4.7 KiB
C++
152 lines
4.7 KiB
C++
/* Copyright (c) 2020 The Brave Authors. All rights reserved.
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#include "brave/components/ipfs/ipfs_utils.h"
|
|
|
|
#include <string>
|
|
#include <string_view>
|
|
|
|
#include "base/check.h"
|
|
#include "base/check_op.h"
|
|
#include "base/logging.h"
|
|
#include "base/strings/strcat.h"
|
|
#include "base/strings/string_util.h"
|
|
#include "brave/components/filecoin/rs/src/lib.rs.h"
|
|
#include "components/base32/base32.h"
|
|
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
|
|
#include "net/base/url_util.h"
|
|
#include "third_party/abseil-cpp/absl/strings/str_format.h"
|
|
#include "url/gurl.h"
|
|
#include "url/origin.h"
|
|
|
|
namespace {
|
|
constexpr char kIPFSScheme[] = "ipfs";
|
|
constexpr char kIPNSScheme[] = "ipns";
|
|
|
|
// Ipfs codes from multicodec table
|
|
// https://github.com/multiformats/multicodec/blob/master/table.csv
|
|
const int64_t kIpfsNSCodec = 0xE3;
|
|
const int64_t kIpnsNSCodec = 0xE5;
|
|
|
|
// Decodes a varint from the given string piece into the given int64_t. Returns
|
|
// remaining span if the string had a valid varint (where a byte was found with
|
|
// it's top bit set).
|
|
base::span<const uint8_t> DecodeVarInt(base::span<const uint8_t> from,
|
|
int64_t* into) {
|
|
auto it = from.begin();
|
|
int shift = 0;
|
|
uint64_t ret = 0;
|
|
do {
|
|
if (it == from.end()) {
|
|
return {};
|
|
}
|
|
|
|
// Shifting 64 or more bits is undefined behavior.
|
|
DCHECK_LT(shift, 64);
|
|
unsigned char c = *it;
|
|
ret |= static_cast<uint64_t>(c & 0x7f) << shift;
|
|
shift += 7;
|
|
} while (*it++ & 0x80);
|
|
*into = static_cast<int64_t>(ret);
|
|
return from.subspan(static_cast<size_t>(std::distance(from.begin(), it)));
|
|
}
|
|
|
|
// Extracts cid and path from ipfs URLs like:
|
|
// [scheme]://[cid][.gateway][/path]
|
|
// [scheme]://[cid][/path]
|
|
bool ParseCIDAndPathFromIPFSUrl(const GURL& url,
|
|
std::string* cid,
|
|
std::string* path) {
|
|
if (!url.SchemeIs(kIPFSScheme) && !url.SchemeIs(kIPNSScheme)) {
|
|
return false;
|
|
}
|
|
if (url.host().empty() && url.path().find("/") != std::string::npos) {
|
|
return false;
|
|
}
|
|
DCHECK(cid);
|
|
DCHECK(path);
|
|
// In the case of a URL like ipfs://[cid]/wiki/Vincent_van_Gogh.html
|
|
// host is [cid] and path is /wiki/Vincent_van_Gogh.html
|
|
if (!url.host().empty()) {
|
|
*cid = url.host();
|
|
*path = url.path();
|
|
} else {
|
|
*cid = url.path();
|
|
*path = "";
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// Simple CID validation based on multibase table.
|
|
bool IsValidCID(const std::string& cid) {
|
|
if (cid.empty()) {
|
|
return false;
|
|
}
|
|
return filecoin::is_valid_cid(cid);
|
|
}
|
|
|
|
} // namespace
|
|
|
|
namespace ipfs {
|
|
bool TranslateIPFSURI(const GURL& url, GURL* new_url, bool use_subdomain) {
|
|
const GURL gateway_url{kDefaultPublicGateway};
|
|
std::string cid, path;
|
|
if (!ParseCIDAndPathFromIPFSUrl(url, &cid, &path)) {
|
|
return false;
|
|
}
|
|
bool ipfs_scheme = url.scheme() == kIPFSScheme;
|
|
bool ipns_scheme = url.scheme() == kIPNSScheme;
|
|
if ((ipfs_scheme && IsValidCID(cid)) || ipns_scheme) {
|
|
// new_url would be:
|
|
// https://dweb.link/ipfs/[cid]//wiki/Vincent_van_Gogh.html
|
|
if (new_url) {
|
|
GURL::Replacements replacements;
|
|
replacements.SetSchemeStr(gateway_url.scheme());
|
|
replacements.SetPortStr(gateway_url.port());
|
|
std::string new_host;
|
|
std::string new_path = path;
|
|
if (use_subdomain) {
|
|
new_host = absl::StrFormat(
|
|
"%s.%s.%s", cid, ipfs_scheme ? "ipfs" : "ipns", gateway_url.host());
|
|
} else {
|
|
new_host = std::string(gateway_url.host());
|
|
new_path = base::StrCat({(ipfs_scheme ? "ipfs/" : "ipns/"), cid, path});
|
|
}
|
|
replacements.SetHostStr(new_host);
|
|
replacements.SetPathStr(new_path);
|
|
*new_url = url.ReplaceComponents(replacements);
|
|
VLOG(1) << "[IPFS] " << __func__ << " new URL: " << *new_url;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
GURL ContentHashToCIDv1URL(base::span<const uint8_t> contenthash) {
|
|
int64_t code = 0;
|
|
contenthash = DecodeVarInt(contenthash, &code);
|
|
if (contenthash.empty()) {
|
|
return GURL();
|
|
}
|
|
if (code != kIpnsNSCodec && code != kIpfsNSCodec) {
|
|
return GURL();
|
|
}
|
|
std::string encoded = base32::Base32Encode(contenthash);
|
|
if (encoded.empty()) {
|
|
return GURL();
|
|
}
|
|
std::string trimmed;
|
|
base::TrimString(encoded, "=", &trimmed);
|
|
std::string lowercase = base::ToLowerASCII(trimmed);
|
|
// multibase format <base-encoding-character><base-encoded-data>
|
|
// https://github.com/multiformats/multibase/blob/master/multibase.csv
|
|
std::string cidv1 = "b" + lowercase;
|
|
std::string scheme = (code == kIpnsNSCodec) ? kIPNSScheme : kIPFSScheme;
|
|
return GURL(scheme + "://" + cidv1);
|
|
}
|
|
|
|
} // namespace ipfs
|