File: base64.cc

package info (click to toggle)
chromium 138.0.7204.183-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,908 kB
  • sloc: cpp: 34,937,088; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (140 lines) | stat: -rw-r--r-- 5,211 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/*
   Copyright (C) 2000-2001 Dawit Alemayehu <adawit@kde.org>
   Copyright (C) 2006 Alexey Proskuryakov <ap@webkit.org>
   Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
   Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com>

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU Lesser General Public License (LGPL)
   version 2 as published by the Free Software Foundation.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU Library General Public
   License along with this program; if not, write to the Free Software
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
   USA.

   This code is based on the java implementation in HTTPClient
   package by Ronald Tschalaer Copyright (C) 1996-1999.
*/

#include "third_party/blink/renderer/platform/wtf/text/base64.h"

#include <limits.h>

#include "third_party/blink/renderer/platform/wtf/text/string_buffer.h"
#include "third_party/blink/renderer/platform/wtf/text/string_utf8_adaptor.h"
#include "third_party/modp_b64/modp_b64.h"

namespace WTF {

namespace {

// https://infra.spec.whatwg.org/#ascii-whitespace
// Matches the definition of IsHTMLSpace in html_parser_idioms.h.
template <typename CharType>
bool IsAsciiWhitespace(CharType character) {
  return character <= ' ' &&
         (character == ' ' || character == '\n' || character == '\t' ||
          character == '\r' || character == '\f');
}

ModpDecodePolicy GetModpPolicy(Base64DecodePolicy policy) {
  switch (policy) {
    case Base64DecodePolicy::kForgiving:
      return ModpDecodePolicy::kForgiving;
    case Base64DecodePolicy::kNoPaddingValidation:
      return ModpDecodePolicy::kNoPaddingValidation;
  }
}

// Invokes modp_b64 without stripping whitespace.
bool Base64DecodeRaw(const StringView& in,
                     Vector<uint8_t>& out,
                     Base64DecodePolicy policy) {
  // Using StringUTF8Adaptor means we avoid allocations if the string is 8-bit
  // ascii, which is likely given that base64 is required to be ascii.
  StringUTF8Adaptor adaptor(in);
  out.resize(modp_b64_decode_len(adaptor.size()));
  base::span<char> write_buffer = base::as_writable_chars(base::span(out));
  size_t output_size = modp_b64_decode(write_buffer.data(), adaptor.data(),
                                       adaptor.size(), GetModpPolicy(policy));
  if (output_size == MODP_B64_ERROR)
    return false;

  out.resize(output_size);
  return true;
}

}  // namespace

String Base64Encode(base::span<const uint8_t> data) {
  size_t encode_len = modp_b64_encode_data_len(data.size());
  CHECK_LE(data.size(), MODP_B64_MAX_INPUT_LEN);
  StringBuffer<LChar> result(encode_len);
  if (encode_len == 0)
    return String();
  const size_t output_size = modp_b64_encode_data(
      reinterpret_cast<char*>(result.Characters()),
      reinterpret_cast<const char*>(data.data()), data.size());
  DCHECK_EQ(output_size, encode_len);
  return result.Release();
}

void Base64Encode(base::span<const uint8_t> data, Vector<char>& out) {
  size_t encode_len = modp_b64_encode_data_len(data.size());
  CHECK_LE(data.size(), MODP_B64_MAX_INPUT_LEN);
  if (encode_len == 0) {
    out.clear();
    return;
  }
  out.resize(encode_len);
  const size_t output_size = modp_b64_encode_data(
      out.data(), reinterpret_cast<const char*>(data.data()), data.size());
  DCHECK_EQ(output_size, encode_len);
}

bool Base64Decode(const StringView& in,
                  Vector<uint8_t>& out,
                  Base64DecodePolicy policy) {
  switch (policy) {
    case Base64DecodePolicy::kForgiving: {
      // https://infra.spec.whatwg.org/#forgiving-base64-decode
      // Step 1 is to remove all whitespace. However, checking for whitespace
      // slows down the "happy" path. Since any whitespace will fail normal
      // decoding from modp_b64_decode, just try again if we detect a failure.
      // This shouldn't be much slower for whitespace inputs.
      //
      // TODO(csharrison): Most callers use String inputs so ToString() should
      // be fast. Still, we should add a RemoveCharacters method to StringView
      // to avoid a double allocation for non-String-backed StringViews.
      return Base64DecodeRaw(in, out, policy) ||
             Base64DecodeRaw(in.ToString().RemoveCharacters(&IsAsciiWhitespace),
                             out, policy);
    }
    case Base64DecodePolicy::kNoPaddingValidation: {
      return Base64DecodeRaw(in, out, policy);
    }
  }
}

bool Base64UnpaddedURLDecode(const String& in, Vector<uint8_t>& out) {
  if (in.Contains('+') || in.Contains('/') || in.Contains('='))
    return false;

  return Base64Decode(NormalizeToBase64(in), out);
}

String Base64URLEncode(base::span<const uint8_t> data) {
  return Base64Encode(data).Replace('+', '-').Replace('/', '_');
}

String NormalizeToBase64(const String& encoding) {
  return String(encoding).Replace('-', '+').Replace('_', '/');
}

}  // namespace WTF