summaryrefslogtreecommitdiff
path: root/Source/WTF/wtf/text/Base64.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WTF/wtf/text/Base64.cpp')
-rw-r--r--Source/WTF/wtf/text/Base64.cpp76
1 files changed, 50 insertions, 26 deletions
diff --git a/Source/WTF/wtf/text/Base64.cpp b/Source/WTF/wtf/text/Base64.cpp
index 2323f3fa3..714a7ead4 100644
--- a/Source/WTF/wtf/text/Base64.cpp
+++ b/Source/WTF/wtf/text/Base64.cpp
@@ -1,7 +1,7 @@
/*
Copyright (C) 2000-2001 Dawit Alemayehu <adawit@kde.org>
Copyright (C) 2006 Alexey Proskuryakov <ap@webkit.org>
- Copyright (C) 2007, 2008, 2013 Apple Inc. All rights reserved.
+ Copyright (C) 2007, 2008, 2013, 2016 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
@@ -92,7 +92,7 @@ static const char base64URLDecMap[128] = {
0x31, 0x32, 0x33, nonAlphabet, nonAlphabet, nonAlphabet, nonAlphabet, nonAlphabet
};
-static inline void base64EncodeInternal(const char* data, unsigned len, Vector<char>& out, Base64EncodePolicy policy, const char (&encodeMap)[64])
+static inline void base64EncodeInternal(const unsigned char* data, unsigned len, Vector<char>& out, Base64EncodePolicy policy, const char (&encodeMap)[64])
{
out.clear();
if (!len)
@@ -160,29 +160,29 @@ static inline void base64EncodeInternal(const char* data, unsigned len, Vector<c
String base64Encode(const void* data, unsigned length, Base64EncodePolicy policy)
{
Vector<char> result;
- base64EncodeInternal(static_cast<const char*>(data), length, result, policy, base64EncMap);
+ base64EncodeInternal(static_cast<const unsigned char*>(data), length, result, policy, base64EncMap);
return String(result.data(), result.size());
}
void base64Encode(const void* data, unsigned len, Vector<char>& out, Base64EncodePolicy policy)
{
- base64EncodeInternal(static_cast<const char*>(data), len, out, policy, base64EncMap);
+ base64EncodeInternal(static_cast<const unsigned char*>(data), len, out, policy, base64EncMap);
}
String base64URLEncode(const void* data, unsigned length)
{
Vector<char> result;
- base64EncodeInternal(static_cast<const char*>(data), length, result, Base64URLPolicy, base64URLEncMap);
+ base64EncodeInternal(static_cast<const unsigned char*>(data), length, result, Base64URLPolicy, base64URLEncMap);
return String(result.data(), result.size());
}
void base64URLEncode(const void* data, unsigned len, Vector<char>& out)
{
- base64EncodeInternal(static_cast<const char*>(data), len, out, Base64URLPolicy, base64URLEncMap);
+ base64EncodeInternal(static_cast<const unsigned char*>(data), len, out, Base64URLPolicy, base64URLEncMap);
}
template<typename T>
-static inline bool base64DecodeInternal(const T* data, unsigned length, Vector<char>& out, Base64DecodePolicy policy, const char (&decodeMap)[128])
+static inline bool base64DecodeInternal(const T* data, unsigned length, SignedOrUnsignedCharVectorAdapter& out, unsigned options, const char (&decodeMap)[128])
{
out.clear();
if (!length)
@@ -192,29 +192,47 @@ static inline bool base64DecodeInternal(const T* data, unsigned length, Vector<c
unsigned equalsSignCount = 0;
unsigned outLength = 0;
+ bool hadError = false;
for (unsigned idx = 0; idx < length; ++idx) {
unsigned ch = data[idx];
if (ch == '=') {
++equalsSignCount;
- // There should be no padding if length is a multiple of 4, and there
- // should never be more than 2 padding characters.
- if (policy == Base64FailOnInvalidCharacterOrExcessPadding && (length % 4 || equalsSignCount > 2))
- return false;
+ // There should never be more than 2 padding characters.
+ if (options & Base64ValidatePadding && equalsSignCount > 2) {
+ hadError = true;
+ break;
+ }
} else {
char decodedCharacter = ch < WTF_ARRAY_LENGTH(decodeMap) ? decodeMap[ch] : nonAlphabet;
if (decodedCharacter != nonAlphabet) {
- if (equalsSignCount)
- return false;
- out[outLength] = decodedCharacter;
- ++outLength;
- } else if (policy == Base64FailOnInvalidCharacterOrExcessPadding || policy == Base64FailOnInvalidCharacter || (policy == Base64IgnoreWhitespace && !isSpaceOrNewline(ch)))
- return false;
+ if (equalsSignCount) {
+ hadError = true;
+ break;
+ }
+ out[outLength++] = decodedCharacter;
+ } else if (!(options & Base64IgnoreSpacesAndNewLines) || !isSpaceOrNewline(ch)) {
+ hadError = true;
+ break;
+ }
}
}
+ // Make sure we shrink back the Vector before returning. outLength may be shorter than expected
+ // in case of error or in case of ignored spaces.
+ if (outLength < out.size())
+ out.shrink(outLength);
+
+ if (hadError)
+ return false;
+
if (!outLength)
return !equalsSignCount;
+ // The should be no padding if length is a multiple of 4.
+ // We use (outLength + equalsSignCount) instead of length because we don't want to account for ignored characters (i.e. spaces).
+ if (options & Base64ValidatePadding && equalsSignCount && (outLength + equalsSignCount) % 4)
+ return false;
+
// Valid data is (n * 4 + [0,2,3]) characters long.
if ((outLength % 4) == 1)
return false;
@@ -248,12 +266,15 @@ static inline bool base64DecodeInternal(const T* data, unsigned length, Vector<c
return true;
}
-bool base64Decode(const String& in, SignedOrUnsignedCharVectorAdapter out, Base64DecodePolicy policy)
+bool base64Decode(const String& in, SignedOrUnsignedCharVectorAdapter out, unsigned options)
{
- return base64DecodeInternal<UChar>(in.deprecatedCharacters(), in.length(), out, policy, base64DecMap);
+ unsigned length = in.length();
+ if (!length || in.is8Bit())
+ return base64DecodeInternal(in.characters8(), length, out, options, base64DecMap);
+ return base64DecodeInternal(in.characters16(), length, out, options, base64DecMap);
}
-bool base64Decode(const Vector<char>& in, SignedOrUnsignedCharVectorAdapter out, Base64DecodePolicy policy)
+bool base64Decode(const Vector<char>& in, SignedOrUnsignedCharVectorAdapter out, unsigned options)
{
out.clear();
@@ -261,17 +282,20 @@ bool base64Decode(const Vector<char>& in, SignedOrUnsignedCharVectorAdapter out,
if (in.size() > UINT_MAX)
return false;
- return base64DecodeInternal<char>(in.data(), in.size(), out, policy, base64DecMap);
+ return base64DecodeInternal(reinterpret_cast<const LChar*>(in.data()), in.size(), out, options, base64DecMap);
}
-bool base64Decode(const char* data, unsigned len, SignedOrUnsignedCharVectorAdapter out, Base64DecodePolicy policy)
+bool base64Decode(const char* data, unsigned len, SignedOrUnsignedCharVectorAdapter out, unsigned options)
{
- return base64DecodeInternal<char>(data, len, out, policy, base64DecMap);
+ return base64DecodeInternal(reinterpret_cast<const LChar*>(data), len, out, options, base64DecMap);
}
bool base64URLDecode(const String& in, SignedOrUnsignedCharVectorAdapter out)
{
- return base64DecodeInternal<UChar>(in.deprecatedCharacters(), in.length(), out, Base64FailOnInvalidCharacter, base64URLDecMap);
+ unsigned length = in.length();
+ if (!length || in.is8Bit())
+ return base64DecodeInternal(in.characters8(), length, out, Base64Default, base64URLDecMap);
+ return base64DecodeInternal(in.characters16(), length, out, Base64Default, base64URLDecMap);
}
bool base64URLDecode(const Vector<char>& in, SignedOrUnsignedCharVectorAdapter out)
@@ -282,12 +306,12 @@ bool base64URLDecode(const Vector<char>& in, SignedOrUnsignedCharVectorAdapter o
if (in.size() > UINT_MAX)
return false;
- return base64DecodeInternal<char>(in.data(), in.size(), out, Base64FailOnInvalidCharacter, base64URLDecMap);
+ return base64DecodeInternal(reinterpret_cast<const LChar*>(in.data()), in.size(), out, Base64Default, base64URLDecMap);
}
bool base64URLDecode(const char* data, unsigned len, SignedOrUnsignedCharVectorAdapter out)
{
- return base64DecodeInternal<char>(data, len, out, Base64FailOnInvalidCharacter, base64URLDecMap);
+ return base64DecodeInternal(reinterpret_cast<const LChar*>(data), len, out, Base64Default, base64URLDecMap);
}
} // namespace WTF