From a9f02793820a60726f9960cdbbdc058b718f8297 Mon Sep 17 00:00:00 2001 From: Guenter Obiltschnig Date: Tue, 31 Oct 2017 12:25:33 +0100 Subject: [PATCH] Base64Encoder/Decoder: added support for 'base64url' encoding Conflicts: Foundation/src/Base64Decoder.cpp Foundation/src/Base64Encoder.cpp --- Foundation/include/Poco/Base64Decoder.h | 18 ++- Foundation/include/Poco/Base64Encoder.h | 30 +++- Foundation/src/Base64Decoder.cpp | 98 +++++++++---- Foundation/src/Base64Encoder.cpp | 59 +++++--- Foundation/testsuite/src/Base64Test.cpp | 186 ++++++++++++++++++++++++ Foundation/testsuite/src/Base64Test.h | 4 + 6 files changed, 334 insertions(+), 61 deletions(-) diff --git a/Foundation/include/Poco/Base64Decoder.h b/Foundation/include/Poco/Base64Decoder.h index e5bfad5e3..51958231e 100644 --- a/Foundation/include/Poco/Base64Decoder.h +++ b/Foundation/include/Poco/Base64Decoder.h @@ -37,21 +37,25 @@ class Foundation_API Base64DecoderBuf: public UnbufferedStreamBuf /// its streambuf. { public: - Base64DecoderBuf(std::istream& istr); + Base64DecoderBuf(std::istream& istr, int options = 0); ~Base64DecoderBuf(); - + private: int readFromDevice(); int readOne(); + int _options; unsigned char _group[3]; int _groupLength; int _groupIndex; std::streambuf& _buf; - + const unsigned char* _pInEncoding; + static unsigned char IN_ENCODING[256]; static bool IN_ENCODING_INIT; - + static unsigned char IN_ENCODING_URL[256]; + static bool IN_ENCODING_URL_INIT; + private: Base64DecoderBuf(const Base64DecoderBuf&); Base64DecoderBuf& operator = (const Base64DecoderBuf&); @@ -65,13 +69,13 @@ class Foundation_API Base64DecoderIOS: public virtual std::ios /// order of the stream buffer and base classes. { public: - Base64DecoderIOS(std::istream& istr); + Base64DecoderIOS(std::istream& istr, int options = 0); ~Base64DecoderIOS(); Base64DecoderBuf* rdbuf(); protected: Base64DecoderBuf _buf; - + private: Base64DecoderIOS(const Base64DecoderIOS&); Base64DecoderIOS& operator = (const Base64DecoderIOS&); @@ -89,7 +93,7 @@ class Foundation_API Base64Decoder: public Base64DecoderIOS, public std::istream /// its streambuf. { public: - Base64Decoder(std::istream& istr); + Base64Decoder(std::istream& istr, int options = 0); ~Base64Decoder(); private: diff --git a/Foundation/include/Poco/Base64Encoder.h b/Foundation/include/Poco/Base64Encoder.h index 78c1457e7..4371803a5 100644 --- a/Foundation/include/Poco/Base64Encoder.h +++ b/Foundation/include/Poco/Base64Encoder.h @@ -26,6 +26,19 @@ namespace Poco { +enum Base64EncodingOptions +{ + BASE64_URL_ENCODING = 0x01, + /// Use the URL and filename-safe alphabet, + /// replacing '+' with '-' and '/' with '_'. + /// + /// Will also set line length to unlimited. + + BASE64_NO_PADDING = 0x02 + /// Do not append padding characters ('=') at end. +}; + + class Foundation_API Base64EncoderBuf: public UnbufferedStreamBuf /// This streambuf base64-encodes all data written /// to it and forwards it to a connected @@ -37,9 +50,9 @@ class Foundation_API Base64EncoderBuf: public UnbufferedStreamBuf /// not updated to match the buffer's state. { public: - Base64EncoderBuf(std::ostream& ostr); + Base64EncoderBuf(std::ostream& ostr, int options = 0); ~Base64EncoderBuf(); - + int close(); /// Closes the stream buffer. @@ -53,18 +66,21 @@ public: int getLineLength() const; /// Returns the currently set line length. - + private: int writeToDevice(char c); + int _options; unsigned char _group[3]; int _groupLength; int _pos; int _lineLength; std::streambuf& _buf; - + const unsigned char* _pOutEncoding; + static const unsigned char OUT_ENCODING[64]; - + static const unsigned char OUT_ENCODING_URL[64]; + friend class Base64DecoderBuf; Base64EncoderBuf(const Base64EncoderBuf&); @@ -79,7 +95,7 @@ class Foundation_API Base64EncoderIOS: public virtual std::ios /// order of the stream buffer and base classes. { public: - Base64EncoderIOS(std::ostream& ostr); + Base64EncoderIOS(std::ostream& ostr, int options = 0); ~Base64EncoderIOS(); int close(); Base64EncoderBuf* rdbuf(); @@ -107,7 +123,7 @@ class Foundation_API Base64Encoder: public Base64EncoderIOS, public std::ostream /// not updated to match the buffer's state. { public: - Base64Encoder(std::ostream& ostr); + Base64Encoder(std::ostream& ostr, int options = 0); ~Base64Encoder(); private: diff --git a/Foundation/src/Base64Decoder.cpp b/Foundation/src/Base64Decoder.cpp index a9c6b5972..d433e51b8 100644 --- a/Foundation/src/Base64Decoder.cpp +++ b/Foundation/src/Base64Decoder.cpp @@ -23,6 +23,8 @@ namespace Poco { unsigned char Base64DecoderBuf::IN_ENCODING[256]; bool Base64DecoderBuf::IN_ENCODING_INIT = false; +unsigned char Base64DecoderBuf::IN_ENCODING_URL[256]; +bool Base64DecoderBuf::IN_ENCODING_URL_INIT = false; namespace @@ -31,24 +33,45 @@ namespace } -Base64DecoderBuf::Base64DecoderBuf(std::istream& istr): +Base64DecoderBuf::Base64DecoderBuf(std::istream& istr, int options): + _options(options), _groupLength(0), _groupIndex(0), - _buf(*istr.rdbuf()) + _buf(*istr.rdbuf()), + _pInEncoding((options & BASE64_URL_ENCODING) ? IN_ENCODING_URL : IN_ENCODING) { FastMutex::ScopedLock lock(mutex); - if (!IN_ENCODING_INIT) + if (options & BASE64_URL_ENCODING) { - for (unsigned i = 0; i < sizeof(IN_ENCODING); i++) + if (!IN_ENCODING_URL_INIT) { - IN_ENCODING[i] = 0xFF; + for (unsigned i = 0; i < sizeof(IN_ENCODING_URL); i++) + { + IN_ENCODING_URL[i] = 0xFF; + } + for (unsigned i = 0; i < sizeof(Base64EncoderBuf::OUT_ENCODING_URL); i++) + { + IN_ENCODING_URL[Base64EncoderBuf::OUT_ENCODING_URL[i]] = i; + } + IN_ENCODING_URL[static_cast('=')] = '\0'; + IN_ENCODING_URL_INIT = true; } - for (unsigned i = 0; i < sizeof(Base64EncoderBuf::OUT_ENCODING); i++) + } + else + { + if (!IN_ENCODING_INIT) { - IN_ENCODING[Base64EncoderBuf::OUT_ENCODING[i]] = i; + for (unsigned i = 0; i < sizeof(IN_ENCODING); i++) + { + IN_ENCODING[i] = 0xFF; + } + for (unsigned i = 0; i < sizeof(Base64EncoderBuf::OUT_ENCODING); i++) + { + IN_ENCODING[Base64EncoderBuf::OUT_ENCODING[i]] = i; + } + IN_ENCODING[static_cast('=')] = '\0'; + IN_ENCODING_INIT = true; } - IN_ENCODING[static_cast('=')] = '\0'; - IN_ENCODING_INIT = true; } } @@ -60,7 +83,7 @@ Base64DecoderBuf::~Base64DecoderBuf() int Base64DecoderBuf::readFromDevice() { - if (_groupIndex < _groupLength) + if (_groupIndex < _groupLength) { return _group[_groupIndex++]; } @@ -70,24 +93,40 @@ int Base64DecoderBuf::readFromDevice() int c; if ((c = readOne()) == -1) return -1; buffer[0] = (unsigned char) c; - if (IN_ENCODING[buffer[0]] == 0xFF) throw DataFormatException(); - if ((c = readOne()) == -1) throw DataFormatException(); + if (_pInEncoding[buffer[0]] == 0xFF) throw DataFormatException(); + if ((c = readOne()) == -1) return -1; buffer[1] = (unsigned char) c; - if (IN_ENCODING[buffer[1]] == 0xFF) throw DataFormatException(); - if ((c = readOne()) == -1) throw DataFormatException(); - buffer[2] = c; - if (IN_ENCODING[buffer[2]] == 0xFF) throw DataFormatException(); - if ((c = readOne()) == -1) throw DataFormatException(); - buffer[3] = c; - if (IN_ENCODING[buffer[3]] == 0xFF) throw DataFormatException(); - - _group[0] = (IN_ENCODING[buffer[0]] << 2) | (IN_ENCODING[buffer[1]] >> 4); - _group[1] = ((IN_ENCODING[buffer[1]] & 0x0F) << 4) | (IN_ENCODING[buffer[2]] >> 2); - _group[2] = (IN_ENCODING[buffer[2]] << 6) | IN_ENCODING[buffer[3]]; + if (_pInEncoding[buffer[1]] == 0xFF) throw DataFormatException(); + if (_options & BASE64_NO_PADDING) + { + if ((c = readOne()) != -1) + buffer[2] = c; + else + buffer[2] = '='; + if (_pInEncoding[buffer[2]] == 0xFF) throw DataFormatException(); + if ((c = readOne()) != -1) + buffer[3] = c; + else + buffer[3] = '='; + if (_pInEncoding[buffer[3]] == 0xFF) throw DataFormatException(); + } + else + { + if ((c = readOne()) == -1) throw DataFormatException(); + buffer[2] = c; + if (_pInEncoding[buffer[2]] == 0xFF) throw DataFormatException(); + if ((c = readOne()) == -1) throw DataFormatException(); + buffer[3] = c; + if (_pInEncoding[buffer[3]] == 0xFF) throw DataFormatException(); + } + + _group[0] = (_pInEncoding[buffer[0]] << 2) | (_pInEncoding[buffer[1]] >> 4); + _group[1] = ((_pInEncoding[buffer[1]] & 0x0F) << 4) | (_pInEncoding[buffer[2]] >> 2); + _group[2] = (_pInEncoding[buffer[2]] << 6) | _pInEncoding[buffer[3]]; if (buffer[2] == '=') _groupLength = 1; - else if (buffer[3] == '=') + else if (buffer[3] == '=') _groupLength = 2; else _groupLength = 3; @@ -100,13 +139,16 @@ int Base64DecoderBuf::readFromDevice() int Base64DecoderBuf::readOne() { int ch = _buf.sbumpc(); - while (ch == ' ' || ch == '\r' || ch == '\t' || ch == '\n') - ch = _buf.sbumpc(); + if (!(_options & BASE64_URL_ENCODING)) + { + while (ch == ' ' || ch == '\r' || ch == '\t' || ch == '\n') + ch = _buf.sbumpc(); + } return ch; } -Base64DecoderIOS::Base64DecoderIOS(std::istream& istr): _buf(istr) +Base64DecoderIOS::Base64DecoderIOS(std::istream& istr, int options): _buf(istr, options) { poco_ios_init(&_buf); } @@ -123,7 +165,7 @@ Base64DecoderBuf* Base64DecoderIOS::rdbuf() } -Base64Decoder::Base64Decoder(std::istream& istr): Base64DecoderIOS(istr), std::istream(&_buf) +Base64Decoder::Base64Decoder(std::istream& istr, int options): Base64DecoderIOS(istr, options), std::istream(&_buf) { } diff --git a/Foundation/src/Base64Encoder.cpp b/Foundation/src/Base64Encoder.cpp index bc0165e80..8f76f6cff 100644 --- a/Foundation/src/Base64Encoder.cpp +++ b/Foundation/src/Base64Encoder.cpp @@ -26,16 +26,31 @@ const unsigned char Base64EncoderBuf::OUT_ENCODING[64] = 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', - 'w', 'x', 'y', 'z', '0', '1', '2', '3', + 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' }; -Base64EncoderBuf::Base64EncoderBuf(std::ostream& ostr): +const unsigned char Base64EncoderBuf::OUT_ENCODING_URL[64] = +{ + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', + 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', + 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', + 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', + 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', + 'w', 'x', 'y', 'z', '0', '1', '2', '3', + '4', '5', '6', '7', '8', '9', '-', '_' +}; + + +Base64EncoderBuf::Base64EncoderBuf(std::ostream& ostr, int options): + _options(options), _groupLength(0), _pos(0), - _lineLength(72), - _buf(*ostr.rdbuf()) + _lineLength((options & BASE64_URL_ENCODING) ? 0 : 72), + _buf(*ostr.rdbuf()), + _pOutEncoding((options & BASE64_URL_ENCODING) ? OUT_ENCODING_URL : OUT_ENCODING) { } @@ -73,15 +88,15 @@ int Base64EncoderBuf::writeToDevice(char c) { unsigned char idx; idx = _group[0] >> 2; - if (_buf.sputc(OUT_ENCODING[idx]) == eof) return eof; + if (_buf.sputc(_pOutEncoding[idx]) == eof) return eof; idx = ((_group[0] & 0x03) << 4) | (_group[1] >> 4); - if (_buf.sputc(OUT_ENCODING[idx]) == eof) return eof; + if (_buf.sputc(_pOutEncoding[idx]) == eof) return eof; idx = ((_group[1] & 0x0F) << 2) | (_group[2] >> 6); - if (_buf.sputc(OUT_ENCODING[idx]) == eof) return eof; + if (_buf.sputc(_pOutEncoding[idx]) == eof) return eof; idx = _group[2] & 0x3F; - if (_buf.sputc(OUT_ENCODING[idx]) == eof) return eof; + if (_buf.sputc(_pOutEncoding[idx]) == eof) return eof; _pos += 4; - if (_lineLength > 0 && _pos >= _lineLength) + if (_lineLength > 0 && _pos >= _lineLength) { if (_buf.sputc('\r') == eof) return eof; if (_buf.sputc('\n') == eof) return eof; @@ -103,30 +118,36 @@ int Base64EncoderBuf::close() _group[1] = 0; unsigned char idx; idx = _group[0] >> 2; - if (_buf.sputc(OUT_ENCODING[idx]) == eof) return eof; + if (_buf.sputc(_pOutEncoding[idx]) == eof) return eof; idx = ((_group[0] & 0x03) << 4) | (_group[1] >> 4); - if (_buf.sputc(OUT_ENCODING[idx]) == eof) return eof; - if (_buf.sputc('=') == eof) return eof; - if (_buf.sputc('=') == eof) return eof; + if (_buf.sputc(_pOutEncoding[idx]) == eof) return eof; + if (!(_options & BASE64_NO_PADDING)) + { + if (_buf.sputc('=') == eof) return eof; + if (_buf.sputc('=') == eof) return eof; + } } else if (_groupLength == 2) { _group[2] = 0; unsigned char idx; idx = _group[0] >> 2; - if (_buf.sputc(OUT_ENCODING[idx]) == eof) return eof; + if (_buf.sputc(_pOutEncoding[idx]) == eof) return eof; idx = ((_group[0] & 0x03) << 4) | (_group[1] >> 4); - if (_buf.sputc(OUT_ENCODING[idx]) == eof) return eof; + if (_buf.sputc(_pOutEncoding[idx]) == eof) return eof; idx = ((_group[1] & 0x0F) << 2) | (_group[2] >> 6); - if (_buf.sputc(OUT_ENCODING[idx]) == eof) return eof; - if (_buf.sputc('=') == eof) return eof; + if (_buf.sputc(_pOutEncoding[idx]) == eof) return eof; + if (!(_options & BASE64_NO_PADDING)) + { + if (_buf.sputc('=') == eof) return eof; + } } _groupLength = 0; return _buf.pubsync(); } -Base64EncoderIOS::Base64EncoderIOS(std::ostream& ostr): _buf(ostr) +Base64EncoderIOS::Base64EncoderIOS(std::ostream& ostr, int options): _buf(ostr, options) { poco_ios_init(&_buf); } @@ -149,7 +170,7 @@ Base64EncoderBuf* Base64EncoderIOS::rdbuf() } -Base64Encoder::Base64Encoder(std::ostream& ostr): Base64EncoderIOS(ostr), std::ostream(&_buf) +Base64Encoder::Base64Encoder(std::ostream& ostr, int options): Base64EncoderIOS(ostr, options), std::ostream(&_buf) { } diff --git a/Foundation/testsuite/src/Base64Test.cpp b/Foundation/testsuite/src/Base64Test.cpp index e60218390..51aa02692 100644 --- a/Foundation/testsuite/src/Base64Test.cpp +++ b/Foundation/testsuite/src/Base64Test.cpp @@ -55,6 +55,79 @@ void Base64Test::testEncoder() encoder.close(); assert (str.str() == "QUJDREVG"); } + { + std::ostringstream str; + Base64Encoder encoder(str); + encoder << "!@#$%^&*()_~<>"; + encoder.close(); + assert (str.str() == "IUAjJCVeJiooKV9+PD4="); + } +} + + +void Base64Test::testEncoderURL() +{ + { + std::ostringstream str; + Base64Encoder encoder(str, Poco::BASE64_URL_ENCODING); + encoder << std::string("\00\01\02\03\04\05", 6); + encoder.close(); + assert (str.str() == "AAECAwQF"); + } + { + std::ostringstream str; + Base64Encoder encoder(str, Poco::BASE64_URL_ENCODING); + encoder << std::string("\00\01\02\03", 4); + encoder.close(); + assert (str.str() == "AAECAw=="); + } + { + std::ostringstream str; + Base64Encoder encoder(str, Poco::BASE64_URL_ENCODING); + encoder << "ABCDEF"; + encoder.close(); + assert (str.str() == "QUJDREVG"); + } + { + std::ostringstream str; + Base64Encoder encoder(str, Poco::BASE64_URL_ENCODING); + encoder << "!@#$%^&*()_~<>"; + encoder.close(); + assert (str.str() == "IUAjJCVeJiooKV9-PD4="); + } +} + + +void Base64Test::testEncoderNoPadding() +{ + { + std::ostringstream str; + Base64Encoder encoder(str, Poco::BASE64_URL_ENCODING | Poco::BASE64_NO_PADDING); + encoder << std::string("\00\01\02\03\04\05", 6); + encoder.close(); + assert (str.str() == "AAECAwQF"); + } + { + std::ostringstream str; + Base64Encoder encoder(str, Poco::BASE64_URL_ENCODING | Poco::BASE64_NO_PADDING); + encoder << std::string("\00\01\02\03", 4); + encoder.close(); + assert (str.str() == "AAECAw"); + } + { + std::ostringstream str; + Base64Encoder encoder(str, Poco::BASE64_URL_ENCODING | Poco::BASE64_NO_PADDING); + encoder << "ABCDEF"; + encoder.close(); + assert (str.str() == "QUJDREVG"); + } + { + std::ostringstream str; + Base64Encoder encoder(str, Poco::BASE64_URL_ENCODING | Poco::BASE64_NO_PADDING); + encoder << "!@#$%^&*()_~<>"; + encoder.close(); + assert (str.str() == "IUAjJCVeJiooKV9-PD4"); + } } @@ -125,6 +198,115 @@ void Base64Test::testDecoder() } +void Base64Test::testDecoderURL() +{ + { + std::istringstream istr("AAECAwQF"); + Base64Decoder decoder(istr, Poco::BASE64_URL_ENCODING); + assert (decoder.good() && decoder.get() == 0); + assert (decoder.good() && decoder.get() == 1); + assert (decoder.good() && decoder.get() == 2); + assert (decoder.good() && decoder.get() == 3); + assert (decoder.good() && decoder.get() == 4); + assert (decoder.good() && decoder.get() == 5); + assert (decoder.good() && decoder.get() == -1); + } + { + std::istringstream istr("AAECAwQ="); + Base64Decoder decoder(istr, Poco::BASE64_URL_ENCODING); + assert (decoder.good() && decoder.get() == 0); + assert (decoder.good() && decoder.get() == 1); + assert (decoder.good() && decoder.get() == 2); + assert (decoder.good() && decoder.get() == 3); + assert (decoder.good() && decoder.get() == 4); + assert (decoder.good() && decoder.get() == -1); + } + { + std::istringstream istr("AAECAw==", Poco::BASE64_URL_ENCODING); + Base64Decoder decoder(istr); + assert (decoder.good() && decoder.get() == 0); + assert (decoder.good() && decoder.get() == 1); + assert (decoder.good() && decoder.get() == 2); + assert (decoder.good() && decoder.get() == 3); + assert (decoder.good() && decoder.get() == -1); + } + { + std::istringstream istr("QUJDREVG", Poco::BASE64_URL_ENCODING); + Base64Decoder decoder(istr); + std::string s; + decoder >> s; + assert (s == "ABCDEF"); + assert (decoder.eof()); + assert (!decoder.fail()); + } + { + std::istringstream istr("QUJ\r\nDRE\r\nVG"); + Base64Decoder decoder(istr, Poco::BASE64_URL_ENCODING); + std::string s; + decoder >> s; + assert (decoder.bad()); + } + { + std::istringstream istr("QUJD#REVG"); + Base64Decoder decoder(istr, Poco::BASE64_URL_ENCODING); + std::string s; + try + { + decoder >> s; + assert (decoder.bad()); + } + catch (DataFormatException&) + { + } + assert (!decoder.eof()); + } + { + std::istringstream istr("IUAjJCVeJiooKV9-PD4="); + Base64Decoder decoder(istr, Poco::BASE64_URL_ENCODING); + std::string s; + decoder >> s; + assert (s == "!@#$%^&*()_~<>"); + assert (decoder.eof()); + assert (!decoder.fail()); + } +} + + +void Base64Test::testDecoderNoPadding() +{ + { + std::istringstream istr("AAECAwQF"); + Base64Decoder decoder(istr, Poco::BASE64_NO_PADDING); + assert (decoder.good() && decoder.get() == 0); + assert (decoder.good() && decoder.get() == 1); + assert (decoder.good() && decoder.get() == 2); + assert (decoder.good() && decoder.get() == 3); + assert (decoder.good() && decoder.get() == 4); + assert (decoder.good() && decoder.get() == 5); + assert (decoder.good() && decoder.get() == -1); + } + { + std::istringstream istr("AAECAwQ"); + Base64Decoder decoder(istr, Poco::BASE64_NO_PADDING); + assert (decoder.good() && decoder.get() == 0); + assert (decoder.good() && decoder.get() == 1); + assert (decoder.good() && decoder.get() == 2); + assert (decoder.good() && decoder.get() == 3); + assert (decoder.good() && decoder.get() == 4); + assert (decoder.good() && decoder.get() == -1); + } + { + std::istringstream istr("AAECAw"); + Base64Decoder decoder(istr, Poco::BASE64_NO_PADDING); + assert (decoder.good() && decoder.get() == 0); + assert (decoder.good() && decoder.get() == 1); + assert (decoder.good() && decoder.get() == 2); + assert (decoder.good() && decoder.get() == 3); + assert (decoder.good() && decoder.get() == -1); + } +} + + void Base64Test::testEncodeDecode() { { @@ -170,7 +352,11 @@ CppUnit::Test* Base64Test::suite() CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("Base64Test"); CppUnit_addTest(pSuite, Base64Test, testEncoder); + CppUnit_addTest(pSuite, Base64Test, testEncoderURL); + CppUnit_addTest(pSuite, Base64Test, testEncoderNoPadding); CppUnit_addTest(pSuite, Base64Test, testDecoder); + CppUnit_addTest(pSuite, Base64Test, testDecoderURL); + CppUnit_addTest(pSuite, Base64Test, testDecoderNoPadding); CppUnit_addTest(pSuite, Base64Test, testEncodeDecode); return pSuite; diff --git a/Foundation/testsuite/src/Base64Test.h b/Foundation/testsuite/src/Base64Test.h index 67dd7cd96..88d3777c2 100644 --- a/Foundation/testsuite/src/Base64Test.h +++ b/Foundation/testsuite/src/Base64Test.h @@ -25,7 +25,11 @@ public: ~Base64Test(); void testEncoder(); + void testEncoderURL(); + void testEncoderNoPadding(); void testDecoder(); + void testDecoderURL(); + void testDecoderNoPadding(); void testEncodeDecode(); void setUp();