1/*
2 * Copyright (C) 2006 Alexey Proskuryakov <ap@webkit.org>
3 * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com>
4 * Copyright (C) 2013, 2016 Apple Inc. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
16 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
19 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#pragma once
29
30#include <wtf/Vector.h>
31#include <wtf/text/CString.h>
32#include <wtf/text/WTFString.h>
33
34namespace WTF {
35
36enum Base64EncodePolicy {
37 Base64DoNotInsertLFs,
38 Base64InsertLFs,
39 Base64URLPolicy // No padding, no LFs.
40};
41
42enum Base64DecodeOptions {
43 Base64Default = 0,
44 Base64ValidatePadding = 1 << 0,
45 Base64IgnoreSpacesAndNewLines = 1 << 1,
46};
47
48class SignedOrUnsignedCharVectorAdapter {
49public:
50 SignedOrUnsignedCharVectorAdapter(Vector<char>& vector)
51 : m_isSigned(true)
52 {
53 m_vector.c = &vector;
54 }
55 SignedOrUnsignedCharVectorAdapter(Vector<uint8_t>& vector)
56 : m_isSigned(false)
57 {
58 m_vector.u = &vector;
59 }
60
61 uint8_t* data()
62 {
63 if (m_isSigned)
64 return reinterpret_cast<uint8_t*>(m_vector.c->data());
65 return m_vector.u->data();
66 }
67
68 size_t size() const
69 {
70 if (m_isSigned)
71 return m_vector.c->size();
72 return m_vector.u->size();
73 }
74
75 void clear()
76 {
77 if (m_isSigned) {
78 m_vector.c->clear();
79 return;
80 }
81 m_vector.u->clear();
82 }
83
84 void grow(size_t size)
85 {
86 if (m_isSigned) {
87 m_vector.c->grow(size);
88 return;
89 }
90 m_vector.u->grow(size);
91 }
92
93 void shrink(size_t size)
94 {
95 if (m_isSigned) {
96 m_vector.c->shrink(size);
97 return;
98 }
99 m_vector.u->shrink(size);
100 }
101
102 uint8_t& operator[](size_t position) { return data()[position]; }
103
104private:
105 bool m_isSigned;
106 union {
107 Vector<char>* c;
108 Vector<uint8_t>* u;
109 } m_vector;
110};
111
112class ConstSignedOrUnsignedCharVectorAdapter {
113public:
114 ConstSignedOrUnsignedCharVectorAdapter(const Vector<char>& vector)
115 : m_isSigned(false)
116 {
117 m_vector.c = &vector;
118 }
119 ConstSignedOrUnsignedCharVectorAdapter(const Vector<uint8_t>& vector)
120 : m_isSigned(true)
121 {
122 m_vector.u = &vector;
123 }
124
125 const uint8_t* data() const
126 {
127 if (m_isSigned)
128 return reinterpret_cast<const uint8_t*>(m_vector.c->data());
129 return m_vector.u->data();
130 }
131 size_t size() const
132 {
133 if (m_isSigned)
134 return m_vector.c->size();
135 return m_vector.u->size();
136 }
137
138private:
139 bool m_isSigned;
140 union {
141 const Vector<char>* c;
142 const Vector<uint8_t>* u;
143 } m_vector;
144};
145
146WTF_EXPORT_PRIVATE void base64Encode(const void*, unsigned, Vector<char>&, Base64EncodePolicy = Base64DoNotInsertLFs);
147void base64Encode(ConstSignedOrUnsignedCharVectorAdapter, Vector<char>&, Base64EncodePolicy = Base64DoNotInsertLFs);
148void base64Encode(const CString&, Vector<char>&, Base64EncodePolicy = Base64DoNotInsertLFs);
149WTF_EXPORT_PRIVATE String base64Encode(const void*, unsigned, Base64EncodePolicy = Base64DoNotInsertLFs);
150String base64Encode(ConstSignedOrUnsignedCharVectorAdapter, Base64EncodePolicy = Base64DoNotInsertLFs);
151String base64Encode(const CString&, Base64EncodePolicy = Base64DoNotInsertLFs);
152
153WTF_EXPORT_PRIVATE bool base64Decode(const String&, SignedOrUnsignedCharVectorAdapter, unsigned options = Base64Default);
154WTF_EXPORT_PRIVATE bool base64Decode(StringView, SignedOrUnsignedCharVectorAdapter, unsigned options = Base64Default);
155WTF_EXPORT_PRIVATE bool base64Decode(const Vector<char>&, SignedOrUnsignedCharVectorAdapter, unsigned options = Base64Default);
156WTF_EXPORT_PRIVATE bool base64Decode(const char*, unsigned, SignedOrUnsignedCharVectorAdapter, unsigned options = Base64Default);
157
158inline void base64Encode(ConstSignedOrUnsignedCharVectorAdapter in, Vector<char>& out, Base64EncodePolicy policy)
159{
160 base64Encode(in.data(), in.size(), out, policy);
161}
162
163inline void base64Encode(const CString& in, Vector<char>& out, Base64EncodePolicy policy)
164{
165 base64Encode(in.data(), in.length(), out, policy);
166}
167
168inline String base64Encode(ConstSignedOrUnsignedCharVectorAdapter in, Base64EncodePolicy policy)
169{
170 return base64Encode(in.data(), in.size(), policy);
171}
172
173inline String base64Encode(const CString& in, Base64EncodePolicy policy)
174{
175 return base64Encode(in.data(), in.length(), policy);
176}
177
178// ======================================================================================
179// All the same functions modified for base64url, as defined in RFC 4648.
180// This format uses '-' and '_' instead of '+' and '/' respectively.
181// ======================================================================================
182
183WTF_EXPORT_PRIVATE void base64URLEncode(const void*, unsigned, Vector<char>&);
184void base64URLEncode(ConstSignedOrUnsignedCharVectorAdapter, Vector<char>&);
185void base64URLEncode(const CString&, Vector<char>&);
186
187WTF_EXPORT_PRIVATE String base64URLEncode(const void*, unsigned);
188String base64URLEncode(ConstSignedOrUnsignedCharVectorAdapter);
189String base64URLEncode(const CString&);
190
191WTF_EXPORT_PRIVATE bool base64URLDecode(const String&, SignedOrUnsignedCharVectorAdapter);
192WTF_EXPORT_PRIVATE bool base64URLDecode(StringView, SignedOrUnsignedCharVectorAdapter);
193WTF_EXPORT_PRIVATE bool base64URLDecode(const Vector<char>&, SignedOrUnsignedCharVectorAdapter);
194WTF_EXPORT_PRIVATE bool base64URLDecode(const char*, unsigned, SignedOrUnsignedCharVectorAdapter);
195
196inline void base64URLEncode(ConstSignedOrUnsignedCharVectorAdapter in, Vector<char>& out)
197{
198 base64URLEncode(in.data(), in.size(), out);
199}
200
201inline void base64URLEncode(const CString& in, Vector<char>& out)
202{
203 base64URLEncode(in.data(), in.length(), out);
204}
205
206inline String base64URLEncode(ConstSignedOrUnsignedCharVectorAdapter in)
207{
208 return base64URLEncode(in.data(), in.size());
209}
210
211inline String base64URLEncode(const CString& in)
212{
213 return base64URLEncode(in.data(), in.length());
214}
215
216template<typename CharacterType> static inline bool isBase64OrBase64URLCharacter(CharacterType c)
217{
218 return isASCIIAlphanumeric(c) || c == '+' || c == '/' || c == '-' || c == '_';
219}
220
221} // namespace WTF
222
223using WTF::Base64EncodePolicy;
224using WTF::Base64DoNotInsertLFs;
225using WTF::Base64InsertLFs;
226using WTF::Base64ValidatePadding;
227using WTF::Base64IgnoreSpacesAndNewLines;
228using WTF::base64Encode;
229using WTF::base64Decode;
230using WTF::base64URLDecode;
231using WTF::isBase64OrBase64URLCharacter;
232