commands/cenrep/cenrep.cpp
changeset 0 7f656887cf89
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands/cenrep/cenrep.cpp	Wed Jun 23 15:52:26 2010 +0100
@@ -0,0 +1,434 @@
+// cenrep.cpp
+// 
+// Copyright (c) 2007 - 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 <centralrepository.h>
+#include <fshell/ltkutils.h>
+#include <fshell/descriptorutils.h>
+
+using namespace IoUtils;
+
+class CCmdCenrep : public CCommandBase
+	{
+public:
+	static CCommandBase* NewLC();
+	~CCmdCenrep();
+private:
+	CCmdCenrep();
+	void PrintKeyL(TUint aKey, RBuf8& valDes);
+	template <class KEYTYPE>
+	void SetKeyL(const KEYTYPE& aVal);
+	void ListRepositoriesL();
+	void ForceSetKeyL(TInt aVal);
+	void ForceSetKeyL(const TDesC& aVal);
+	void SudoL(TRefByValue<const TDesC> aFmt, ...);
+	void AddFilesL(RArray<TUint>&, const TDesC& aMatch, const TDesC& aDir);
+
+private: // From CCommandBase.
+	virtual const TDesC& Name() const;
+	virtual void DoRunL();
+	virtual void ArgumentsL(RCommandArgumentList& aArguments);
+	virtual void OptionsL(RCommandOptionList& aOptions);
+private:
+	// Arguments
+	TUint iRepository;
+	TUint iKey;
+	// Options
+	HBufC* iStringVal;
+	TInt iIntVal;
+	TBool iForce;
+	TBool iDelete;
+	TBool iReset;
+	CRepository* iRep;
+	};
+
+CCommandBase* CCmdCenrep::NewLC()
+	{
+	CCmdCenrep* self = new(ELeave) CCmdCenrep();
+	CleanupStack::PushL(self);
+	self->BaseConstructL();
+	return self;
+	}
+
+CCmdCenrep::~CCmdCenrep()
+	{
+	delete iStringVal;
+	delete iRep;
+	}
+
+CCmdCenrep::CCmdCenrep()
+	{
+	}
+
+const TDesC& CCmdCenrep::Name() const
+	{
+	_LIT(KName, "cenrep");	
+	return KName;
+	}
+
+void CCmdCenrep::DoRunL()
+	{
+	//__DEBUGGER();
+	if (iRepository == 0)
+		{
+		ListRepositoriesL();
+		return;
+		}
+
+	TRAPD(err, iRep = CRepository::NewL(TUid::Uid(iRepository)));
+	if (err && iForce)
+		{
+		// force create a repository?
+		}
+	else
+		{
+		if (err == KErrNotFound)
+			{
+			PrintError(err, _L("Repository 0x%x not found"), iRepository);
+			}
+		User::LeaveIfError(err);
+		}
+
+	if (iDelete)
+		{
+		if (!iArguments.IsPresent(1))
+			{
+			// Delete all
+			if (iForce)
+				{
+				SudoL(_L("--delete"));
+				}
+			else
+				{
+				TUint32 errorKey = 0;
+				err = iRep->Delete(0, 0, errorKey);
+				if (err && errorKey && errorKey != NCentralRepositoryConstants::KUnspecifiedKey)
+					{
+					PrintError(err, _L("Delete failed due to key 0x%x"), errorKey);
+					}
+				}
+			}
+		else
+			{
+			if (iForce)
+				{
+				SudoL(_L("--delete %d"), iKey);
+				}
+			else
+				{
+				err = iRep->Delete(iKey);
+				}
+			}
+		if (err == KErrPermissionDenied)
+			{
+			PrintError(err, _L("Delete failed, retry with --force"));
+			}
+		User::LeaveIfError(err);
+		}
+	else if (iReset)
+		{
+		if (iForce)
+			{
+			delete iRep;
+			iRep = NULL;
+			LtkUtils::RLtkBuf persistsName;
+			CleanupClosePushL(persistsName);
+			persistsName.AppendFormatL(_L("C:\\private\\10202be9\\persists\\%08x.cre"), iRepository);
+			err = FsL().Delete(persistsName);
+			LeaveIfErr(err, _L("Couldn't delete repository file %S"), &persistsName);
+			CleanupStack::PopAndDestroy(&persistsName);
+			}
+		else
+			{
+			User::LeaveIfError(iRep->Reset());
+			}
+		}
+	else if (iOptions.IsPresent(&iIntVal))
+		{
+		// Set int
+		SetKeyL(iIntVal);
+		}
+	else if (iOptions.IsPresent(&iStringVal))
+		{
+		// Set string
+		//TPtrC8 data((TUint8*)iStringVal->Ptr(), iStringVal->Size());
+		//SetKeyL(data);
+		SetKeyL(*iStringVal);
+		}
+	else if (!iArguments.IsPresent(1))
+		{
+		// Get all
+		if (iForce)
+			{
+			SudoL(KNullDesC);
+			}
+		else
+			{
+			RBuf8 valDes;
+			CleanupClosePushL(valDes);
+			valDes.CreateL(NCentralRepositoryConstants::KMaxBinaryLength);
+
+			RArray<TUint32> keys;
+			CleanupClosePushL(keys);
+			iRep->FindL(0, 0, keys);
+			for (TInt i = 0; i < keys.Count(); i++)
+				{
+				PrintKeyL(keys[i], valDes);
+				}
+			CleanupStack::PopAndDestroy(2, &valDes); // keys, valDes
+			}
+		}
+	else
+		{
+		// Get
+		RBuf8 valDes;
+		CleanupClosePushL(valDes);
+		valDes.CreateL(NCentralRepositoryConstants::KMaxBinaryLength * 3); // Because we also use this for hexifying
+		PrintKeyL(iKey, valDes);
+		CleanupStack::PopAndDestroy(&valDes);
+		}
+	}
+
+template <class KEYTYPE>
+void CCmdCenrep::SetKeyL(const KEYTYPE& aVal)
+	{
+	if (!iArguments.IsPresent(1))
+		{
+		LeaveIfErr(KErrArgument, _L("You must specify a key to set"));
+		}
+	if (iForce)
+		{
+		ForceSetKeyL(aVal);
+		}
+	else
+		{
+		TInt err = iRep->Set(iKey, aVal);
+		if (err == KErrArgument)
+			{
+			PrintError(err, _L("Key does not appear to be of the right type"));
+			}
+		User::LeaveIfError(err);
+		}
+	}
+
+void CCmdCenrep::ForceSetKeyL(TInt aVal)
+	{
+	SudoL(_L("%d --set-int %d"), iKey, aVal);
+	}
+
+void CCmdCenrep::ForceSetKeyL(const TDesC& aVal)
+	{
+	SudoL(_L("%d --set-string '%S'"), iKey, &aVal);
+	}
+
+void CCmdCenrep::PrintKeyL(TUint aKey, RBuf8& valDes)
+	{
+	TInt valInt;
+	valDes.Zero();
+	enum TType { EUnknown, EInt, EDes };
+	TType type = EUnknown;
+	TInt reallen = 0;
+
+	TInt err = KErrNotFound;
+
+	if (iForce)
+		{
+		SudoL(_L("%d"), aKey);
+		}
+	else
+		{
+		// Guess the value type
+		// Int?
+		if (type == EUnknown)
+			{
+			err = iRep->Get(aKey, valInt);
+			if (err != KErrArgument)
+				{
+				type = EInt;
+				}
+			}
+		
+		if (type == EUnknown)
+			{
+			// Des?
+			err = iRep->Get(aKey, valDes, reallen);
+			if (err != KErrArgument)
+				{
+				type = EDes;
+				}
+			}
+		}
+
+	switch(err)
+		{
+		case KErrNotFound:
+			PrintError(err, _L("Key not found"));
+			break;
+		case KErrArgument:
+			PrintError(err, _L("Unknown key type, not int, des8 or des16"));
+			break;
+		case KErrPermissionDenied:
+			PrintError(err, _L("Permission denied, retry with --force"));
+			break;
+		/* Won't happen because we now set our buffers to be the max size cenrep can handle
+		case KErrOverflow:
+			valDes16.ReallocL(reallen);
+			valDes8.ReallocL(reallen);
+			if (type == EDes8)
+				{
+				err = rep->Get(iKey, valDes8, reallen); // Better not fail this time!
+				}
+			else
+				{
+				err = rep->Get(iKey, valDes16, reallen); // Better not fail this time!
+				}
+		*/
+		case KErrNone:
+			// do nothing
+			break;
+		default:
+			PrintError(err, _L("Unrecognised error returned from CRepository"));
+			break;
+		}
+
+	if (err == KErrNone)
+		{
+		switch (type)
+			{
+			case EInt:
+				Printf(_L("Key 0x%08x TInt: %d (0x%x)\r\n"), aKey, valInt, valInt);
+				break;
+			/*case EDes8:
+				valDes16.Copy(valDes8);
+				Printf(_L("Key 0x%x TDesC8 length=%d: %S\r\n"), aKey, valDes16.Length(), &valDes16);
+				break;*/
+			case EDes:
+				{
+				TInt len = valDes.Length();
+
+				// Figure out if this string is likely to be 16bit ASCII, 8bit ASCII or just binary data
+				TBool wide = ETrue;
+				TBool ascii = ETrue;
+				if (len&1) wide = EFalse; // Odd number of bytes can't be 16-bit
+				for (TInt i = 0; i < len; i++)
+					{
+					TChar c(valDes[i]);
+					if ((i&1) && valDes[i] != 0) wide = EFalse;
+					if (!(c.IsPrint() && c < 127))
+						{
+						if (!(i&1)) wide = EFalse;
+						ascii = EFalse;
+						}
+					}
+
+				if (wide)
+					{
+					TPtr16 widePtr((TUint16*)valDes.Ptr(), len/2, valDes.MaxLength()/2);
+					Printf(_L("Key 0x%08x TDesC16 length=%d: %S\r\n"), aKey, widePtr.Length(), &widePtr);
+					}
+				else if (ascii)
+					{
+					Printf(_L8("Key 0x%08x TDesC8  length=%d: %S\r\n"), aKey, len, &valDes);
+					}
+				else
+					{
+					Printf(_L("Key 0x%08x TDesC8  hex dump:\r\n"), aKey);
+					LtkUtils::HexDumpToOutput(valDes, Stdout());
+					}
+				}
+				break;
+			default:
+				break;
+			}
+		}
+	}
+
+void CCmdCenrep::ArgumentsL(RCommandArgumentList& aArguments)
+	{
+	aArguments.AppendUintL(iRepository, _L("repository_uid"));
+	aArguments.AppendUintL(iKey, _L("key"));
+ 	}
+
+void CCmdCenrep::OptionsL(RCommandOptionList& aOptions)
+	{
+	aOptions.AppendIntL(iIntVal, _L("set-int"));
+	aOptions.AppendStringL(iStringVal, _L("set-string"));
+	aOptions.AppendBoolL(iForce, _L("force"));
+	aOptions.AppendBoolL(iDelete, _L("delete"));
+	aOptions.AppendBoolL(iReset, _L("reset"));
+	}
+
+EXE_BOILER_PLATE(CCmdCenrep)
+
+void CCmdCenrep::ListRepositoriesL()
+	{
+	RArray<TUint> uids;
+	CleanupClosePushL(uids);
+	AddFilesL(uids, _L("*.cre"), _L("Y:\\private\\10202be9\\persists\\"));
+	AddFilesL(uids, _L("*.cre"), _L("Y:\\private\\10202be9\\"));
+	AddFilesL(uids, _L("*.txt"), _L("Y:\\private\\10202be9\\"));
+
+	for (TInt i = 0; i < uids.Count(); i++)
+		{
+		Printf(_L("%08x\r\n"), uids[i]);
+		}
+	CleanupStack::PopAndDestroy(&uids);
+	}
+
+void CCmdCenrep::AddFilesL(RArray<TUint>& aUids, const TDesC& aMatch, const TDesC& aDir)
+	{
+	TFindFile finder(FsL());
+	CDir* files = NULL;
+	TInt err = finder.FindWildByDir(aMatch, aDir, files);
+
+	while (err == KErrNone)
+		{
+		for (TInt i = 0; i < files->Count(); i++)
+			{
+			TUint uid;
+			TLex lex((*files)[i].iName);
+			err = lex.Val(uid, EHex);
+			if (!err)
+				{
+				err = aUids.InsertInOrder(uid);
+				if (err == KErrAlreadyExists) err = KErrNone;
+				}
+			}
+		delete files;
+		files = NULL;
+		err = finder.FindWild(files);
+		}
+
+	if (err && err != KErrNotFound) LeaveIfErr(err, _L("Couldn't read directory %S"), &aDir);
+	}
+
+void CCmdCenrep::SudoL(TRefByValue<const TDesC> aFmt, ...)
+	{
+	VA_LIST args;
+	VA_START(args, aFmt);
+	
+	// We use sudo to give ourselves the SID of the repository, in the hope that will confer us more rights to access the data.
+	// Some repos might be configured to deny access even from their own SID; there's nothing we can do in that case
+	TBuf<256> commandLine;
+	commandLine.AppendFormat(_L("--sid 0x%x cenrep.exe 0x%x "), iRepository, iRepository);
+	commandLine.AppendFormatList(aFmt, args);
+	VA_END(args);
+
+	RChildProcess sudo;
+	CleanupClosePushL(sudo);
+	TRAPL(sudo.CreateL(_L("sudo.exe"), commandLine, IoSession(), Stdin(), Stdout(), Stderr()), _L("Couldn't create sudo process"));
+	TRequestStatus logon;
+	sudo.Run(logon);
+	User::WaitForRequest(logon);
+	LeaveIfErr(logon.Int(), _L("Error running sudo %S"), &commandLine);
+	CleanupStack::PopAndDestroy(&sudo);
+	}