diff --git a/applications/test/base64/Make/files b/applications/test/base64/Make/files
new file mode 100644
index 0000000000..4c6f18ce4c
--- /dev/null
+++ b/applications/test/base64/Make/files
@@ -0,0 +1,3 @@
+Test-base64Encoding.C
+
+EXE = $(FOAM_USER_APPBIN)/Test-base64Encoding
diff --git a/applications/test/base64/Make/options b/applications/test/base64/Make/options
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/applications/test/base64/Test-base64Encoding.C b/applications/test/base64/Test-base64Encoding.C
new file mode 100644
index 0000000000..478a1d9848
--- /dev/null
+++ b/applications/test/base64/Test-base64Encoding.C
@@ -0,0 +1,169 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration |
+ \\ / A nd | Copyright (C) 2016 OpenCFD Ltd.
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+License
+ This file is part of OpenFOAM.
+
+ OpenFOAM is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ OpenFOAM 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 General Public License
+ along with OpenFOAM. If not, see .
+
+Application
+ Test-base64Encoding
+
+Description
+ Test base64 encoding layer.
+
+ Target values generated with "base64 encode ..." in Google.
+ A simple independent source for comparison.
+
+\*---------------------------------------------------------------------------*/
+
+#include "base64Layer.H"
+#include "List.H"
+#include "Pair.H"
+
+#include
+#include
+
+using namespace Foam;
+
+bool test(const Pair& unit)
+{
+ const string& input = unit.first();
+ const string& expected = unit.second();
+
+ std::ostringstream os;
+
+ base64Layer b64(os);
+ b64.write(input.data(), input.size());
+ b64.close();
+
+ const string encoded = os.str();
+
+ Info<< input << nl;
+
+ if (encoded == expected)
+ {
+ Info<< " encoded: " << encoded << " (OK)" << nl
+ << endl;
+ return true;
+ }
+ else
+ {
+ Info<< " encoded: " << encoded << " (ERROR)" << nl
+ << " expected: " << expected << nl
+ << endl;
+
+ return false;
+ }
+}
+
+
+bool test(std::initializer_list> list)
+{
+ bool good = true;
+
+ for (const Pair& t : list)
+ {
+ good = test(t) && good;
+ }
+
+ return good;
+}
+
+
+bool test(const UList>& list)
+{
+ bool good = true;
+
+ for (const Pair& t : list)
+ {
+ good = test(t) && good;
+ }
+
+ return good;
+}
+
+
+void testMixed(std::ostream& os, const UList>& list)
+{
+ base64Layer b64(os);
+
+ os << "" << nl;
+
+ int i=0;
+ for (const Pair& t : list)
+ {
+ const string& input = t.first();
+
+ os << "" << nl;
+ os << " ";
+
+ b64.write(input.data(), input.size());
+ b64.close();
+
+ os << nl
+ << "" << nl;
+ }
+
+ os << "" << nl
+ << nl;
+}
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+int main(int argc, char * argv[])
+{
+ Info<< "Test base64 encode layer" << nl << endl;
+
+ List> testList
+ {
+ {
+ "abcdef", // 6 input, 8 output
+ "YWJjZGVm"
+ },
+ {
+ "OpenFOAM",
+ "T3BlbkZPQU0="
+ },
+ {
+ "OpenFOAM: The Open Source CFD Toolbox",
+ "T3BlbkZPQU06IFRoZSBPcGVuIFNvdXJjZSBDRkQgVG9vbGJveA=="
+ }
+ };
+
+
+ bool good = test(testList);
+
+
+ // Test mixing output
+ testMixed(std::cout, testList);
+
+ if (good)
+ {
+ Info<< "All tests passed" << endl;
+ return 0;
+ }
+ else
+ {
+ Info<< "One or more tests failed" << endl;
+ return 1;
+ }
+}
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
diff --git a/src/OpenFOAM/Make/files b/src/OpenFOAM/Make/files
index 13a9595fcf..8b6be8d895 100644
--- a/src/OpenFOAM/Make/files
+++ b/src/OpenFOAM/Make/files
@@ -144,6 +144,9 @@ $(Sstreams)/SstreamsPrint.C
$(Sstreams)/readHexLabel.C
$(Sstreams)/prefixOSstream.C
+hashes = $(Streams)/hashes
+$(hashes)/base64Layer.C
+
gzstream = $(Streams)/gzstream
$(gzstream)/gzstream.C
diff --git a/src/OpenFOAM/db/IOstreams/hashes/base64Layer.C b/src/OpenFOAM/db/IOstreams/hashes/base64Layer.C
new file mode 100644
index 0000000000..f1123f7519
--- /dev/null
+++ b/src/OpenFOAM/db/IOstreams/hashes/base64Layer.C
@@ -0,0 +1,168 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration |
+ \\ / A nd | Copyright (C) 2016 OpenCFD Ltd.
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+License
+ This file is part of OpenFOAM.
+
+ OpenFOAM is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ OpenFOAM 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 General Public License
+ along with OpenFOAM. If not, see .
+
+\*---------------------------------------------------------------------------*/
+
+#include "base64Layer.H"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+//! \cond fileScope
+//- The characters used for base-64
+static const unsigned char base64Chars[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', '+', '/'
+};
+//! \endcond
+
+
+// * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
+
+inline unsigned char Foam::base64Layer::encode0()
+{
+ // Top 6 bits of char0
+ return base64Chars[((group_[0] & 0xFC) >> 2)];
+}
+
+inline unsigned char Foam::base64Layer::encode1()
+{
+ // Bottom 2 bits of char0, Top 4 bits of char1
+ return base64Chars[((group_[0] & 0x03) << 4) | ((group_[1] & 0xF0) >> 4)];
+}
+
+inline unsigned char Foam::base64Layer::encode2()
+{
+ // Bottom 4 bits of char1, Top 2 bits of char2
+ return base64Chars[((group_[1] & 0x0F) << 2) | ((group_[2] & 0xC0) >> 6)];
+}
+
+inline unsigned char Foam::base64Layer::encode3()
+{
+ // Bottom 6 bits of char2
+ return base64Chars[(group_[2] & 0x3F)];
+}
+
+
+void Foam::base64Layer::add(char c)
+{
+ group_[groupLen_++] = static_cast(c);
+ if (groupLen_ == 3)
+ {
+ unsigned char out[4];
+
+ out[0] = encode0();
+ out[1] = encode1();
+ out[2] = encode2();
+ out[3] = encode3();
+ os_.write(reinterpret_cast(out), 4);
+
+ groupLen_ = 0;
+ }
+
+ dirty_ = true;
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
+
+Foam::base64Layer::base64Layer(std::ostream& os)
+:
+ os_(os),
+ group_(),
+ groupLen_(0),
+ dirty_(false)
+{}
+
+
+// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
+Foam::base64Layer::~base64Layer()
+{
+ close();
+}
+
+
+// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
+
+void Foam::base64Layer::write(const char* s, std::streamsize n)
+{
+ for (std::streamsize i=0; i < n; ++i)
+ {
+ add(s[i]);
+ }
+}
+
+
+void Foam::base64Layer::reset()
+{
+ groupLen_ = 0;
+ dirty_ = false;
+}
+
+
+bool Foam::base64Layer::close()
+{
+ if (!dirty_)
+ {
+ return false;
+ }
+
+ unsigned char out[4];
+ if (groupLen_ == 1)
+ {
+ group_[1] = 0;
+
+ out[0] = encode0();
+ out[1] = encode1();
+ out[2] = '=';
+ out[3] = '=';
+ os_.write(reinterpret_cast(out), 4);
+ }
+ else if (groupLen_ == 2)
+ {
+ group_[2] = 0;
+
+ out[0] = encode0();
+ out[1] = encode1();
+ out[2] = encode2();
+ out[3] = '=';
+ os_.write(reinterpret_cast(out), 4);
+ }
+
+ // group-length == 0 (no content)
+ // group-length == 3 is not possible, already reset in add()
+
+ groupLen_ = 0;
+ dirty_ = false;
+
+ return true;
+}
+
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/db/IOstreams/hashes/base64Layer.H b/src/OpenFOAM/db/IOstreams/hashes/base64Layer.H
new file mode 100644
index 0000000000..9aa4bc8d79
--- /dev/null
+++ b/src/OpenFOAM/db/IOstreams/hashes/base64Layer.H
@@ -0,0 +1,127 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
+ \\ / O peration |
+ \\ / A nd | Copyright (C) 2016 OpenCFD Ltd.
+ \\/ M anipulation |
+-------------------------------------------------------------------------------
+License
+ This file is part of OpenFOAM.
+
+ OpenFOAM is free software: you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ OpenFOAM 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 General Public License
+ along with OpenFOAM. If not, see .
+
+Class
+ base64Layer
+
+Description
+ An output filter layer to write base-64 encoded content.
+
+ Base64 encoding accoding to RFC 4648 specification
+ (https://tools.ietf.org/html/rfc4648#page-5).
+ It is the obligation of the caller to avoid using normal output
+ while the base-64 encoding layer is actively being used.
+
+SourceFiles
+ base64Layer.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef base64Layer_H
+#define base64Layer_H
+
+#include
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+/*---------------------------------------------------------------------------*\
+ Class base64Layer Declaration
+\*---------------------------------------------------------------------------*/
+
+class base64Layer
+{
+ // Private data
+
+ //- The output stream for the layer
+ std::ostream& os_;
+
+ //- Buffer of characters to encode
+ unsigned char group_[3];
+
+ //- Current length of the encode buffer
+ unsigned char groupLen_;
+
+ //- Track if anything has been encoded.
+ bool dirty_;
+
+
+ // Private Member Functions
+
+ inline unsigned char encode0();
+ inline unsigned char encode1();
+ inline unsigned char encode2();
+ inline unsigned char encode3();
+
+ //- Disallow default bitwise copy construct
+ base64Layer(const base64Layer&) = delete;
+
+ //- Disallow default bitwise assignment
+ void operator=(const base64Layer&) = delete;
+
+
+protected:
+
+ // Protected Member Functions
+
+ //- Add a character to the group, outputting when the group is full.
+ void add(char c);
+
+
+public:
+
+ // Constructors
+
+ //- Construct and attach to an output stream
+ base64Layer(std::ostream&);
+
+
+ //- Destructor
+ ~base64Layer();
+
+
+ // Member Functions
+
+ //- Encode the character sequence, writing when possible.
+ void write(const char* s, std::streamsize n);
+
+ //- Restart a new encoding sequence.
+ void reset();
+
+ //- End the encoding sequence, padding the final characters with '='.
+ // Return false if no encoding layer was actually used.
+ bool close();
+
+};
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //