--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/base64/base64.cpp Thu Oct 28 16:54:54 2010 +0100
@@ -0,0 +1,433 @@
+// base64.cpp
+//
+// Copyright (c) 2010 Accenture. All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of the "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Accenture - Initial contribution
+//
+
+#include <fshell/ioutils.h>
+#include <fshell/common.mmh>
+
+using namespace IoUtils;
+
+const TInt KBlockSize = 512;
+const TInt KLineLength = 76;
+const TUint8 KBase64Chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+const TUint8 KPadCharacter = '=';
+
+const TUint8 KInvBase64[] =
+ {
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x3e,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x3f,
+ 0x34,
+ 0x35,
+ 0x36,
+ 0x37,
+ 0x38,
+ 0x39,
+ 0x3a,
+ 0x3b,
+ 0x3c,
+ 0x3d,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x1,
+ 0x2,
+ 0x3,
+ 0x4,
+ 0x5,
+ 0x6,
+ 0x7,
+ 0x8,
+ 0x9,
+ 0xa,
+ 0xb,
+ 0xc,
+ 0xd,
+ 0xe,
+ 0xf,
+ 0x10,
+ 0x11,
+ 0x12,
+ 0x13,
+ 0x14,
+ 0x15,
+ 0x16,
+ 0x17,
+ 0x18,
+ 0x19,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x0,
+ 0x1a,
+ 0x1b,
+ 0x1c,
+ 0x1d,
+ 0x1e,
+ 0x1f,
+ 0x20,
+ 0x21,
+ 0x22,
+ 0x23,
+ 0x24,
+ 0x25,
+ 0x26,
+ 0x27,
+ 0x28,
+ 0x29,
+ 0x2a,
+ 0x2b,
+ 0x2c,
+ 0x2d,
+ 0x2e,
+ 0x2f,
+ 0x30,
+ 0x31,
+ 0x32,
+ 0x33
+ };
+
+_LIT(KNewLine, "\r\n");
+_LIT(KCr, "\r");
+_LIT(KLf, "\n");
+
+
+class CCmdBase64 : public CCommandBase
+ {
+public:
+ static CCommandBase* NewLC();
+ ~CCmdBase64();
+private:
+ CCmdBase64();
+ void DecodeL();
+ void EncodeL();
+private: // From CCommandBase.
+ virtual const TDesC& Name() const;
+ virtual void DoRunL();
+ virtual void ArgumentsL(RCommandArgumentList& aArguments);
+ virtual void OptionsL(RCommandOptionList& aOptions);
+private:
+ enum
+ {
+ EDecode,
+ EEncode
+ } iOperation;
+ TFileName2 iFileName;
+ TBool iVerbose;
+ TBool iOverwrite;
+ };
+
+EXE_BOILER_PLATE(CCmdBase64)
+
+CCommandBase* CCmdBase64::NewLC()
+ {
+ CCmdBase64* self = new(ELeave) CCmdBase64();
+ CleanupStack::PushL(self);
+ self->BaseConstructL();
+ return self;
+ }
+
+CCmdBase64::~CCmdBase64()
+ {
+ }
+
+CCmdBase64::CCmdBase64()
+ {
+ }
+
+void CCmdBase64::DecodeL()
+ {
+ if (!iOverwrite)
+ {
+ LeaveIfFileExists(iFileName);
+ }
+
+ User::LeaveIfError(Stdin().CaptureAllKeys()); // To iosrv buffering incoming data if we're not keeping up.
+ Stdin().SetReadModeL(RIoReadHandle::ELine);
+
+ RFile file;
+ LeaveIfErr(file.Replace(FsL(), iFileName, EFileWrite | EFileStream), _L("Unabled to open '%S' for writing"), &iFileName);
+ CleanupClosePushL(file);
+
+ TBuf<KLineLength + 2> lineBuf;
+ TBuf8<(KLineLength / 4) * 3> outputBuf;
+ TBool finished(EFalse);
+ TBool started(EFalse);
+ while (!finished)
+ {
+ TInt err = Stdin().Read(lineBuf);
+ if (err == KErrNone)
+ {
+ if (iVerbose)
+ {
+ Printf(_L("Read %d chars:\r\n'%S'\r\n"), lineBuf.Length(), &lineBuf);
+ }
+ if ((lineBuf == KNewLine) || (lineBuf == KCr) || (lineBuf == KLf))
+ {
+ if (started)
+ {
+ finished = ETrue;
+ }
+ }
+ else
+ {
+ if (lineBuf.Right(2) == KNewLine)
+ {
+ lineBuf.SetLength(lineBuf.Length() - 2);
+ }
+ if ((lineBuf.Right(1) == KCr) || (lineBuf.Right(1) == KLf))
+ {
+ lineBuf.SetLength(lineBuf.Length() - 1);
+ }
+ const TInt lineLength = lineBuf.Length();
+ if ((lineLength % 4) > 0)
+ {
+ LeaveIfErr(KErrArgument, _L("Invalid base 64 encoded line (not a multiple of 4 characters in length):\r\n%S\r\n"), &lineBuf);
+ }
+
+ started = ETrue;
+ outputBuf.Zero();
+
+ for (TInt i = 0; i < lineLength; i += 4)
+ {
+ TInt n = ((TInt)KInvBase64[lineBuf[i]] << 18) + ((TInt)KInvBase64[lineBuf[i + 1]] << 12) + ((TInt)KInvBase64[lineBuf[i + 2]] << 6) + (TInt)KInvBase64[lineBuf[i + 3]];
+
+ if (lineBuf[i + 2] == KPadCharacter)
+ {
+ // Two pad characters
+ outputBuf.Append((n >> 16) & 0x000000FF);
+ }
+ else if (lineBuf[i + 3] == KPadCharacter)
+ {
+ // One pad character
+ outputBuf.Append((n >> 16) & 0x000000FF);
+ outputBuf.Append((n >> 8) & 0x000000FF);
+ }
+ else
+ {
+ outputBuf.Append((n >> 16) & 0x000000FF);
+ outputBuf.Append((n >> 8) & 0x000000FF);
+ outputBuf.Append(n & 0x000000FF);
+ }
+ }
+
+ LeaveIfErr(file.Write(outputBuf), _L("Failed to write to '%S'"), &iFileName);
+ if (iVerbose)
+ {
+ Printf(_L("Wrote %d bytes to '%S'\r\n"), outputBuf.Length(), &iFileName);
+ }
+ }
+ }
+ else if (err == KErrEof)
+ {
+ finished = ETrue;
+ }
+ else
+ {
+ LeaveIfErr(err, _L("Couldn't read STDIN"));
+ }
+ }
+
+ CleanupStack::PopAndDestroy(&file);
+ }
+
+void CCmdBase64::EncodeL()
+ {
+ LeaveIfFileNotFound(iFileName);
+
+ RFile file;
+ User::LeaveIfError(file.Open(FsL(), iFileName, EFileRead | EFileStream));
+ CleanupClosePushL(file);
+
+ TBuf8<KBlockSize> inputBuf;
+ TBuf<KLineLength + 2> outputBuf;
+ TBool finished(EFalse);
+ while (!finished)
+ {
+ TPtr8 ptr((TUint8*)inputBuf.Ptr() + inputBuf.Length(), 0, inputBuf.MaxLength() - inputBuf.Length());
+ LeaveIfErr(file.Read(ptr), _L("Couldn't read from '%S'"), &iFileName);
+
+ if (ptr.Length() > 0)
+ {
+ inputBuf.SetLength(inputBuf.Length() + ptr.Length());
+ const TInt inputBufLength = inputBuf.Length();
+ const TInt excess = inputBufLength % 3;
+ const TInt bytesToProcess = inputBufLength - excess;
+
+ for (TInt i = 0; i < bytesToProcess; i += 3)
+ {
+ // Combine the next three bytes into a 24 bit number.
+ TInt n = ((TInt)inputBuf[i] << 16) + ((TInt)inputBuf[i + 1] << 8) + (TInt)inputBuf[i + 2];
+
+ // Split the 24-bit number into four 6-bit numbers.
+ TUint8 n0 = (TUint8)(n >> 18) & 0x3F;
+ TUint8 n1 = (TUint8)(n >> 12) & 0x3F;
+ TUint8 n2 = (TUint8)(n >> 6) & 0x3F;
+ TUint8 n3 = (TUint8)n & 0x3F;
+
+ // Buffer the base64 encoded equivalent.
+ outputBuf.Append(KBase64Chars[n0]);
+ outputBuf.Append(KBase64Chars[n1]);
+ outputBuf.Append(KBase64Chars[n2]);
+ outputBuf.Append(KBase64Chars[n3]);
+
+ // Flush output buffer if it's full.
+ if (outputBuf.Length() == KLineLength)
+ {
+ outputBuf.Append(KNewLine);
+ Write(outputBuf);
+ outputBuf.Zero();
+ }
+ }
+
+ inputBuf.Delete(0, inputBufLength - excess);
+ }
+ else
+ {
+ // Process what's left over in inputBuf from the previous successful read, padding as required.
+ const TInt inputBufLength = inputBuf.Length();
+ if (inputBufLength > 0)
+ {
+ TInt n = (TInt)inputBuf[0] << 16;
+ if (inputBufLength > 1)
+ {
+ n += (TInt)inputBuf[1] << 8;
+ if (inputBufLength > 2)
+ {
+ n += (TInt)inputBuf[2];
+ }
+ }
+
+ TUint8 n0 = (TUint8)(n >> 18) & 0x3F;
+ TUint8 n1 = (TUint8)(n >> 12) & 0x3F;
+ TUint8 n2 = (TUint8)(n >> 6) & 0x3F;
+ TUint8 n3 = (TUint8)n & 0x3F;
+
+ outputBuf.Append(KBase64Chars[n0]);
+ outputBuf.Append(KBase64Chars[n1]);
+ if (inputBufLength > 1)
+ {
+ outputBuf.Append(KBase64Chars[n2]);
+ if (inputBufLength > 2)
+ {
+ outputBuf.Append(KBase64Chars[n3]);
+ }
+ }
+
+ for (TInt i = inputBufLength; i < 3; ++i)
+ {
+ outputBuf.Append('=');
+ }
+ }
+
+ if (outputBuf.Length() > 0)
+ {
+ outputBuf.Append(KNewLine);
+ Write(outputBuf);
+ }
+
+ finished = ETrue;
+ }
+ }
+
+ CleanupStack::PopAndDestroy(&file);
+ }
+
+const TDesC& CCmdBase64::Name() const
+ {
+ _LIT(KName, "base64");
+ return KName;
+ }
+
+void CCmdBase64::ArgumentsL(RCommandArgumentList& aArguments)
+ {
+ _LIT(KArgOperation, "operation");
+ aArguments.AppendEnumL((TInt&)iOperation, KArgOperation);
+
+ _LIT(KArgFilename, "filename");
+ aArguments.AppendFileNameL(iFileName, KArgFilename);
+ }
+
+void CCmdBase64::OptionsL(RCommandOptionList& aOptions)
+ {
+ _LIT(KOptVerbose, "verbose");
+ aOptions.AppendBoolL(iVerbose, KOptVerbose);
+
+ _LIT(KOptOverwrite, "overwrite");
+ aOptions.AppendBoolL(iOverwrite, KOptOverwrite);
+ }
+
+void CCmdBase64::DoRunL()
+ {
+ switch (iOperation)
+ {
+ case EDecode:
+ DecodeL();
+ break;
+ case EEncode:
+ EncodeL();
+ break;
+ default:
+ ASSERT(EFalse);
+ }
+ }