diff -r 000000000000 -r 7f656887cf89 commands/swi/swi.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/commands/swi/swi.cpp Wed Jun 23 15:52:26 2010 +0100 @@ -0,0 +1,1250 @@ +// swi.cpp +// +// Copyright (c) 2008 - 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 "swi.h" +#include +#include + +typedef TBuf<1> TUserInput; +_LIT(KSwiYes, "y"); +_LIT(KSwiNo, "n"); +_LIT(KSwiJarExtension, "*.jar"); +_LIT(KSwiJadExtension, "*.jad"); +#ifndef SYMBIAN_JAVA_NOT_INCLUDED +_LIT8(KDefaultJadMimeType, "text/vnd.sun.j2me.app-descriptor"); +_LIT8(KDefaultJarMimeType, "application/java-archive"); +#endif +_LIT(KDefaultMatch, "*"); + +// +// CCmdSwi +// class to handle the fshell console user interaction +// +CCommandBase* CCmdSwi::NewLC() + { + CCmdSwi* self = new(ELeave) CCmdSwi(); + CleanupStack::PushL(self); + self->BaseConstructL(); + return self; + } + +CCmdSwi::~CCmdSwi() + { +#ifndef SYMBIAN_JAVA_NOT_INCLUDED + delete iMidletHandler; +#endif + delete iSisHandler; + delete iMatch; + } + +CCmdSwi::CCmdSwi(): +CCommandBase(CCommandBase::EManualComplete) + { + } + +const TDesC& CCmdSwi::Name() const + { + _LIT(KName, "swi"); + return KName; + } + +void CCmdSwi::ArgumentsL(RCommandArgumentList& aArguments) + { + aArguments.AppendEnumL((TInt&)iCommand, _L("operation")); + + _LIT(KArgFilename, "sis-file"); + aArguments.AppendFileNameL(iSisFile, KArgFilename); + } + +void CCmdSwi::OptionsL(RCommandOptionList& aOptions) + { + _LIT(KOptUid, "uid"); + aOptions.AppendUintL((TUint&)iUid.iUid, KOptUid); + + _LIT(KOptVerbose, "verbose"); + aOptions.AppendBoolL(iVerbose, KOptVerbose); + + _LIT(KOptQuiet, "quiet"); + aOptions.AppendBoolL(iQuiet, KOptQuiet); + + _LIT(KOptMatch, "match"); + aOptions.AppendStringL(iMatch, KOptMatch); + } + +void CCmdSwi::DoRunL() + { + if (iMatch == NULL) + { + iMatch = KDefaultMatch().AllocL(); + } + + iSisHandler = CSwiSisInstallerAO::NewL(*this, FsL(), iVerbose, iQuiet); +#ifndef SYMBIAN_JAVA_NOT_INCLUDED + iMidletHandler = CSwiMidletInstallerAO::NewL(*this, FsL(), iVerbose, iQuiet); +#endif + + switch (iCommand) + { + case EList: + //TODO matching + TRAPL(iSisHandler->ListInstalledAppsL(iUid, *iMatch), _L("Couldn't list installed SIS files")); +#ifndef SYMBIAN_JAVA_NOT_INCLUDED + TRAPL(iMidletHandler->ListInstalledAppsL(iUid, *iMatch), _L("Couldn't list installed midlets")); +#endif + Complete(KErrNone); + break; + + case EUninstall: + if (!iOptions.IsPresent(&iUid)) + { + LeaveIfErr(KErrArgument, _L("UID must be specified for \"uninstall\"")); + } + TRAPD(error, iSisHandler->UninstallL(iUid)); + if (error != KErrNone) + { +#ifndef SYMBIAN_JAVA_NOT_INCLUDED + // possibly a midlet + TRAP(error, iMidletHandler->UninstallL(iUid)); +#endif + } + LeaveIfErr(error, _L("Failed to uninstall package 0x%08x"), iUid.iUid); + break; + + case EInstall: + if (!iArguments.IsPresent(1)) + { + LeaveIfErr(KErrArgument, _L("SIS file must be specified for \"install\"")); + } + User::LeaveIfError(Stdin().SetReadMode(RIoReadHandle::ELine)); +#ifndef SYMBIAN_JAVA_NOT_INCLUDED + if (IsMidlet()) + { + TRAPL(iMidletHandler->InstallL(iSisFile), _L("Failed to install midlet '%S'"), &iSisFile); + } + else +#endif + { + TRAPL(iSisHandler->InstallL(iSisFile), _L("Failed to install sis '%S'"), &iSisFile); + } + break; + } + + } + +TBool CCmdSwi::IsMidlet() + { + if ((iSisFile.MatchF(KSwiJarExtension) != KErrNotFound) || (iSisFile.MatchF(KSwiJadExtension) != KErrNotFound)) + return ETrue; + return EFalse; + } + +// +// CCmdSwi::GetAnswer +// only for use when not in quiet mode +// Reads input from stdin, determines whether it's a 'yes' or 'no', returning ETrue, EFalse respectively +// +TBool CCmdSwi::GetAnswer() + { + ASSERT(!iQuiet); + TUserInput in; + for (;;) + { + if (Stdin().Read(in) != KErrNone) + { + return EFalse; + } + Stdout().Write(in); + if (in.MatchF(KSwiYes) == 0) + { + return ETrue; + } + if (in.MatchF(KSwiNo) == 0) + { + return EFalse; + } + // else it's an unrecognised response + } + } + +// +// MCmdSwiParent hooks +// +RIoConsoleReadHandle& CCmdSwi::Input() + { + return Stdin(); + } + +RIoConsoleWriteHandle& CCmdSwi::Output(TInt aError) + { + if (aError == KErrNone) + { + return Stdout(); + } + return Stderr(); + } + +// +// CCmdSwi::Finished +// callback from the underlying AO's RunL +// +void CCmdSwi::Finished(const TInt aError) + { + Complete(aError); + } + +// +// Sis installer AO +// +CSwiSisInstallerAO* CSwiSisInstallerAO::NewL(MCmdSwiParent& aParent, RFs& aFs, TBool aVerbose, TBool aQuiet) + { + CSwiSisInstallerAO* self = new (ELeave) CSwiSisInstallerAO(aParent, aFs, aVerbose, aQuiet); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +CSwiSisInstallerAO::CSwiSisInstallerAO(MCmdSwiParent& aParent, RFs& aFs, TBool aVerbose, TBool aQuiet) + : CActive(CActive::EPriorityStandard), iParent(aParent), iVerbose(aVerbose), iQuiet(aQuiet), iCurrentDrive('c') + { + TFileName sessionPath; + TInt err = aFs.SessionPath(sessionPath); + if (err == KErrNone) + { + iCurrentDrive = sessionPath[0]; + iCurrentDrive.LowerCase(); + } + CActiveScheduler::Add(this); + } + +CSwiSisInstallerAO::~CSwiSisInstallerAO() + { + Cancel(); + delete iLauncher; + delete iRegPackage; + iRegistrySession.Close(); + delete iPrefs; + } + +void CSwiSisInstallerAO::ConstructL() + { + iLauncher = CAsyncLauncher::NewL(); + User::LeaveIfError(iRegistrySession.Connect()); + iPrefs = Swi::CInstallPrefs::NewL(); + iPrefs->SetPerformRevocationCheck(EFalse); // TODO - not currently supported in CCmdSwi + } + +void CSwiSisInstallerAO::RunL() + { + iParent.Finished(iStatus.Int()); + } + +void CSwiSisInstallerAO::DoCancel() + { + iLauncher->CancelOperation(); + iParent.Finished(KErrCancel); + } + +void CSwiSisInstallerAO::PrintDetails(Swi::CSisRegistryPackage& aPackage) + { + if (iVerbose) + { + TName myBuf; + myBuf.Format(_L("\r\nName:\t%S\r\n"), &aPackage.Name()); + Stdout().Write(myBuf); + myBuf.Format(_L("Vendor:\t%S\r\n"), &aPackage.Vendor()); + Stdout().Write(myBuf); + myBuf.Format(_L("Uid:\t0x%x\r\n"), aPackage.Uid()); + Stdout().Write(myBuf); + } + else + { + TBuf<256> buf; buf.Format(_L("0x%08x: "), aPackage.Uid()); + Stdout().Write(buf); + Stdout().Write(aPackage.Name()); + Stdout().Write(_L("\r\n")); + } + } + +void CSwiSisInstallerAO::InstallL(TFileName& aInstallFile) + { + // install regular sis file + ASSERT(iPrefs); + ASSERT(iLauncher); + iLauncher->InstallL(*this, aInstallFile, *iPrefs, iStatus); + SetActive(); + } + +void CSwiSisInstallerAO::UninstallL(const TUid& aPackageUid) + { + // remove regular sis file + ASSERT(iLauncher); + ASSERT(!iRegPackage); + Swi::CSisRegistryPackage* iRegPackage = GetSisRegistryPackageL(aPackageUid); + iLauncher->UninstallL(*this, *iRegPackage, iStatus); + SetActive(); + } + +// +// CSwiSisInstallerAO::ListInstalledAppsL +// lists apps currently installed on the device +// +void CSwiSisInstallerAO::ListInstalledAppsL(const TUid& aAppUid, const TDesC& aMatchString) + { + if (aAppUid.iUid != 0) + { + DisplayPackageL(aAppUid); + } + else + { + ASSERT(iRegistrySession.Handle() > 0); + RPointerArray packages; + LtkUtils::CleanupResetAndDestroyPushL(packages); + iRegistrySession.InstalledPackagesL(packages); + if (packages.Count() <= 0) + { + User::Leave(KErrNotFound); + } + TInt count = 0; + const TInt endCount = packages.Count(); + do + { + CSisRegistryPackage* current = packages[count++]; + if ((current->Name().MatchF(aMatchString) >= 0) || (current->Vendor().MatchF(aMatchString) >= 0)) + { + PrintDetails(*current); + } + } while (count < endCount); + CleanupStack::PopAndDestroy(&packages); + } + } + +// +// CSwiSisInstallerAO::DisplayPackageL +// find information on the specified package uid and display it on the console +// +void CSwiSisInstallerAO::DisplayPackageL(const TUid& aPackageUid) + { + ASSERT(iRegistrySession.Handle() > 0); + Swi::RSisRegistryEntry entry; + User::LeaveIfError(entry.Open(iRegistrySession, aPackageUid)); + CleanupClosePushL(entry); + Swi::CSisRegistryPackage* registryPackage = entry.PackageL(); + CleanupStack::PushL(registryPackage); + PrintDetails(*registryPackage); + CleanupStack::PopAndDestroy(2, &entry); + } + +// +// CSwiSisInstallerAO::GetSisRegistryPackageL +// locate the sis registry package corresponding to the specified package ui +// +Swi::CSisRegistryPackage* CSwiSisInstallerAO::GetSisRegistryPackageL(const TUid& aPackageUid) + { + ASSERT(iRegistrySession.Handle() > 0); + if (!iRegistrySession.IsInstalledL(aPackageUid)) + { + User::Leave(KErrNotFound); // invalid uid + } + // else iterate through the installed packages to find ours + RPointerArray packages; + iRegistrySession.InstalledPackagesL(packages); + if (packages.Count() <= 0) + { + User::Leave(KErrNotFound); + } + TInt count = 0; + const TInt endCount = packages.Count(); + Swi::CSisRegistryPackage* found = NULL; + do + { + Swi::CSisRegistryPackage* current = packages[count]; + if (current->Uid() == aPackageUid) + { + found = current; + break; + } + count++; + } while (count < endCount); + ASSERT(found); // IsInstalledL stated it's in there + return found; + } + +// +// SWI UI Hooks +// +TBool CSwiSisInstallerAO::DisplayTextL(const Swi::CAppInfo& /*aAppInfo*/, Swi::TFileTextOption /*aOption*/, const TDesC& aText) + { + TBool response = ETrue; // default, the user will continue with the installation/uninstallation + if (!iQuiet) + { + Stdout().Write(aText); + Stdout().Write(_L("Continue [y/n]?\r\n")); + response = iParent.GetAnswer(); + } + return response; + } + +void CSwiSisInstallerAO::DisplayErrorL(const Swi::CAppInfo& /*aAppInfo*/, Swi::TErrorDialog aType, const TDesC& /*aParam*/) + { + if (iVerbose) + { + switch (aType) + { + case Swi::EUiAlreadyInRom: + Stderr().Write(_L("\r\nCannot overwrite a ROM component.\r\n")); + break; + + case Swi::EUiMissingDependency: + Stderr().Write(_L("\r\nMissing a dependency.\r\n")); + break; + + case Swi::EUiRequireVer: + Stderr().Write(_L("\r\nA dependency exists on a specific version of an application which is different from the one installed.\r\n")); + break; + + case Swi::EUiFileCorrupt: + Stderr().Write(_L("\r\nSISX file corrupt. Checksums stored in file do not match actual.\r\n")); + break; + + case Swi::EUiDiskNotPresent: + Stderr().Write(_L("\r\nAll your bases are belong to us. \r\n")); + break; + + case Swi::EUiCannotRead: + Stderr().Write(_L("\r\nCannot read a file which is needed in order to proceed.\r\n")); + break; + + case Swi::EUiCannotDelete: + Stderr().Write(_L("\r\nCannot delete a file.\r\n")); + break; + + case Swi::EUiInvalidFileName: + Stderr().Write(_L("\r\nA filename specified in the SISX package is not valid.\r\n")); + break; + + case Swi::EUiInsufficientSpaceOnDrive: + Stderr().Write(_L("\r\nInsufficient space on the drive.\r\n")); + break; + + case Swi::EUiCapabilitiesCannotBeGranted: + Stderr().Write(_L("\r\nApplication requires system capability it is not signed for.\r\n")); + break; + + case Swi::EUiUnknownFile: + Stderr().Write(_L("\r\nNot a recognised SISX file.\r\n")); + break; + + case Swi::EUiMissingBasePackage: + Stderr().Write(_L("\r\nA base package required for installation is not present.\r\n")); + break; + + case Swi::EUiConstraintsExceeded: + Stderr().Write(_L("\r\nConstraints imposed by a developer mode certificate have been exceeded.\r\n")); + break; + + case Swi::EUiSIDViolation: + Stderr().Write(_L("\r\nThe package contains a file with a protected SID which is not signed for.\r\n")); + break; + + case Swi::EUiVIDViolation: + Stderr().Write(_L("\r\nThe package contains a file with a protected VID which is not signed for.\r\n")); + break; + + case Swi::EUiSIDMismatch: + Stderr().Write(_L("\r\nMismatched SID.\r\n")); + break; + + case Swi::EUiBlockingEclipsingFile: + Stderr().Write(_L("\r\nThe package contains an invalid eclipsing file which is already in the device other than ROM.\r\n")); + break; + + default: + { + TBuf<64> buf; + buf.Format(_L("\r\nAn error %d has occured. Aborting.\r\n"), aType); + Stderr().Write(buf); + } + break; + }; + } + } + +TBool CSwiSisInstallerAO::DisplayDependencyBreakL(const Swi::CAppInfo& /*aAppInfo*/, const RPointerArray& /*aComponents*/) + { + TBool response = ETrue; // default response is to continue with uninstallation + if (iVerbose) + { + Stdout().Write(_L("\r\nComponent being uninstalled has dependencies which may no longer work. Continue uninstalling [y/n]?\r\n")); + response = iParent.GetAnswer(); + } + return response; + } + +TBool CSwiSisInstallerAO::DisplayApplicationsInUseL(const Swi::CAppInfo& /*aAppInfo*/, const RPointerArray& /*aAppNames*/) + { + TBool response = EFalse; // EFalse indicates we don't continue with uninstallation + if (!iQuiet) + { + Stdout().Write(_L("\r\nApplication is currently open. Continue uninstalling? [y/n]\r\n")); + response = iParent.GetAnswer(); + } + if (!response) + { + Stderr().Write(_L("Uninstall aborted. Application will not be closed.\r\n")); + } + return response; + } + +TBool CSwiSisInstallerAO::DisplayQuestionL(const Swi::CAppInfo& /* aAppInfo */, Swi::TQuestionDialog aQuestion, const TDesC& aDes) + { + TBool response = ETrue; // default behaviour assumes the user presses 'Yes' to any question + if (!iQuiet) + { + if (aQuestion == Swi::EQuestionIncompatible) + { + Stdout().Write(_L("\r\nApplication is not compatible with this device. Install anyway [y/n]?")); + } + else if (aQuestion == Swi::EQuestionOverwriteFile) + { + Stdout().Write(_L("\r\nSome system files will be overwritten by this installation. Install anyway [y/n]?")); + } + else + { + TBuf<128> buf; buf.Format(_L("Unrecognised question from engine %d\r\n"), aQuestion); + Stderr().Write(buf); + User::Leave(KErrNotSupported); + } + + if (aDes.Length() > 0) + { + Stdout().Write(aDes); + } + Stdout().Write(_L("\r\n")); + response = iParent.GetAnswer(); + } + return response; + } + +TBool CSwiSisInstallerAO::DisplayInstallL(const Swi::CAppInfo& aAppInfo, const CApaMaskedBitmap* /*aLogo*/, const RPointerArray& /*aCertificates*/) + { + if (iVerbose) + { + TBuf<256> myBuf; + myBuf.Format(_L("NAME:\t\t%S\r\n"), &aAppInfo.AppName()); + Stdout().Write(myBuf); + myBuf.Format(_L("VENDOR:\t\t%S\r\n"), &aAppInfo.AppVendor()); + Stdout().Write(myBuf); + myBuf.Format(_L("VERSION:\t%d.%d.%d\r\n"), aAppInfo.AppVersion().iMajor, aAppInfo.AppVersion().iMinor, aAppInfo.AppVersion().iBuild); + Stdout().Write(myBuf); + } + TBool response = ETrue; // default behaviour is to continue the install + return response; + } + +TBool CSwiSisInstallerAO::DisplayGrantCapabilitiesL(const Swi::CAppInfo& /*aAppInfo*/, const TCapabilitySet& /*aCapabilitySet*/) + { + TBool response = ETrue; // default behaviour is to continue the install + if (iVerbose) + { + // todo verbose mode + Stdout().Write(_L("\r\nTODO - CCmdSwi::DisplayGrantCapabilitiesL\r\n")); + } + return response; + } + +TInt CSwiSisInstallerAO::DisplayLanguageL(const Swi::CAppInfo& /*aAppInfo*/, const RArray& /*aLanguages*/) + { + if (iVerbose) + { + // todo verbose mode + Stdout().Write(_L("\r\nTODO - CCmdSwi::DisplayLanguageL\r\n")); + } + return 0; // the first language + } + +TInt CSwiSisInstallerAO::DisplayDriveL(const Swi::CAppInfo& /*aAppInfo*/, TInt64 aSize, const RArray& aDriveLetters, const RArray& aDriveSpaces) + { + TInt response = 0; // default to the first known drive + for (TInt i = 0; i < aDriveLetters.Count(); i++) + { + TChar letter = aDriveLetters[i]; + letter.LowerCase(); + if (letter == iCurrentDrive) + { + response = i; // Default to using the CWD drive, if it is in the list of available drives + break; + } + } + + if (!iQuiet) + { + TBuf<128> info; + info.Format(_L("Application requires %d bytes free space. Please select installation drive:\r\n"), aSize); + Stdout().Write(info); + for (TInt ii = 0 ; ii < aDriveLetters.Count() ; ii++) + { + info.Format(_L("%d. \'"), ii); // pseudo-drive number + info.Append(aDriveLetters[ii]); // drive letter + info.Append(_L("\' ")); + info.AppendNum(aDriveSpaces[ii]); // free space + info.Append(_L(" bytes free\r\n")); + Stdout().Write(info); + } + TUserInput in; + User::LeaveIfError(Stdin().Read(in)); + TLex lex(in); + User::LeaveIfError(lex.Val(response)); + } + return response; + } + +TBool CSwiSisInstallerAO::DisplayUpgradeL(const Swi::CAppInfo& /*aAppInfo*/, const Swi::CAppInfo& /*aExistingAppInfo*/) + { + TBool response = ETrue; // default behaviour is to continue the install + if (!iQuiet) + { + Stdout().Write(_L("Do you wish to replace the existing installed application [y/n]?\r\n")); + response = iParent.GetAnswer(); + } + return response; + } + +TBool CSwiSisInstallerAO::DisplayOptionsL(const Swi::CAppInfo& /*aAppInfo*/, const RPointerArray& /*aOptions*/, RArray& /*aSelections*/) + { + TBool response = ETrue; // default behaviour is to continue the install + if (iVerbose) + { + // todo verbose mode + Stdout().Write(_L("TODO - CCmdSwi::DisplayOptionsL\r\n")); + } + return response; + } + +TBool CSwiSisInstallerAO::HandleInstallEventL(const Swi::CAppInfo& /*aAppInfo*/, Swi::TInstallEvent aEvent, TInt /*aValue*/, const TDesC& /*aDes*/) + { + TBool response = ETrue; // default behaviour is to continue the install + if (iVerbose) + { + switch (aEvent) + { + case Swi::EEventUpdateProgressBar: + Stdout().Write(_L(".")); + break; + + case Swi::EEventCompletedInstall: + case Swi::EEventCompletedUnInstall: + { + Stdout().Write(_L("\r\nComplete\r\n")); + } + break; + + default: + // do nothing to inform the user of other cases + break; + }; + } + return response; + } + +void CSwiSisInstallerAO::HandleCancellableInstallEventL(const Swi::CAppInfo& /*aAppInfo*/, Swi::TInstallCancellableEvent aEvent, Swi::MCancelHandler& /*aCancelHandler*/, TInt /*aValue*/, const TDesC& /*aDes*/) + { + if (iVerbose) + { + switch (aEvent) + { + case Swi::EEventRemovingFiles: + { + Stdout().Write(_L("\r\nRemoving files\r\n")); + } + break; + + case Swi::EEventShuttingDownApps: + { + Stdout().Write(_L("Closing App\r\n")); + } + break; + + case Swi::EEventCopyingFiles: + { + Stdout().Write(_L("Copying files\r\n")); + } + break; + + default: + break; + }; + } + } + +TBool CSwiSisInstallerAO::DisplaySecurityWarningL(const Swi::CAppInfo& /*aAppInfo*/, Swi::TSignatureValidationResult /*aSigValidationResult*/, RPointerArray& /*aPkixResults*/, RPointerArray& /*aCertificates*/, TBool /*aInstallAnyway*/) + { + TBool response = ETrue; // default behaviour is to continue the install + if (!iQuiet) + { + Stdout().Write(_L("\r\nApplication signature cannot be validated. Continue installing [y/n]?\r\n")); + response = iParent.GetAnswer(); + } + return response; + } + +TBool CSwiSisInstallerAO::DisplayOcspResultL(const Swi::CAppInfo& /*aAppInfo*/, Swi::TRevocationDialogMessage /*aMessage*/, RPointerArray& /*aOutcomes*/, RPointerArray& /*aCertificates*/, TBool /*aWarningOnly*/) + { + TBool response = ETrue; // default behaviour is to continue the install + if (iVerbose) + { + // todo verbose mode + Stdout().Write(_L("TODO - CCmdSwi::DisplayOcspResultL\r\n")); + } + return response; + } + +void CSwiSisInstallerAO::DisplayCannotOverwriteFileL(const Swi::CAppInfo& /*aAppInfo*/, const Swi::CAppInfo& /*aInstalledAppInfo*/, const TDesC& aFileName) + { + if (iVerbose) + { + Stdout().Write(_L("\r\nCannot overwrite a file required for installation. Aborting -")); + Stdout().Write(aFileName); + Stdout().Write(_L(" - \r\n")); + } + } + +TBool CSwiSisInstallerAO::DisplayMissingDependencyL(const Swi::CAppInfo& /*aAppInfo*/, const TDesC& aDependencyName, TVersion /*aWantedVersionFrom*/, TVersion /*aWantedVersionTo*/, TVersion /*aInstalledVersion*/) + { + TBool response = ETrue; // default behaviour is to continue the install + if (!iQuiet) + { + Stdout().Write(_L("Warning: Depedency is missing or has incorrect version - ")); + Stdout().Write(aDependencyName); + Stdout().Write(_L(" - \r\n")); + } + return response; + } + +TBool CSwiSisInstallerAO::DisplayUninstallL(const Swi::CAppInfo& aAppInfo) + { + if (iVerbose) + { + TName myBuf; + myBuf.Format(_L("NAME:\t\t%S\r\n"), &aAppInfo.AppName()); + Stdout().Write(myBuf); + myBuf.Format(_L("VENDOR:\t\t%S\r\n"), &aAppInfo.AppVendor()); + Stdout().Write(myBuf); + myBuf.Format(_L("VERSION:\t%d.%d.%d\r\n"), aAppInfo.AppVersion().iMajor, aAppInfo.AppVersion().iMinor, aAppInfo.AppVersion().iBuild); + Stdout().Write(myBuf); + } + TBool response = ETrue; // default behaviour is to continue the uninstall + return response; + } + +#ifndef SYMBIAN_JAVA_NOT_INCLUDED +// +// java ui installer +// +CSwiMidletInstallerAO* CSwiMidletInstallerAO::NewL(MCmdSwiParent& aParent, RFs& aFs, TBool aVerbose, TBool aQuiet) + { + CSwiMidletInstallerAO* self = new (ELeave) CSwiMidletInstallerAO(aParent, aFs, aVerbose, aQuiet); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +CSwiMidletInstallerAO::CSwiMidletInstallerAO(MCmdSwiParent& aParent, RFs& aFs, TBool aVerbose, TBool aQuiet) + : CActive(CActive::EPriorityStandard), iParent(aParent), iFs(aFs), iVerbose(aVerbose), iQuiet(aQuiet) + { + CActiveScheduler::Add(this); + } + +CSwiMidletInstallerAO::~CSwiMidletInstallerAO() + { + Cancel(); + if (iInstaller) + delete iInstaller; + if (iJadHandle) + iJadHandle->CloseFileHandle(); + if (iJarHandle) + iJarHandle->CloseFileHandle(); + if (iInfo) + delete iInfo; + if (iRemover) + delete iRemover; + } + +void CSwiMidletInstallerAO::ConstructL() + { + iInstaller = CJavaInstaller::NewL(*this, *this, KNullDesC8, EFalse, 0); + } + +TBool CSwiMidletInstallerAO::IsJad(TDes& aMidlet) + { + if (aMidlet.MatchF(KSwiJadExtension) > 0) + return ETrue; + return EFalse; + } + +TBool CSwiMidletInstallerAO::IsJar(TDes& aMidlet) + { + if (aMidlet.MatchF(KSwiJarExtension) > 0) + return ETrue; + return EFalse; + } + +void CSwiMidletInstallerAO::ListInstalledAppsL(TUid aAppUid, const TDesC& aMatchString) + { + MJavaRegistry* reg = MJavaRegistry::CreateL(); + RArray list; + TInt count = 0; + CleanupStack::PushL(reg); + if ((aAppUid.iUid != 0) && (reg->SuiteEntryExistsL(aAppUid))) + { + MJavaRegistrySuiteEntry* suite = reg->SuiteEntryL(aAppUid); + CleanupStack::PushL(suite); + suite->MIDletUidsL(list); + while (count < list.Count()) + { + MJavaRegistryMIDletEntry* entry = reg->MIDletEntryL(list[count++]); + CleanupStack::PushL(entry); + DisplayPackageL(*entry); + CleanupStack::Pop(entry); + entry->Release(); + } + CleanupStack::Pop(suite); + suite->Release(); + } + else + { + reg->InstalledMIDletUidsL(list); + while (count < list.Count()) + { + MJavaRegistryMIDletEntry* entry = reg->MIDletEntryL(list[count++]); + CleanupStack::PushL(entry); + if ((entry->MIDletNameL().MatchF(aMatchString)>=0) || (entry->SuiteEntryL().VendorL().MatchF(aMatchString)>=0)) + { + DisplayPackageL(*entry); + } + CleanupStack::Pop(entry); + entry->Release(); + } + } + CleanupStack::Pop(reg); + } + +// +// CSwiMidleInstallerAO::DisplayPackageL +// find information on the specified package uid and display it on the console +// +void CSwiMidletInstallerAO::DisplayPackageL(MJavaRegistryMIDletEntry& aPackage) + { + TName myBuf; + myBuf.Format(_L("\r\nNAME:\t%S\r\n"), &aPackage.MIDletNameL()); + Stdout().Write(myBuf); + myBuf.Format(_L("VENDOR:\t%S\r\n"), &aPackage.SuiteEntryL().VendorL()); + Stdout().Write(myBuf); + myBuf.Format(_L("UID:\t0x%x\r\n"), aPackage.SuiteEntryL().UidL()); + Stdout().Write(myBuf); + } + +// +// CSwiMidletInstallerAO::InstallL +// installs a jar/jad midp 1.0/2.0-compatible midlet +// +void CSwiMidletInstallerAO::InstallL(TFileName& aInstallFile) + { + ASSERT(iInstaller); + ASSERT(!iInfo); + ASSERT(!iJarHandle); + ASSERT(!iJadHandle); + if (aInstallFile.Length() <= 0) + { + User::Leave(KErrNotFound); + } + if (iVerbose) + { + Stdout().Write(_L("Installing Midlet...\r\n")); + } + const TInt length = aInstallFile.Length() - 3; // the java midlet filename minus the jad/jar extension name + TFileName sisterFile(aInstallFile.Left(length)); + if (IsJad(aInstallFile)) + { + iJadHandle = CJavaFileHandle::NewL(iFs, aInstallFile, KNullDesC, KDefaultJadMimeType()); + // name the associated jar file + sisterFile.Append(_L("jar")); + iJarHandle = CJavaFileHandle::NewL(iFs, sisterFile, KNullDesC, KDefaultJarMimeType()); + } + else + { + ASSERT(IsJar(aInstallFile)); + iJarHandle = CJavaFileHandle::NewL(iFs, aInstallFile, KNullDesC, KDefaultJarMimeType()); + // name the associated jad file + sisterFile.Append(_L("jad")); + iJadHandle = CJavaFileHandle::NewL(iFs, sisterFile, KNullDesC, KDefaultJadMimeType()); + } + iInfo = CMIDPInstallationLaunchInfo::NewL(iFs, *iJadHandle, *iJarHandle); + iInstaller->Install(*iInfo, iStatus); + SetActive(); + } + +// +// CSwiMidletInstallerAO::Uninstall +// uninstalls a jar/jad midp 1.0/2.0-compatible midlet +// +void CSwiMidletInstallerAO::UninstallL(const TUid& aPackageUid) + { + ASSERT(!iRemover); + if (iVerbose) + { + Stdout().Write(_L("Removing Midlet...\r\n")); + } + iRemover = CJavaRemover::NewL(aPackageUid, *this); + iRemover->Remove(iStatus); + SetActive(); + } + +void CSwiMidletInstallerAO::RunL() + { + iParent.Finished(iStatus.Int()); + } + +void CSwiMidletInstallerAO::DoCancel() + { + ASSERT(iInstaller); + ASSERT(iRemover); + iInstaller->Cancel(); + iRemover->Cancel(); + iParent.Finished(KErrCancel); + } + +// +// java installer UI hooks +// +TBool CSwiMidletInstallerAO::StartInstallL(const CMIDletSuiteAttributes& aMIDlet) + { + if (iVerbose) + { + TName myBuf; + myBuf.Format(_L("\r\nNAME:\t\t%S\r\n"), &aMIDlet.MIDletName()); + Stdout().Write(myBuf); + myBuf.Format(_L("VENDOR:\t\t%S\r\n"), &aMIDlet.MIDletVendor()); + Stdout().Write(myBuf); + myBuf.Format(_L("VERSION:\t%d.%d.%d\r\n"), aMIDlet.MIDletVersion().iMajor, aMIDlet.MIDletVersion().iMinor, aMIDlet.MIDletVersion().iBuild); + Stdout().Write(myBuf); + } + TBool response = ETrue; // default behaviour is to continue the install + return response; + } + +TBool CSwiMidletInstallerAO::SelectDriveL(const CMIDletSuiteAttributes& /*aMIDlet*/, TInt aSpaceRequired, TChar& aDrive, TBool& aSufficientSpace) + { + aSufficientSpace = ETrue; + aDrive = 'c'; + if (iQuiet) + { + // Default to CWD drive if writeable + TFileName sessionPath; + TInt err = iFs.SessionPath(sessionPath); + if (err == KErrNone) + { + TChar drive = sessionPath[0]; + drive.LowerCase(); + TVolumeInfo volInfo; + if (iFs.Volume(volInfo, ((TUint)drive)-'a') == KErrNone && volInfo.iFree >= aSpaceRequired && !(volInfo.iDrive.iDriveAtt & KDriveAttRom) && !(volInfo.iDrive.iMediaAtt & KMediaAttWriteProtected)) + { + aDrive = drive; + } + } + } + else + { + // ask the question + TBuf<128> info; + info.Format(_L("Midlet requires %d bytes free space. Please select installation drive:\r\n"), aSpaceRequired); + Stdout().Write(info); + + // cycle through drive list checking for existing drive + TDriveList drives; + TVolumeInfo volume; + TChar driveChar; + TBool displayed = EFalse; + User::LeaveIfError(iFs.DriveList(drives)); + for (TInt ii = 0 ; ii < KMaxDrives ; ii++) + { + if (drives[ii]) + { + // drive exists + if (KErrNone == iFs.Volume(volume, ii)) + { + // drive is present + if (volume.iFree >= aSpaceRequired) + { + // drive has sufficient space + aSufficientSpace = ETrue; + if (!(volume.iDrive.iDriveAtt & KDriveAttRom) && + !(volume.iDrive.iMediaAtt & KMediaAttWriteProtected)) + { + // drive is not a rom drive and is not write protected + User::LeaveIfError(iFs.DriveToChar(ii, driveChar)); + info.Format(_L("%d. \'"), ii); // drive number + info.Append(driveChar); // drive letter + info.Append(_L("\' ")); + info.AppendNum(volume.iFree); // free space + info.Append(_L(" bytes free\r\n")); + Stdout().Write(info); + displayed = ETrue; + } + } + } + } + } + // get the answer + if (displayed) + { + TUserInput in; + User::LeaveIfError(Stdin().Read(in)); + TLex lex(in); + TInt response; + User::LeaveIfError(lex.Val(response)); + User::LeaveIfError(iFs.DriveToChar(response, aDrive)); + } + else + { + Stdout().Write(_L("Error. No drives capable of supporting midlet install. Aborting\r\n")); + return EFalse; + } + } + return ETrue; + } + +TBool CSwiMidletInstallerAO::ReplaceExistingMIDletL(const CMIDletSuiteAttributes& /*aMIDlet*/, const TAppVersion& /*aOldVersion*/) + { + TBool response = ETrue; // default behaviour is to continue the install + if (!iQuiet) + { + Stdout().Write(_L("Do you wish to replace the existing midlet [y/n]?\r\n")); + response = iParent.GetAnswer(); + } + return response; + } + +TBool CSwiMidletInstallerAO::UpgradeRMSL(const CMIDletSuiteAttributes& /*aMIDlet*/, const TAppVersion& /*aOldVersion*/) + { + TBool response = ETrue; // default behaviour is to continue the install + if (!iQuiet) + { + Stdout().Write(_L("Do you wish to upgrade the existing midlet [y/n]?\r\n")); + response = iParent.GetAnswer(); + } + return response; + } + +TBool CSwiMidletInstallerAO::MIDletUntrustedL(const CMIDletSuiteAttributes& /*aMIDlet*/) + { + TBool response = ETrue; // default behaviour is to continue the install + if (!iQuiet) + { + Stdout().Write(_L("\r\nMidlet is untrusted. Continue installing [y/n]?\r\n")); + response = iParent.GetAnswer(); + } + return response; + } + +void CSwiMidletInstallerAO::CertificateHasNoRootL(const CMIDletSuiteAttributes& /*aMIDlet*/, const CPKIXCertChain& /*aCertChain*/, const CPKIXValidationResult& /*aValidationResult*/) + { + Stderr().Write(_L("\r\nCertificate attached to midlet has no identifiable root. Aborting installation.\r\n")); + } + +void CSwiMidletInstallerAO::BadSignatureL(const CMIDletSuiteAttributes& /*aMIDlet*/, const CPKIXCertChain& /*aCertChain*/, const CPKIXValidationResult& /*aValidationResult*/) + { + if (iVerbose) + { + Stdout().Write(_L("\r\nWarning: Midlet certificate chain is incomplete. Continuing installation\r\n")); + } + } + +TBool CSwiMidletInstallerAO::PerformRevocationCheckL(TBool& aDoCheck) + { + aDoCheck = EFalse; + return ETrue; + } + +void CSwiMidletInstallerAO::StartRevocationCheckL() + { + if (iVerbose) + { + Stdout().Write(_L("\r\nStarted: Revocation check\r\n")); + } + } + +void CSwiMidletInstallerAO::FinishedRevocationCheckL() + { + if (iVerbose) + { + Stdout().Write(_L("\r\nFinished: Revocation check\r\n")); + } + } + +void CSwiMidletInstallerAO::StartIconConversionL() + { + } + +void CSwiMidletInstallerAO::FinishedIconConversionL() + { + } + +TBool CSwiMidletInstallerAO::OCSPWarningL(const CMIDletSuiteAttributes& /*aMIDlet*/, TRevocationMsg /*aRevocationMsg*/, const TOCSPOutcome* /*aOCSPOutcome*/) + { + if (iVerbose) + { + Stdout().Write(_L("\r\nWarning: OCSP failure. Continuing installation.\r\n")); + } + return ETrue; + } + +void CSwiMidletInstallerAO::OCSPErrorL(const CMIDletSuiteAttributes& /*aMIDlet*/, TRevocationMsg /*aRevocationMsg*/, const TOCSPOutcome* /*aOCSPOutcome*/) + { + Stderr().Write(_L("\r\nOCSP Error. Aborting installation.\r\n")); + } + +TBool CSwiMidletInstallerAO::MIDletInUseL(const CMIDletSuiteAttributes& /*aMIDlet*/) + { + TBool response = EFalse; // EFalse indicates we don't continue with uninstallation + if (!iQuiet) + { + // print the question + Stdout().Write(_L("\r\nMidlet is currently open. Continue installing? [y/n]\r\n")); + + // get the answer + TUserInput in; + const TInt error = Stdin().Read(in); + if ((error == KErrNone) && (in.MatchF(KSwiYes) == 0)) + { + response = ETrue; + } + } + if (!response) + { + Stderr().Write(_L("Uninstall aborted. Midlet has not been closed.\r\n")); + } + return response; + } + +void CSwiMidletInstallerAO::OTAReportResponseL(TInt aOTAResponseCode, const TDesC& /*aReportBody*/) + { + if (iVerbose) + { + switch (aOTAResponseCode) + { + case CJavaMIDletInstallationResult::EOkay: + Stdout().Write(_L("\r\nComplete\r\n")); + break; + + default: + Stdout().Write(_L("Abort\r\n")); + break; + }; + } + } + +TInt CSwiMidletInstallerAO::CopyStarted(TInt /*aSize*/) + { + return KErrNone; + } + +TInt CSwiMidletInstallerAO::DownloadStarted(TInt /*aSize*/) + { + if (iVerbose) + { + Stdout().Write(_L("Downloading midlet\r\n")); + } + return KErrNone; + } + +TInt CSwiMidletInstallerAO::UpdateProgress(TInt /*aSize*/) + { + if (iVerbose) + { + Stdout().Write(_L(".")); + } + return KErrNone; + } + +TBool CSwiMidletInstallerAO::GetUsernamePasswordL(HBufC8*& /*aUsername*/, HBufC8*& /*aPassword*/) + { + if (iVerbose) + { + Stdout().Write(_L("\r\nTODO: CCmdSwi::GetUsernamePasswordL\r\n")); + } + return EFalse; + } + +TBool CSwiMidletInstallerAO::ConfirmRemovalL(const TDesC& /*aRemovalMessage*/) + { + TBool response = ETrue; // default behaviour is to continue the uninstall + return response; + } + +void CSwiMidletInstallerAO::InitialiseProgressBarL(TInt /*aMaximumLength*/) + { + } + +void CSwiMidletInstallerAO::UpdateProgressBarL(TInt /*aUnits*/) + { + if (iVerbose) + { + Stdout().Write(_L(".")); + } + } + +TBool CSwiMidletInstallerAO::MIDletInUseL() + { + TBool response = EFalse; // EFalse indicates we don't continue with uninstallation + if (!iQuiet) + { + // print the question + Stdout().Write(_L("\r\nApplication is currently open. Continue uninstalling? [y/n]\r\n")); + + // get the answer + TUserInput in; + const TInt error = Stdin().Read(in); + if ((error == KErrNone) && (in.MatchF(KSwiYes) == 0)) + { + response = ETrue; + } + } + return response; + } + +TBool CSwiMidletInstallerAO::FileInUseL(const TDesC& /*aFileName*/) + { + TBool response = EFalse; // EFalse indicates we don't continue with uninstallation + if (!iQuiet) + { + // print the question + Stdout().Write(_L("\r\nApplication has a file handle open. Continue uninstalling? [y/n]\r\n")); + + // get the answer + TUserInput in; + const TInt error = Stdin().Read(in); + if ((error == KErrNone) && (in.MatchF(KSwiYes) == 0)) + { + response = ETrue; + } + } + return response; + } + +#endif // SYMBIAN_JAVA_NOT_INCLUDED + +#ifdef EXE_BUILD +EXE_BOILER_PLATE(CCmdSwi) +#endif +