1 | /* |
2 | * Copyright (C) 2006 Alexey Proskuryakov <[email protected]> |
3 | * Copyright (C) 2010 Patrick Gansterer <[email protected]> |
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 | |
34 | namespace WTF { |
35 | |
36 | enum Base64EncodePolicy { |
37 | Base64DoNotInsertLFs, |
38 | Base64InsertLFs, |
39 | Base64URLPolicy // No padding, no LFs. |
40 | }; |
41 | |
42 | enum Base64DecodeOptions { |
43 | Base64Default = 0, |
44 | Base64ValidatePadding = 1 << 0, |
45 | Base64IgnoreSpacesAndNewLines = 1 << 1, |
46 | }; |
47 | |
48 | class SignedOrUnsignedCharVectorAdapter { |
49 | public: |
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 | |
104 | private: |
105 | bool m_isSigned; |
106 | union { |
107 | Vector<char>* c; |
108 | Vector<uint8_t>* u; |
109 | } m_vector; |
110 | }; |
111 | |
112 | class ConstSignedOrUnsignedCharVectorAdapter { |
113 | public: |
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 | |
138 | private: |
139 | bool m_isSigned; |
140 | union { |
141 | const Vector<char>* c; |
142 | const Vector<uint8_t>* u; |
143 | } m_vector; |
144 | }; |
145 | |
146 | WTF_EXPORT_PRIVATE void base64Encode(const void*, unsigned, Vector<char>&, Base64EncodePolicy = Base64DoNotInsertLFs); |
147 | void base64Encode(ConstSignedOrUnsignedCharVectorAdapter, Vector<char>&, Base64EncodePolicy = Base64DoNotInsertLFs); |
148 | void base64Encode(const CString&, Vector<char>&, Base64EncodePolicy = Base64DoNotInsertLFs); |
149 | WTF_EXPORT_PRIVATE String base64Encode(const void*, unsigned, Base64EncodePolicy = Base64DoNotInsertLFs); |
150 | String base64Encode(ConstSignedOrUnsignedCharVectorAdapter, Base64EncodePolicy = Base64DoNotInsertLFs); |
151 | String base64Encode(const CString&, Base64EncodePolicy = Base64DoNotInsertLFs); |
152 | |
153 | WTF_EXPORT_PRIVATE bool base64Decode(const String&, SignedOrUnsignedCharVectorAdapter, unsigned options = Base64Default); |
154 | WTF_EXPORT_PRIVATE bool base64Decode(StringView, SignedOrUnsignedCharVectorAdapter, unsigned options = Base64Default); |
155 | WTF_EXPORT_PRIVATE bool base64Decode(const Vector<char>&, SignedOrUnsignedCharVectorAdapter, unsigned options = Base64Default); |
156 | WTF_EXPORT_PRIVATE bool base64Decode(const char*, unsigned, SignedOrUnsignedCharVectorAdapter, unsigned options = Base64Default); |
157 | |
158 | inline void base64Encode(ConstSignedOrUnsignedCharVectorAdapter in, Vector<char>& out, Base64EncodePolicy policy) |
159 | { |
160 | base64Encode(in.data(), in.size(), out, policy); |
161 | } |
162 | |
163 | inline void base64Encode(const CString& in, Vector<char>& out, Base64EncodePolicy policy) |
164 | { |
165 | base64Encode(in.data(), in.length(), out, policy); |
166 | } |
167 | |
168 | inline String base64Encode(ConstSignedOrUnsignedCharVectorAdapter in, Base64EncodePolicy policy) |
169 | { |
170 | return base64Encode(in.data(), in.size(), policy); |
171 | } |
172 | |
173 | inline 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 | |
183 | WTF_EXPORT_PRIVATE void base64URLEncode(const void*, unsigned, Vector<char>&); |
184 | void base64URLEncode(ConstSignedOrUnsignedCharVectorAdapter, Vector<char>&); |
185 | void base64URLEncode(const CString&, Vector<char>&); |
186 | |
187 | WTF_EXPORT_PRIVATE String base64URLEncode(const void*, unsigned); |
188 | String base64URLEncode(ConstSignedOrUnsignedCharVectorAdapter); |
189 | String base64URLEncode(const CString&); |
190 | |
191 | WTF_EXPORT_PRIVATE bool base64URLDecode(const String&, SignedOrUnsignedCharVectorAdapter); |
192 | WTF_EXPORT_PRIVATE bool base64URLDecode(StringView, SignedOrUnsignedCharVectorAdapter); |
193 | WTF_EXPORT_PRIVATE bool base64URLDecode(const Vector<char>&, SignedOrUnsignedCharVectorAdapter); |
194 | WTF_EXPORT_PRIVATE bool base64URLDecode(const char*, unsigned, SignedOrUnsignedCharVectorAdapter); |
195 | |
196 | inline void base64URLEncode(ConstSignedOrUnsignedCharVectorAdapter in, Vector<char>& out) |
197 | { |
198 | base64URLEncode(in.data(), in.size(), out); |
199 | } |
200 | |
201 | inline void base64URLEncode(const CString& in, Vector<char>& out) |
202 | { |
203 | base64URLEncode(in.data(), in.length(), out); |
204 | } |
205 | |
206 | inline String base64URLEncode(ConstSignedOrUnsignedCharVectorAdapter in) |
207 | { |
208 | return base64URLEncode(in.data(), in.size()); |
209 | } |
210 | |
211 | inline String base64URLEncode(const CString& in) |
212 | { |
213 | return base64URLEncode(in.data(), in.length()); |
214 | } |
215 | |
216 | template<typename CharacterType> static inline bool isBase64OrBase64URLCharacter(CharacterType c) |
217 | { |
218 | return isASCIIAlphanumeric(c) || c == '+' || c == '/' || c == '-' || c == '_'; |
219 | } |
220 | |
221 | } // namespace WTF |
222 | |
223 | using WTF::Base64EncodePolicy; |
224 | using WTF::Base64DoNotInsertLFs; |
225 | using WTF::Base64InsertLFs; |
226 | using WTF::Base64ValidatePadding; |
227 | using WTF::Base64IgnoreSpacesAndNewLines; |
228 | using WTF::base64Encode; |
229 | using WTF::base64Decode; |
230 | using WTF::base64URLDecode; |
231 | using WTF::isBase64OrBase64URLCharacter; |
232 | |