Files
brave-core/components/ipfs/ipfs_utils.cc
T
Claudio DeSouza 13a2651e70 [cr143] GURL::*_piece() removed
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}
2025-11-18 11:18:46 -05:00

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