Mozilla/mozilla/xpinstall/src/nsInstall.cpp
dveditz%netscape.com 5df7fedc87 bug 28896 register file versions r=ssu,sr=mscott
bug 45939 File.remove() returns bogus error,r=sgehani,sr=alecf
bug 7022  make platform/build info available to XPInstall script r=sgehani,sr=mscott
bug 47258 more detailed error reporting failing to install file, r=sgehani,sr=mscott
bug 62916 refresh plugins from install script r=ssu,sr=mscott


git-svn-id: svn://10.0.0.236/trunk@89610 18797224-902f-48f8-a5cc-f745e15eee43
2001-03-14 05:30:25 +00:00

2820 lines
71 KiB
C++

/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is Mozilla Communicator client code,
* released March 31, 1998.
*
* The Initial Developer of the Original Code is Netscape Communications
* Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Daniel Veditz <dveditz@netscape.com>
* Douglas Turner <dougt@netscape.com>
* Pierre Phaneuf <pp@ludusdesign.com>
*/
#include "nscore.h"
#include "nsIFactory.h"
#include "nsISupports.h"
#include "nsRepository.h"
#include "nsIServiceManager.h"
#include "nsHashtable.h"
#include "nsFileStream.h"
#include "nsIFileChannel.h"
#include "nsSpecialSystemDirectory.h"
#include "nsDirectoryService.h"
#include "nsDirectoryServiceDefs.h"
#include "nsIPref.h"
#include "prmem.h"
#include "plstr.h"
#include "prprf.h"
#include "VerReg.h"
#include "nsInstall.h"
#include "nsInstallFolder.h"
#include "nsInstallVersion.h"
#include "nsInstallFile.h"
#include "nsInstallExecute.h"
#include "nsInstallPatch.h"
#include "nsInstallUninstall.h"
#include "nsInstallResources.h"
#include "nsXPIProxy.h"
#include "nsRegisterItem.h"
#include "nsNetUtil.h"
#include "nsIProxyObjectManager.h"
#include "nsProxiedService.h"
#include "nsICommonDialogs.h"
#include "nsIPrompt.h"
#ifdef _WINDOWS
#include "nsWinReg.h"
#include "nsWinProfile.h"
#endif
#include "nsInstallFileOpEnums.h"
#include "nsInstallFileOpItem.h"
#ifdef XP_MAC
#include "Gestalt.h"
#include "nsAppleSingleDecoder.h"
#include "nsILocalFileMac.h"
#endif
#include "nsILocalFile.h"
#include "nsIURL.h"
#if defined(XP_UNIX) || defined(XP_BEOS)
#include <sys/utsname.h>
#endif /* XP_UNIX */
#if defined(XP_PC) && !defined(XP_OS2)
#include <windows.h>
#endif
static NS_DEFINE_IID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
static NS_DEFINE_IID(kIEventQueueServiceIID, NS_IEVENTQUEUESERVICE_IID);
static NS_DEFINE_IID(kProxyObjectManagerCID, NS_PROXYEVENT_MANAGER_CID);
static NS_DEFINE_CID(kCommonDialogsCID, NS_CommonDialog_CID);
static NS_DEFINE_CID(kStringBundleServiceCID, NS_STRINGBUNDLESERVICE_CID);
static NS_DEFINE_IID(kIStringBundleServiceIID, NS_ISTRINGBUNDLESERVICE_IID);
#define kInstallLocaleProperties "chrome://global/locale/commonDialogs.properties"
MOZ_DECL_CTOR_COUNTER(nsInstallInfo)
nsInstallInfo::nsInstallInfo(PRUint32 aInstallType,
nsIFile* aFile,
const PRUnichar* aURL,
const PRUnichar* aArgs,
PRUint32 flags,
nsIXPIListener* aListener,
nsIDOMWindowInternal* aParentWindow,
nsIChromeRegistry* aChromeReg)
: mError(0),
mType(aInstallType),
mFlags(flags),
mURL(aURL),
mArgs(aArgs),
mFile(aFile),
mListener(aListener),
mParent(aParentWindow),
mChromeReg(aChromeReg)
{
MOZ_COUNT_CTOR(nsInstallInfo);
}
nsInstallInfo::~nsInstallInfo()
{
MOZ_COUNT_DTOR(nsInstallInfo);
}
static NS_DEFINE_CID(kStandardURLCID, NS_STANDARDURL_CID);
static NS_DEFINE_IID(kISoftwareUpdateIID, NS_ISOFTWAREUPDATE_IID);
static NS_DEFINE_IID(kSoftwareUpdateCID, NS_SoftwareUpdate_CID);
static NS_DEFINE_IID(kIZipReaderIID, NS_IZIPREADER_IID);
static NS_DEFINE_IID(kZipReaderCID, NS_ZIPREADER_CID);
MOZ_DECL_CTOR_COUNTER(nsInstall)
nsInstall::nsInstall(nsIZipReader * theJARFile)
{
MOZ_COUNT_CTOR(nsInstall);
mScriptObject = nsnull; // this is the jsobject for our context
mVersionInfo = nsnull; // this is the version information passed to us in StartInstall()
mInstalledFiles = nsnull; // the list of installed objects
// mRegistryPackageName = ""; // this is the name that we will add into the registry for the component we are installing
// mUIName = ""; // this is the name that will be displayed in UI.
mPatchList = nsnull;
mUninstallPackage = PR_FALSE;
mRegisterPackage = PR_FALSE;
mStatusSent = PR_FALSE;
mStartInstallCompleted = PR_FALSE;
mJarFileLocation = nsnull;
//mInstallArguments = "";
mPackageFolder = nsnull;
// mJarFileData is an opaque handle to the jarfile.
mJarFileData = theJARFile;
nsISoftwareUpdate *su;
nsresult rv = nsServiceManager::GetService(kSoftwareUpdateCID,
kISoftwareUpdateIID,
(nsISupports**) &su);
if (NS_SUCCEEDED(rv))
{
su->GetMasterListener( getter_AddRefs(mListener) );
}
su->Release();
// get the resourced xpinstall string bundle
mStringBundle = nsnull;
NS_WITH_PROXIED_SERVICE( nsIStringBundleService,
service,
kStringBundleServiceCID,
NS_UI_THREAD_EVENTQ,
&rv );
if (NS_SUCCEEDED(rv) && service)
{
nsILocale* locale = nsnull;
rv = service->CreateBundle( XPINSTALL_BUNDLE_URL, locale,
getter_AddRefs(mStringBundle) );
}
}
nsInstall::~nsInstall()
{
if (mVersionInfo != nsnull)
delete mVersionInfo;
if (mPackageFolder)
delete mPackageFolder;
MOZ_COUNT_DTOR(nsInstall);
}
PRInt32
nsInstall::SetScriptObject(void *aScriptObject)
{
mScriptObject = (JSObject*) aScriptObject;
return NS_OK;
}
#ifdef _WINDOWS
PRInt32
nsInstall::SaveWinRegPrototype(void *aScriptObject)
{
mWinRegObject = (JSObject*) aScriptObject;
return NS_OK;
}
PRInt32
nsInstall::SaveWinProfilePrototype(void *aScriptObject)
{
mWinProfileObject = (JSObject*) aScriptObject;
return NS_OK;
}
JSObject*
nsInstall::RetrieveWinRegPrototype()
{
return mWinRegObject;
}
JSObject*
nsInstall::RetrieveWinProfilePrototype()
{
return mWinProfileObject;
}
#endif
PRInt32
nsInstall::GetInstallPlatform(nsCString& aPlatform)
{
if (mInstallPlatform.IsEmpty())
{
// Duplicated from mozilla/netwerk/protocol/http/src/nsHTTPHandler.cpp
// which is not yet available in a wizard install
// Gather platform.
#if defined(XP_OS2)
mInstallPlatform = "OS/2";
#elif defined(XP_PC)
mInstallPlatform = "Windows";
#elif defined(RHAPSODY)
mInstallPlatform = "Macintosh";
#elif defined (XP_UNIX)
mInstallPlatform = "X11";
#elif defined(XP_BEOS)
mInstallPlatform = "BeOS";
#elif defined(XP_MAC)
mInstallPlatform = "Macintosh";
#endif
mInstallPlatform += "; ";
// Gather OS/CPU.
#if defined(XP_OS2)
ULONG os2ver = 0;
DosQuerySysInfo(QSV_VERSION_MINOR, QSV_VERSION_MINOR,
&os2ver, sizeof(os2ver));
if (os2ver == 11)
mInstallPlatform += "2.11";
else if (os2ver == 30)
mInstallPlatform += "Warp 3";
else if (os2ver == 40)
mInstallPlatform += "Warp 4";
else if (os2ver == 45)
mInstallPlatform += "Warp 4.5";
else
mInstallPlatform += "Warp ???";
#elif defined(XP_PC)
OSVERSIONINFO info = { sizeof OSVERSIONINFO };
if (GetVersionEx(&info)) {
if ( info.dwPlatformId == VER_PLATFORM_WIN32_NT ) {
if (info.dwMajorVersion == 3) {
mInstallPlatform += "WinNT3.51";
}
else if (info.dwMajorVersion == 4) {
mInstallPlatform += "WinNT4.0";
}
else if (info.dwMajorVersion == 5) {
mInstallPlatform += "Windows NT 5.0";
}
else {
mInstallPlatform += "WinNT";
}
} else if (info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
if (info.dwMinorVersion == 90)
mInstallPlatform += "Win 9x 4.90";
else if (info.dwMinorVersion > 0)
mInstallPlatform += "Win98";
else
mInstallPlatform += "Win95";
}
}
#elif defined (XP_UNIX) || defined (XP_BEOS)
struct utsname name;
int ret = uname(&name);
if (ret >= 0) {
mInstallPlatform += (char*)name.sysname;
mInstallPlatform += ' ';
mInstallPlatform += (char*)name.release;
mInstallPlatform += ' ';
mInstallPlatform += (char*)name.machine;
}
#elif defined (XP_MAC)
mInstallPlatform += "PPC";
#endif
}
aPlatform = mInstallPlatform;
return NS_OK;
}
void
nsInstall::InternalAbort(PRInt32 errcode)
{
if (mListener)
{
mListener->FinalStatus(mInstallURL.GetUnicode(), errcode);
mStatusSent = PR_TRUE;
}
nsInstallObject* ie;
if (mInstalledFiles != nsnull)
{
for (PRInt32 i = mInstalledFiles->Count(); i >= 0; i--)
{
ie = (nsInstallObject *)mInstalledFiles->ElementAt(i);
if (ie)
ie->Abort();
}
}
CleanUp();
}
PRInt32
nsInstall::AbortInstall(PRInt32 aErrorNumber)
{
InternalAbort(aErrorNumber);
return NS_OK;
}
PRInt32
nsInstall::AddDirectory(const nsString& aRegName,
const nsString& aVersion,
const nsString& aJarSource,
nsInstallFolder *aFolder,
const nsString& aSubdir,
PRInt32 aMode,
PRInt32* aReturn)
{
nsInstallFile* ie = nsnull;
PRInt32 result;
if ( aJarSource.IsEmpty() || aFolder == nsnull )
{
*aReturn = SaveError(nsInstall::INVALID_ARGUMENTS);
return NS_OK;
}
result = SanityCheck();
if (result != nsInstall::SUCCESS)
{
*aReturn = SaveError( result );
return NS_OK;
}
nsString qualifiedRegName;
if ( aRegName.IsEmpty())
{
// Default subName = location in jar file
*aReturn = GetQualifiedRegName( aJarSource, qualifiedRegName);
}
else
{
*aReturn = GetQualifiedRegName( aRegName, qualifiedRegName );
}
if (*aReturn != SUCCESS)
{
return NS_OK;
}
nsString qualifiedVersion = aVersion;
if (qualifiedVersion.IsEmpty())
{
// assume package version for overriden forms that don't take version info
*aReturn = mVersionInfo->ToString(qualifiedVersion);
if (NS_FAILED(*aReturn))
{
SaveError( nsInstall::UNEXPECTED_ERROR );
return NS_OK;
}
}
nsString subdirectory(aSubdir);
if (!subdirectory.IsEmpty())
{
subdirectory.AppendWithConversion("/");
}
nsVoidArray *paths = new nsVoidArray();
if (paths == nsnull)
{
*aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
return NS_OK;
}
result = ExtractDirEntries(aJarSource, paths);
if (result != nsInstall::SUCCESS)
{
*aReturn = SaveError( result );
return NS_OK;
}
PRInt32 count = paths->Count();
if (count == 0)
{
*aReturn = SaveError( nsInstall::DOES_NOT_EXIST );
return NS_OK;
}
for (PRInt32 i=0; i < count; i++)
{
nsString *thisPath = (nsString *)paths->ElementAt(i);
nsString newJarSource = aJarSource;
newJarSource.AppendWithConversion("/");
newJarSource += *thisPath;
nsString fullRegName = qualifiedRegName;
fullRegName.AppendWithConversion("/");
fullRegName += *thisPath;
nsString newSubDir;
if (!subdirectory.IsEmpty())
{
newSubDir = subdirectory;
}
newSubDir += *thisPath;
ie = new nsInstallFile( this,
fullRegName,
qualifiedVersion,
newJarSource,
aFolder,
newSubDir,
aMode,
(i == 0), // register the first one only
&result);
if (ie == nsnull)
{
*aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
return NS_OK;
}
if (result == nsInstall::SUCCESS)
{
result = ScheduleForInstall( ie );
}
else
{
delete ie;
}
}
DeleteVector(paths);
*aReturn = SaveError( result );
return NS_OK;
}
PRInt32
nsInstall::AddDirectory(const nsString& aRegName,
const nsString& aVersion,
const nsString& aJarSource,
nsInstallFolder *aFolder,
const nsString& aSubdir,
PRInt32* aReturn)
{
return AddDirectory(aRegName,
aVersion,
aJarSource,
aFolder,
aSubdir,
INSTALL_NO_COMPARE,
aReturn);
}
PRInt32
nsInstall::AddDirectory(const nsString& aRegName,
const nsString& aJarSource,
nsInstallFolder *aFolder,
const nsString& aSubdir,
PRInt32* aReturn)
{
return AddDirectory(aRegName,
nsAutoString(),
aJarSource,
aFolder,
aSubdir,
INSTALL_NO_COMPARE,
aReturn);
}
PRInt32
nsInstall::AddDirectory(const nsString& aJarSource,
PRInt32* aReturn)
{
if(mPackageFolder == nsnull)
{
*aReturn = SaveError( nsInstall::PACKAGE_FOLDER_NOT_SET );
return NS_OK;
}
return AddDirectory(nsAutoString(),
nsAutoString(),
aJarSource,
mPackageFolder,
nsAutoString(),
INSTALL_NO_COMPARE,
aReturn);
}
PRInt32
nsInstall::AddSubcomponent(const nsString& aRegName,
const nsString& aVersion,
const nsString& aJarSource,
nsInstallFolder *aFolder,
const nsString& aTargetName,
PRInt32 aMode,
PRInt32* aReturn)
{
nsInstallFile* ie;
nsString qualifiedRegName;
nsString qualifiedVersion = aVersion;
nsString tempTargetName = aTargetName;
PRInt32 errcode = nsInstall::SUCCESS;
if(aJarSource.IsEmpty() || aFolder == nsnull )
{
*aReturn = SaveError( nsInstall::INVALID_ARGUMENTS );
return NS_OK;
}
PRInt32 result = SanityCheck();
if (result != nsInstall::SUCCESS)
{
*aReturn = SaveError( result );
return NS_OK;
}
if( aTargetName.IsEmpty() )
{
PRInt32 pos = aJarSource.RFindChar('/');
if ( pos == kNotFound )
tempTargetName = aJarSource;
else
aJarSource.Mid(tempTargetName, pos+1, -1);
}
if (qualifiedVersion.IsEmpty())
qualifiedVersion.AssignWithConversion("0.0.0.0");
if ( aRegName.IsEmpty() )
{
// Default subName = location in jar file
*aReturn = GetQualifiedRegName( aJarSource, qualifiedRegName);
}
else
{
*aReturn = GetQualifiedRegName( aRegName, qualifiedRegName );
}
if (*aReturn != SUCCESS)
{
return NS_OK;
}
ie = new nsInstallFile( this,
qualifiedRegName,
qualifiedVersion,
aJarSource,
aFolder,
tempTargetName,
aMode,
PR_TRUE,
&errcode );
if (ie == nsnull)
{
*aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
return NS_OK;
}
if (errcode == nsInstall::SUCCESS)
{
errcode = ScheduleForInstall( ie );
}
else
{
delete ie;
}
*aReturn = SaveError( errcode );
return NS_OK;
}
PRInt32
nsInstall::AddSubcomponent(const nsString& aRegName,
const nsString& aVersion,
const nsString& aJarSource,
nsInstallFolder* aFolder,
const nsString& aTargetName,
PRInt32* aReturn)
{
return AddSubcomponent(aRegName,
aVersion,
aJarSource,
aFolder,
aTargetName,
INSTALL_NO_COMPARE,
aReturn);
}
PRInt32
nsInstall::AddSubcomponent(const nsString& aRegName,
const nsString& aJarSource,
nsInstallFolder* aFolder,
const nsString& aTargetName,
PRInt32* aReturn)
{
PRInt32 result = SanityCheck();
if (result != nsInstall::SUCCESS)
{
*aReturn = SaveError( result );
return NS_OK;
}
nsString version;
*aReturn = mVersionInfo->ToString(version);
if (NS_FAILED(*aReturn))
{
SaveError( nsInstall::UNEXPECTED_ERROR );
return NS_OK;
}
return AddSubcomponent(aRegName,
version,
aJarSource,
aFolder,
aTargetName,
INSTALL_NO_COMPARE,
aReturn);
}
PRInt32
nsInstall::AddSubcomponent(const nsString& aJarSource,
PRInt32* aReturn)
{
if(mPackageFolder == nsnull)
{
*aReturn = SaveError( nsInstall::PACKAGE_FOLDER_NOT_SET );
return NS_OK;
}
PRInt32 result = SanityCheck();
if (result != nsInstall::SUCCESS)
{
*aReturn = SaveError( result );
return NS_OK;
}
nsString version;
*aReturn = mVersionInfo->ToString(version);
if (NS_FAILED(*aReturn))
{
SaveError( nsInstall::UNEXPECTED_ERROR );
return NS_OK;
}
return AddSubcomponent(nsAutoString(),
version,
aJarSource,
mPackageFolder,
nsAutoString(),
INSTALL_NO_COMPARE,
aReturn);
}
PRInt32
nsInstall::DiskSpaceAvailable(const nsString& aFolder, PRInt64* aReturn)
{
PRInt32 result = SanityCheck();
if (result != nsInstall::SUCCESS)
{
double d = SaveError( result );
LL_L2D(d, *aReturn);
return NS_OK;
}
nsAutoCString temp(aFolder);
nsCOMPtr<nsILocalFile> folder;
NS_NewLocalFile(temp, PR_TRUE, getter_AddRefs(folder));
result = folder->GetDiskSpaceAvailable(aReturn);
return NS_OK;
}
PRInt32
nsInstall::Execute(const nsString& aJarSource, const nsString& aArgs, PRBool aBlocking, PRInt32* aReturn)
{
PRInt32 result = SanityCheck();
if (result != nsInstall::SUCCESS)
{
*aReturn = SaveError( result );
return NS_OK;
}
nsInstallExecute* ie = new nsInstallExecute(this, aJarSource, aArgs, aBlocking, &result);
if (ie == nsnull)
{
*aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
return NS_OK;
}
if (result == nsInstall::SUCCESS)
{
result = ScheduleForInstall( ie );
}
*aReturn = SaveError(result);
return NS_OK;
}
PRInt32
nsInstall::FinalizeInstall(PRInt32* aReturn)
{
PRInt32 result = SUCCESS;
PRBool rebootNeeded = PR_FALSE;
*aReturn = SanityCheck();
if (*aReturn != nsInstall::SUCCESS)
{
SaveError( *aReturn );
if (mListener)
{
mListener->FinalStatus(mInstallURL.GetUnicode(), *aReturn);
mStatusSent = PR_TRUE;
}
return NS_OK;
}
if ( mInstalledFiles->Count() > 0 )
{
if ( mUninstallPackage )
{
VR_UninstallCreateNode( NS_CONST_CAST(char *, NS_ConvertUCS2toUTF8(mRegistryPackageName).get()),
NS_CONST_CAST(char *, NS_ConvertUCS2toUTF8(mUIName).get()));
}
// Install the Component into the Version Registry.
if (mVersionInfo)
{
nsString versionString;
nsCString path;
mVersionInfo->ToString(versionString);
nsCAutoString versionCString;
versionCString.AssignWithConversion(versionString);
if (mPackageFolder)
mPackageFolder->GetDirectoryPath(path);
VR_Install( NS_CONST_CAST(char *, NS_ConvertUCS2toUTF8(mRegistryPackageName).get()),
NS_CONST_CAST(char *, path.get()),
NS_CONST_CAST(char *, versionCString.get()),
PR_TRUE );
}
nsInstallObject* ie = nsnull;
for (PRInt32 i=0; i < mInstalledFiles->Count(); i++)
{
ie = (nsInstallObject*)mInstalledFiles->ElementAt(i);
NS_ASSERTION(ie, "NULL object in install queue!");
if (ie == NULL)
continue;
if (mListener)
{
char *objString = ie->toString();
if (objString)
{
mListener->FinalizeProgress(NS_ConvertASCIItoUCS2(objString).GetUnicode(),
(i+1), mInstalledFiles->Count());
delete [] objString;
}
}
result = ie->Complete();
if (result != nsInstall::SUCCESS)
{
if ( result == REBOOT_NEEDED )
{
rebootNeeded = PR_TRUE;
result = SUCCESS;
}
else
{
InternalAbort( result );
break;
}
}
}
if ( result == SUCCESS )
{
if ( rebootNeeded )
*aReturn = SaveError( REBOOT_NEEDED );
// XXX for now all successful installs will trigger an Autoreg.
// We eventually want to do this only when flagged.
HREG reg;
if ( REGERR_OK == NR_RegOpen("", &reg) )
{
RKEY xpiRoot;
REGERR err;
err = NR_RegAddKey(reg,ROOTKEY_COMMON,XPI_ROOT_KEY,&xpiRoot);
if ( err == REGERR_OK )
NR_RegSetEntryString(reg, xpiRoot, XPI_AUTOREG_VAL, "yes");
NR_RegClose(reg);
}
}
else
*aReturn = SaveError( result );
if (mListener)
{
mListener->FinalStatus(mInstallURL.GetUnicode(), *aReturn);
mStatusSent = PR_TRUE;
}
}
else
{
// no actions queued: don't register the package version
// and no need for user confirmation
if (mListener)
{
mListener->FinalStatus(mInstallURL.GetUnicode(), *aReturn);
mStatusSent = PR_TRUE;
}
}
CleanUp();
return NS_OK;
}
#ifdef XP_MAC
#define GESTALT_CHAR_CODE(x) (((unsigned long) ((x[0]) & 0x000000FF)) << 24) \
| (((unsigned long) ((x[1]) & 0x000000FF)) << 16) \
| (((unsigned long) ((x[2]) & 0x000000FF)) << 8) \
| (((unsigned long) ((x[3]) & 0x000000FF)))
#endif /* XP_MAC */
PRInt32
nsInstall::Gestalt(const nsString& aSelector, PRInt32* aReturn)
{
*aReturn = nsnull;
PRInt32 result = SanityCheck();
if (result != nsInstall::SUCCESS)
{
*aReturn = SaveError( result );
return NS_OK;
}
#ifdef XP_MAC
long response = 0;
char selectorChars[4];
int i;
OSErr err = noErr;
OSType selector;
if (aSelector.IsEmpty())
{
return NS_OK;
}
for (i=0; i<4; i++)
selectorChars[i] = aSelector.CharAt(i);
selector = GESTALT_CHAR_CODE(selectorChars);
err = ::Gestalt(selector, &response);
if (err != noErr)
*aReturn = err;
else
*aReturn = response;
#endif
return NS_OK;
}
PRInt32
nsInstall::GetComponentFolder(const nsString& aComponentName, const nsString& aSubdirectory, nsInstallFolder** aNewFolder)
{
long err;
char dir[MAXREGPATHLEN];
nsFileSpec nsfsDir;
nsresult res = NS_OK;
if(!aNewFolder)
return INVALID_ARGUMENTS;
*aNewFolder = nsnull;
nsString tempString;
if ( GetQualifiedPackageName(aComponentName, tempString) != SUCCESS )
{
return NS_OK;
}
NS_ConvertUCS2toUTF8 componentCString(tempString);
if((err = VR_GetDefaultDirectory( NS_CONST_CAST(char *, componentCString.get()), sizeof(dir), dir )) != REGERR_OK)
{
if((err = VR_GetPath( NS_CONST_CAST(char *, componentCString.get()), sizeof(dir), dir )) == REGERR_OK)
{
int i;
nsString dirStr; dirStr.AssignWithConversion(dir);
if ( (i = dirStr.RFindChar(FILESEP)) > 0 )
{
// i is the index in the string, not the total number of
// characters in the string. ToCString() requires the
// total number of characters in the string to copy,
// therefore add 1 to it.
dirStr.Truncate(i + 1);
dirStr.ToCString(dir, MAXREGPATHLEN);
}
}
else
{
*dir = '\0';
}
}
else
{
*dir = '\0';
}
if(*dir != '\0')
{
nsInstallFolder * folder = new nsInstallFolder();
if (!folder) return NS_ERROR_OUT_OF_MEMORY;
res = folder->Init(NS_ConvertASCIItoUCS2(dir), aSubdirectory);
if (NS_FAILED(res))
{
delete folder;
}
else
{
*aNewFolder = folder;
}
}
return res;
}
PRInt32
nsInstall::GetComponentFolder(const nsString& aComponentName, nsInstallFolder** aNewFolder)
{
return GetComponentFolder(aComponentName, nsAutoString(), aNewFolder);
}
PRInt32
nsInstall::GetFolder(const nsString& targetFolder, const nsString& aSubdirectory, nsInstallFolder** aNewFolder)
{
/* This version of GetFolder takes an nsString object as the first param */
if (!aNewFolder)
return INVALID_ARGUMENTS;
* aNewFolder = nsnull;
nsInstallFolder* folder = new nsInstallFolder();
if (folder == nsnull)
{
return NS_ERROR_OUT_OF_MEMORY;
}
nsresult res = folder->Init(targetFolder, aSubdirectory);
if (NS_FAILED(res))
{
delete folder;
return res;
}
*aNewFolder = folder;
return NS_OK;
}
PRInt32
nsInstall::GetFolder(const nsString& targetFolder, nsInstallFolder** aNewFolder)
{
/* This version of GetFolder takes an nsString object as the only param */
return GetFolder(targetFolder, nsAutoString(), aNewFolder);
}
PRInt32
nsInstall::GetFolder( nsInstallFolder& aTargetFolderObj, const nsString& aSubdirectory, nsInstallFolder** aNewFolder )
{
/* This version of GetFolder takes an nsString object as the first param */
if (!aNewFolder)
return INVALID_ARGUMENTS;
* aNewFolder = nsnull;
nsInstallFolder* folder = new nsInstallFolder();
if (folder == nsnull)
{
return NS_ERROR_OUT_OF_MEMORY;
}
nsresult res = folder->Init(aTargetFolderObj, aSubdirectory);
if (NS_FAILED(res))
{
delete folder;
return res;
}
*aNewFolder = folder;
return NS_OK;
}
PRInt32
nsInstall::GetLastError(PRInt32* aReturn)
{
*aReturn = mLastError;
return NS_OK;
}
PRInt32
nsInstall::GetWinProfile(const nsString& aFolder, const nsString& aFile, JSContext* jscontext, JSClass* WinProfileClass, jsval* aReturn)
{
*aReturn = JSVAL_NULL;
PRInt32 result = SanityCheck();
if (result != nsInstall::SUCCESS)
{
*aReturn = SaveError( result );
return NS_OK;
}
#ifdef _WINDOWS
JSObject* winProfileObject;
nsWinProfile* nativeWinProfileObject = new nsWinProfile(this, aFolder, aFile);
if (nativeWinProfileObject == nsnull)
return NS_OK;
JSObject* winProfilePrototype = this->RetrieveWinProfilePrototype();
winProfileObject = JS_NewObject(jscontext, WinProfileClass, winProfilePrototype, NULL);
if(winProfileObject == NULL)
return NS_OK;
JS_SetPrivate(jscontext, winProfileObject, nativeWinProfileObject);
*aReturn = OBJECT_TO_JSVAL(winProfileObject);
#endif /* _WINDOWS */
return NS_OK;
}
PRInt32
nsInstall::GetWinRegistry(JSContext* jscontext, JSClass* WinRegClass, jsval* aReturn)
{
*aReturn = JSVAL_NULL;
PRInt32 result = SanityCheck();
if (result != nsInstall::SUCCESS)
{
*aReturn = SaveError( result );
return NS_OK;
}
#ifdef _WINDOWS
JSObject* winRegObject;
nsWinReg* nativeWinRegObject = new nsWinReg(this);
if (nativeWinRegObject == nsnull)
return NS_OK;
JSObject* winRegPrototype = this->RetrieveWinRegPrototype();
winRegObject = JS_NewObject(jscontext, WinRegClass, winRegPrototype, NULL);
if(winRegObject == NULL)
return NS_OK;
JS_SetPrivate(jscontext, winRegObject, nativeWinRegObject);
*aReturn = OBJECT_TO_JSVAL(winRegObject);
#endif /* _WINDOWS */
return NS_OK;
}
PRInt32
nsInstall::LoadResources(JSContext* cx, const nsString& aBaseName, jsval* aReturn)
{
PRInt32 result = SanityCheck();
if (result != nsInstall::SUCCESS)
{
*aReturn = SaveError( result );
return NS_OK;
}
nsresult ret;
nsCOMPtr<nsIFile> resFile;
nsCOMPtr<nsIFileURL> resFileURL = nsnull;
nsIURI *url = nsnull;
nsILocale* locale = nsnull;
nsIStringBundleService* service = nsnull;
nsIEventQueueService* pEventQueueService = nsnull;
nsIStringBundle* bundle = nsnull;
nsIBidirectionalEnumerator* propEnum = nsnull;
*aReturn = JSVAL_NULL;
jsval v = JSVAL_NULL;
// set up JSObject to return
JS_GetProperty( cx, JS_GetGlobalObject( cx ), "Object", &v );
if (!v)
{
return NS_ERROR_NULL_POINTER;
}
JSClass *objclass = JS_GetClass( cx, JSVAL_TO_OBJECT(v) );
JSObject *res = JS_NewObject( cx, objclass, JSVAL_TO_OBJECT(v), 0 );
// extract properties file
// XXX append locale info: lang code, country code, .properties suffix to aBaseName
PRInt32 err = ExtractFileFromJar(aBaseName, nsnull, getter_AddRefs(resFile));
if ( (!resFile) || (err != nsInstall::SUCCESS) )
{
SaveError( err );
return NS_OK;
}
// initialize string bundle and related services
ret = nsServiceManager::GetService(kStringBundleServiceCID,
kIStringBundleServiceIID, (nsISupports**) &service);
if (NS_FAILED(ret))
goto cleanup;
ret = nsServiceManager::GetService(kEventQueueServiceCID,
kIEventQueueServiceIID, (nsISupports**) &pEventQueueService);
if (NS_FAILED(ret))
goto cleanup;
ret = pEventQueueService->CreateThreadEventQueue();
if (NS_FAILED(ret))
goto cleanup;
// construct properties file URL as required by StringBundle interface
//nsCOMPtr<nsIFileURL> url;
ret = nsComponentManager::CreateInstance(kStandardURLCID, nsnull,
NS_GET_IID(nsIFileURL),
getter_AddRefs(resFileURL));
if (NS_FAILED(ret)) goto cleanup;
ret = resFileURL->SetFile(resFile);
if (NS_FAILED(ret)) goto cleanup;
// get the string bundle using the extracted properties file
#if 1
{
char* spec = nsnull;
ret = resFileURL->GetSpec(&spec);
if (NS_FAILED(ret)) {
printf("cannot get url spec\n");
nsServiceManager::ReleaseService(kStringBundleServiceCID, service);
nsCRT::free(spec);
return ret;
}
ret = service->CreateBundle(spec, locale, &bundle);
nsCRT::free(spec);
}
#else
ret = service->CreateBundle(url, locale, &bundle);
#endif
if (NS_FAILED(ret))
goto cleanup;
ret = bundle->GetEnumeration(&propEnum);
if (NS_FAILED(ret))
goto cleanup;
// set the variables of the JSObject to return using the StringBundle's
// enumeration service
ret = propEnum->First();
if (NS_FAILED(ret))
goto cleanup;
while (NS_SUCCEEDED(ret))
{
nsIPropertyElement* propElem = nsnull;
ret = propEnum->CurrentItem((nsISupports**)&propElem);
if (NS_FAILED(ret))
goto cleanup;
PRUnichar *pKey = nsnull;
PRUnichar *pVal = nsnull;
ret = propElem->GetKey(&pKey);
if (NS_FAILED(ret))
goto cleanup;
ret = propElem->GetValue(&pVal);
if (NS_FAILED(ret))
goto cleanup;
nsAutoString keyAdjustedLengthBuff(pKey);
nsAutoString valAdjustedLengthBuff(pVal);
char* keyCStr = keyAdjustedLengthBuff.ToNewCString();
PRUnichar* valCStr = valAdjustedLengthBuff.ToNewUnicode();
if (keyCStr && valCStr)
{
JSString* propValJSStr = JS_NewUCStringCopyZ(cx, (jschar*) valCStr);
jsval propValJSVal = STRING_TO_JSVAL(propValJSStr);
JS_SetProperty(cx, res, keyCStr, &propValJSVal);
delete[] keyCStr;
delete[] valCStr;
}
if (pKey)
delete[] pKey;
if (pVal)
delete[] pVal;
ret = propEnum->Next();
}
*aReturn = OBJECT_TO_JSVAL(res);
ret = nsInstall::SUCCESS;
cleanup:
SaveError( ret );
// release services
NS_IF_RELEASE( service );
NS_IF_RELEASE( pEventQueueService );
// release file, URL, StringBundle, Enumerator
NS_IF_RELEASE( url );
NS_IF_RELEASE( bundle );
NS_IF_RELEASE( propEnum );
return NS_OK;
}
PRInt32
nsInstall::Patch(const nsString& aRegName, const nsString& aVersion, const nsString& aJarSource, nsInstallFolder* aFolder, const nsString& aTargetName, PRInt32* aReturn)
{
PRInt32 result = SanityCheck();
if (result != nsInstall::SUCCESS)
{
*aReturn = SaveError( result );
return NS_OK;
}
nsString qualifiedRegName;
*aReturn = GetQualifiedRegName( aRegName, qualifiedRegName);
if (*aReturn != SUCCESS)
{
return NS_OK;
}
if (!mPatchList)
{
mPatchList = new nsHashtable();
if (mPatchList == nsnull)
{
*aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
return NS_OK;
}
}
nsInstallPatch* ip = new nsInstallPatch( this,
qualifiedRegName,
aVersion,
aJarSource,
aFolder,
aTargetName,
&result);
if (ip == nsnull)
{
*aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
return NS_OK;
}
if (result == nsInstall::SUCCESS)
{
result = ScheduleForInstall( ip );
}
*aReturn = SaveError(result);
return NS_OK;
}
PRInt32
nsInstall::Patch(const nsString& aRegName, const nsString& aJarSource, nsInstallFolder* aFolder, const nsString& aTargetName, PRInt32* aReturn)
{
return Patch(aRegName, nsAutoString(), aJarSource, aFolder, aTargetName, aReturn);
}
PRInt32
nsInstall::RegisterChrome(nsIFile* chrome, PRUint32 chromeType, const char* path)
{
PRInt32 result = SanityCheck();
if (result != SUCCESS)
return SaveError( result );
if (!chrome || !chromeType)
return SaveError( INVALID_ARGUMENTS );
nsRegisterItem* ri = new nsRegisterItem(this, chrome, chromeType, path);
if (ri == nsnull)
return SaveError(OUT_OF_MEMORY);
else
return SaveError(ScheduleForInstall( ri ));
}
PRInt32
nsInstall::RefreshPlugins()
{
nsresult rv;
NS_WITH_SERVICE( nsIProxyObjectManager, pmgr, kProxyObjectManagerCID, &rv);
if (NS_SUCCEEDED(rv))
{
nsCOMPtr<nsPIXPIProxy> tmp = do_QueryInterface(new nsXPIProxy());
nsCOMPtr<nsPIXPIProxy> proxy;
rv = pmgr->GetProxyForObject( NS_UI_THREAD_EVENTQ, NS_GET_IID(nsPIXPIProxy),
tmp, PROXY_SYNC | PROXY_ALWAYS, getter_AddRefs(proxy) );
if (NS_SUCCEEDED(rv))
rv = proxy->RefreshPlugins(GetParentDOMWindow());
}
return rv;
}
PRInt32
nsInstall::ResetError()
{
mLastError = nsInstall::SUCCESS;
return NS_OK;
}
PRInt32
nsInstall::SetPackageFolder(nsInstallFolder& aFolder)
{
if (mPackageFolder)
delete mPackageFolder;
nsInstallFolder* folder = new nsInstallFolder();
if (folder == nsnull)
{
return NS_ERROR_OUT_OF_MEMORY;
}
nsresult res = folder->Init(aFolder, nsAutoString());
if (NS_FAILED(res))
{
delete folder;
return res;
}
mPackageFolder = folder;
return NS_OK;
}
PRInt32
nsInstall::StartInstall(const nsString& aUserPackageName, const nsString& aRegistryPackageName, const nsString& aVersion, PRInt32* aReturn)
{
if ( aUserPackageName.Length() == 0 )
{
// There must be some pretty name for the UI and the uninstall list
*aReturn = SaveError(INVALID_ARGUMENTS);
return NS_OK;
}
char szRegPackagePath[MAXREGPATHLEN];
*szRegPackagePath = '0';
*aReturn = nsInstall::SUCCESS;
ResetError();
mUserCancelled = PR_FALSE;
mUIName = aUserPackageName;
*aReturn = GetQualifiedPackageName( aRegistryPackageName, mRegistryPackageName );
if (*aReturn != nsInstall::SUCCESS)
{
return NS_OK;
}
if(REGERR_OK == VR_GetDefaultDirectory(
NS_CONST_CAST(char *, NS_ConvertUCS2toUTF8(mRegistryPackageName).get()),
sizeof(szRegPackagePath), szRegPackagePath))
{
nsInstallFolder* folder = new nsInstallFolder();
if (folder == nsnull)
{
return NS_ERROR_OUT_OF_MEMORY;
}
nsresult res = folder->Init(NS_ConvertASCIItoUCS2(szRegPackagePath), nsAutoString());
if (NS_FAILED(res))
{
delete folder;
}
else
{
mPackageFolder = folder;
}
}
else
{
mPackageFolder = nsnull;
}
if (mVersionInfo != nsnull)
delete mVersionInfo;
mVersionInfo = new nsInstallVersion();
if (mVersionInfo == nsnull)
{
*aReturn = nsInstall::OUT_OF_MEMORY;
return SaveError(nsInstall::OUT_OF_MEMORY);
}
mVersionInfo->Init(aVersion);
mInstalledFiles = new nsVoidArray();
if (mInstalledFiles == nsnull)
{
*aReturn = nsInstall::OUT_OF_MEMORY;
return SaveError(nsInstall::OUT_OF_MEMORY);
}
if (mListener)
mListener->InstallStarted(mInstallURL.GetUnicode(), mUIName.GetUnicode());
mStartInstallCompleted = PR_TRUE;
return NS_OK;
}
PRInt32
nsInstall::Uninstall(const nsString& aRegistryPackageName, PRInt32* aReturn)
{
PRInt32 result = SanityCheck();
if (result != nsInstall::SUCCESS)
{
*aReturn = SaveError( result );
return NS_OK;
}
nsString qualifiedPackageName;
*aReturn = GetQualifiedPackageName( aRegistryPackageName, qualifiedPackageName );
if (*aReturn != SUCCESS)
{
return NS_OK;
}
nsInstallUninstall *ie = new nsInstallUninstall( this,
qualifiedPackageName,
&result );
if (ie == nsnull)
{
*aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
return NS_OK;
}
if (result == nsInstall::SUCCESS)
{
result = ScheduleForInstall( ie );
}
else
{
delete ie;
}
*aReturn = SaveError(result);
return NS_OK;
}
////////////////////////////////////////
void
nsInstall::AddPatch(nsHashKey *aKey, nsIFile* fileName)
{
if (mPatchList != nsnull)
{
mPatchList->Put(aKey, fileName);
}
}
void
nsInstall::GetPatch(nsHashKey *aKey, nsIFile** fileName)
{
if (!fileName)
return;
else
*fileName = nsnull;
if (mPatchList != nsnull)
{
*fileName = (nsIFile*) mPatchList->Get(aKey);
}
}
PRInt32
nsInstall::FileOpDirCreate(nsInstallFolder& aTarget, PRInt32* aReturn)
{
nsCOMPtr<nsIFile> localFile = aTarget.GetFileSpec();
if (localFile == nsnull)
{
*aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
return NS_OK;
}
nsInstallFileOpItem* ifop = new nsInstallFileOpItem(this, NS_FOP_DIR_CREATE, localFile, aReturn);
if (ifop == nsnull)
{
*aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
return NS_OK;
}
PRInt32 result = SanityCheck();
if (result != nsInstall::SUCCESS)
{
delete ifop;
*aReturn = SaveError( result );
return NS_OK;
}
if (*aReturn == nsInstall::SUCCESS)
{
*aReturn = ScheduleForInstall( ifop );
}
SaveError(*aReturn);
return NS_OK;
}
PRInt32
nsInstall::FileOpDirGetParent(nsInstallFolder& aTarget, nsInstallFolder** theParentFolder)
{
nsCOMPtr<nsIFile> parent;
nsCOMPtr<nsIFile> localFile = aTarget.GetFileSpec();
nsresult rv = localFile->GetParent(getter_AddRefs(parent));
if (NS_SUCCEEDED(rv) && parent)
{
nsInstallFolder* folder = new nsInstallFolder();
if (folder == nsnull)
{
return NS_ERROR_OUT_OF_MEMORY;
}
folder->Init(parent);
*theParentFolder = folder;
}
else
theParentFolder = nsnull;
return NS_OK;
}
PRInt32
nsInstall::FileOpDirRemove(nsInstallFolder& aTarget, PRInt32 aFlags, PRInt32* aReturn)
{
nsCOMPtr<nsIFile> localFile = aTarget.GetFileSpec();
if (localFile == nsnull)
{
*aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
return NS_OK;
}
nsInstallFileOpItem* ifop = new nsInstallFileOpItem(this, NS_FOP_DIR_REMOVE, localFile, aFlags, aReturn);
if (ifop == nsnull)
{
*aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
return NS_OK;
}
PRInt32 result = SanityCheck();
if (result != nsInstall::SUCCESS)
{
delete ifop;
*aReturn = SaveError( result );
return NS_OK;
}
if (*aReturn == nsInstall::SUCCESS)
{
*aReturn = ScheduleForInstall( ifop );
}
SaveError(*aReturn);
return NS_OK;
}
PRInt32
nsInstall::FileOpDirRename(nsInstallFolder& aSrc, nsString& aTarget, PRInt32* aReturn)
{
nsCOMPtr<nsIFile> localFile = aSrc.GetFileSpec();
if (localFile == nsnull)
{
*aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
return NS_OK;
}
nsInstallFileOpItem* ifop = new nsInstallFileOpItem(this, NS_FOP_DIR_RENAME, localFile, aTarget, PR_FALSE, aReturn);
if (ifop == nsnull)
{
*aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
return NS_OK;
}
PRInt32 result = SanityCheck();
if (result != nsInstall::SUCCESS)
{
delete ifop;
*aReturn = SaveError( result );
return NS_OK;
}
if (*aReturn == nsInstall::SUCCESS)
{
*aReturn = ScheduleForInstall( ifop );
}
SaveError(*aReturn);
return NS_OK;
}
PRInt32
nsInstall::FileOpFileCopy(nsInstallFolder& aSrc, nsInstallFolder& aTarget, PRInt32* aReturn)
{
nsCOMPtr<nsIFile> localSrcFile = aSrc.GetFileSpec();
if (localSrcFile == nsnull)
{
*aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
return NS_OK;
}
nsCOMPtr<nsIFile>localTargetFile = aTarget.GetFileSpec();
if (localTargetFile == nsnull)
{
*aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
return NS_OK;
}
nsInstallFileOpItem* ifop = new nsInstallFileOpItem(this, NS_FOP_FILE_COPY, localSrcFile, localTargetFile, aReturn);
if (ifop == nsnull)
{
*aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
return NS_OK;
}
PRInt32 result = SanityCheck();
if (result != nsInstall::SUCCESS)
{
delete ifop;
*aReturn = SaveError( result );
return NS_OK;
}
if (*aReturn == nsInstall::SUCCESS)
{
*aReturn = ScheduleForInstall( ifop );
}
SaveError(*aReturn);
return NS_OK;
}
PRInt32
nsInstall::FileOpFileDelete(nsInstallFolder& aTarget, PRInt32 aFlags, PRInt32* aReturn)
{
nsCOMPtr<nsIFile> localFile = aTarget.GetFileSpec();
if (localFile == nsnull)
{
*aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
return NS_OK;
}
nsInstallFileOpItem* ifop = new nsInstallFileOpItem(this, NS_FOP_FILE_DELETE, localFile, aFlags, aReturn);
if (ifop == nsnull)
{
*aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
return NS_OK;
}
PRInt32 result = SanityCheck();
if (result != nsInstall::SUCCESS)
{
delete ifop;
*aReturn = SaveError( result );
return NS_OK;
}
if (*aReturn == nsInstall::SUCCESS)
{
*aReturn = ScheduleForInstall( ifop );
}
SaveError(*aReturn);
return NS_OK;
}
PRInt32
nsInstall::FileOpFileExecute(nsInstallFolder& aTarget, nsString& aParams, PRBool aBlocking, PRInt32* aReturn)
{
nsCOMPtr<nsIFile> localFile = aTarget.GetFileSpec();
if (localFile == nsnull)
{
*aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
return NS_OK;
}
nsInstallFileOpItem* ifop = new nsInstallFileOpItem(this, NS_FOP_FILE_EXECUTE, localFile, aParams, aBlocking, aReturn);
if (ifop == nsnull)
{
*aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
return NS_OK;
}
PRInt32 result = SanityCheck();
if (result != nsInstall::SUCCESS)
{
delete ifop;
*aReturn = SaveError( result );
return NS_OK;
}
if (*aReturn == nsInstall::SUCCESS)
{
*aReturn = ScheduleForInstall( ifop );
}
SaveError(*aReturn);
return NS_OK;
}
PRInt32
nsInstall::FileOpFileExists(nsInstallFolder& aTarget, PRBool* aReturn)
{
nsCOMPtr<nsIFile> localFile = aTarget.GetFileSpec();
localFile->Exists(aReturn);
return NS_OK;
}
PRInt32
nsInstall::FileOpFileGetNativeVersion(nsInstallFolder& aTarget, nsString* aReturn)
{
return NS_OK;
}
PRInt32
nsInstall::FileOpFileGetDiskSpaceAvailable(nsInstallFolder& aTarget, PRInt64* aReturn)
{
nsresult rv;
nsCOMPtr<nsIFile> file = aTarget.GetFileSpec();
nsCOMPtr<nsILocalFile> localFile = do_QueryInterface(file, &rv);
localFile->GetDiskSpaceAvailable(aReturn); //nsIFileXXX: need to figure out how to call GetDiskSpaceAvailable
return NS_OK;
}
//nsIFileXXX: need to get nsIFile equivalent to GetModDate
PRInt32
nsInstall::FileOpFileGetModDate(nsInstallFolder& aTarget, double* aReturn)
{
* aReturn = 0;
nsCOMPtr<nsIFile> localFile = aTarget.GetFileSpec();
if (localFile)
{
double newStamp;
PRInt64 lastModDate = LL_ZERO;
localFile->GetLastModificationDate(&lastModDate);
LL_L2D(newStamp, lastModDate);
*aReturn = newStamp;
}
return NS_OK;
}
PRInt32
nsInstall::FileOpFileGetSize(nsInstallFolder& aTarget, PRInt64* aReturn)
{
nsCOMPtr<nsIFile> localFile = aTarget.GetFileSpec();
localFile->GetFileSize(aReturn);
return NS_OK;
}
PRInt32
nsInstall::FileOpFileIsDirectory(nsInstallFolder& aTarget, PRBool* aReturn)
{
nsCOMPtr<nsIFile> localFile = aTarget.GetFileSpec();
localFile->IsDirectory(aReturn);
return NS_OK;
}
PRInt32
nsInstall::FileOpFileIsFile(nsInstallFolder& aTarget, PRBool* aReturn)
{
nsCOMPtr<nsIFile> localFile = aTarget.GetFileSpec();
localFile->IsFile(aReturn);
return NS_OK;
}
//nsIFileXXX: need to get the ModDateChanged equivalent for nsIFile
PRInt32
nsInstall::FileOpFileModDateChanged(nsInstallFolder& aTarget, double aOldStamp, PRBool* aReturn)
{
*aReturn = PR_TRUE;
nsCOMPtr<nsIFile> localFile = aTarget.GetFileSpec();
if (localFile)
{
double newStamp;
PRInt64 lastModDate = LL_ZERO;
localFile->GetLastModificationDate(&lastModDate);
LL_L2D(newStamp, lastModDate);
*aReturn = !(newStamp == aOldStamp);
}
return NS_OK;
}
PRInt32
nsInstall::FileOpFileMove(nsInstallFolder& aSrc, nsInstallFolder& aTarget, PRInt32* aReturn)
{
nsCOMPtr<nsIFile> localSrcFile = aSrc.GetFileSpec();
if (localSrcFile == nsnull)
{
*aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
return NS_OK;
}
nsCOMPtr<nsIFile> localTargetFile = aTarget.GetFileSpec();
if (localTargetFile == nsnull)
{
*aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
return NS_OK;
}
nsInstallFileOpItem* ifop = new nsInstallFileOpItem(this, NS_FOP_FILE_MOVE, localSrcFile, localTargetFile, aReturn);
if (ifop == nsnull)
{
*aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
return NS_OK;
}
PRInt32 result = SanityCheck();
if (result != nsInstall::SUCCESS)
{
delete ifop;
*aReturn = SaveError( result );
return NS_OK;
}
if (*aReturn == nsInstall::SUCCESS)
{
*aReturn = ScheduleForInstall( ifop );
}
SaveError(*aReturn);
return NS_OK;
}
PRInt32
nsInstall::FileOpFileRename(nsInstallFolder& aSrc, nsString& aTarget, PRInt32* aReturn)
{
nsCOMPtr<nsIFile> localFile = aSrc.GetFileSpec();
if (localFile == nsnull)
{
*aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
return NS_OK;
}
nsInstallFileOpItem* ifop = new nsInstallFileOpItem(this, NS_FOP_FILE_RENAME, localFile, aTarget, PR_FALSE, aReturn);
if (ifop == nsnull)
{
*aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
return NS_OK;
}
PRInt32 result = SanityCheck();
if (result != nsInstall::SUCCESS)
{
delete ifop;
*aReturn = SaveError( result );
return NS_OK;
}
if (*aReturn == nsInstall::SUCCESS)
{
*aReturn = ScheduleForInstall( ifop );
}
SaveError(*aReturn);
return NS_OK;
}
#ifdef _WINDOWS
#include <winbase.h>
#endif
PRInt32
nsInstall::FileOpFileWindowsGetShortName(nsInstallFolder& aTarget, nsString& aShortPathName)
{
#ifdef _WINDOWS
PRInt32 err;
PRBool flagExists;
nsString tmpNsString;
nsXPIDLCString nativeTargetPath;
char nativeShortPathName[MAX_PATH];
nsCOMPtr<nsIFile> localTarget(aTarget.GetFileSpec());
if(localTarget == nsnull)
return NS_OK;
localTarget->Exists(&flagExists);
if(flagExists)
{
memset(nativeShortPathName, 0, MAX_PATH);
localTarget->GetPath(getter_Copies(nativeTargetPath));
err = GetShortPathName(nativeTargetPath, nativeShortPathName, MAX_PATH);
if((err > 0) && (*nativeShortPathName == '\0'))
{
// NativeShortPathName buffer not big enough.
// Reallocate and try again.
// err will have the required size.
char *nativeShortPathNameTmp = new char[err + 1];
if(nativeShortPathNameTmp == nsnull)
return NS_OK;
err = GetShortPathName(nativeTargetPath, nativeShortPathNameTmp, err + 1);
// Is it safe to assume that the second time around the buffer is big enough
// and not to worry about it unless it's a different problem?
// if err is 0, it's not a buffer size problem. It's something else unexpected.
if(err != 0)
aShortPathName.AssignWithConversion(nativeShortPathNameTmp);
if(nativeShortPathNameTmp)
delete [] nativeShortPathNameTmp;
}
else if(err != 0)
// if err is 0, it's not a buffer size problem. It's something else unexpected.
aShortPathName.AssignWithConversion(nativeShortPathName);
}
#endif
return NS_OK;
}
PRInt32
nsInstall::FileOpFileWindowsShortcut(nsIFile* aTarget, nsIFile* aShortcutPath, nsString& aDescription, nsIFile* aWorkingPath, nsString& aParams, nsIFile* aIcon, PRInt32 aIconId, PRInt32* aReturn)
{
nsInstallFileOpItem* ifop = new nsInstallFileOpItem(this, NS_FOP_WIN_SHORTCUT, aTarget, aShortcutPath, aDescription, aWorkingPath, aParams, aIcon, aIconId, aReturn);
if (ifop == nsnull)
{
*aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
return NS_OK;
}
PRInt32 result = SanityCheck();
if (result != nsInstall::SUCCESS)
{
delete ifop;
*aReturn = SaveError( result );
return NS_OK;
}
if (*aReturn == nsInstall::SUCCESS)
{
*aReturn = ScheduleForInstall( ifop );
}
SaveError(*aReturn);
return NS_OK;
}
PRInt32
nsInstall::FileOpFileMacAlias(nsIFile *aSourceFile, nsIFile *aAliasFile, PRInt32* aReturn)
{
*aReturn = nsInstall::SUCCESS;
#ifdef XP_MAC
nsInstallFileOpItem* ifop = new nsInstallFileOpItem(this, NS_FOP_MAC_ALIAS, aSourceFile, aAliasFile, aReturn);
if (!ifop)
{
*aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
return NS_OK;
}
PRInt32 result = SanityCheck();
if (result != nsInstall::SUCCESS)
{
*aReturn = SaveError( result );
return NS_OK;
}
if (ifop == nsnull)
{
*aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
return NS_OK;
}
if (*aReturn == nsInstall::SUCCESS)
{
*aReturn = ScheduleForInstall( ifop );
}
SaveError(*aReturn);
#endif
return NS_OK;
}
PRInt32
nsInstall::FileOpFileUnixLink(nsInstallFolder& aTarget, PRInt32 aFlags, PRInt32* aReturn)
{
return NS_OK;
}
PRInt32
nsInstall::FileOpWinRegisterServer(nsInstallFolder& aTarget, PRInt32* aReturn)
{
nsCOMPtr<nsIFile> localFile = aTarget.GetFileSpec();
if (localFile == nsnull)
{
*aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
return NS_OK;
}
nsInstallFileOpItem* ifop = new nsInstallFileOpItem(this, NS_FOP_WIN_REGISTER_SERVER, localFile, aReturn);
if (ifop == nsnull)
{
*aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
return NS_OK;
}
PRInt32 result = SanityCheck();
if (result != nsInstall::SUCCESS)
{
delete ifop;
*aReturn = SaveError( result );
return NS_OK;
}
if (*aReturn == nsInstall::SUCCESS)
{
*aReturn = ScheduleForInstall( ifop );
}
SaveError(*aReturn);
return NS_OK;
}
void
nsInstall::LogComment(nsString& aComment)
{
if(mListener)
mListener->LogComment(aComment.GetUnicode());
}
/////////////////////////////////////////////////////////////////////////
// Private Methods
/////////////////////////////////////////////////////////////////////////
/**
* ScheduleForInstall
* call this to put an InstallObject on the install queue
* Do not call installedFiles.addElement directly, because this routine also
* handles progress messages
*/
PRInt32
nsInstall::ScheduleForInstall(nsInstallObject* ob)
{
PRInt32 error = nsInstall::SUCCESS;
char *objString = ob->toString();
// flash current item
if (mListener)
mListener->ItemScheduled(NS_ConvertASCIItoUCS2(objString).GetUnicode());
// do any unpacking or other set-up
error = ob->Prepare();
if (error == nsInstall::SUCCESS)
{
// Add to installation list
mInstalledFiles->AppendElement( ob );
// turn on flags for creating the uninstall node and
// the package node for each InstallObject
if (ob->CanUninstall())
mUninstallPackage = PR_TRUE;
if (ob->RegisterPackageNode())
mRegisterPackage = PR_TRUE;
}
else if ( mListener )
{
// error in preparation step -- log it
char* errRsrc = GetResourcedString(NS_ConvertASCIItoUCS2("ERROR"));
if (errRsrc)
{
char* errprefix = PR_smprintf("%s (%d): ", errRsrc, error);
nsString errstr; errstr.AssignWithConversion(errprefix);
errstr.AppendWithConversion(objString);
mListener->LogComment( errstr.GetUnicode() );
PR_smprintf_free(errprefix);
nsCRT::free(errRsrc);
}
}
if (objString)
delete [] objString;
return error;
}
/**
* SanityCheck
*
* This routine checks if the packageName is null. It also checks the flag if the user cancels
* the install progress dialog is set and acccordingly aborts the install.
*/
PRInt32
nsInstall::SanityCheck(void)
{
if ( mInstalledFiles == nsnull || mStartInstallCompleted == PR_FALSE )
{
return INSTALL_NOT_STARTED;
}
if (mUserCancelled)
{
InternalAbort(USER_CANCELLED);
return USER_CANCELLED;
}
return 0;
}
/**
* GetQualifiedPackageName
*
* This routine converts a package-relative component registry name
* into a full name that can be used in calls to the version registry.
*/
PRInt32
nsInstall::GetQualifiedPackageName( const nsString& name, nsString& qualifiedName )
{
nsString startOfName;
name.Left(startOfName, 7);
if ( startOfName.EqualsWithConversion( "=USER=/") )
{
CurrentUserNode(qualifiedName);
qualifiedName += name;
}
else
{
qualifiedName = name;
}
if (BadRegName(qualifiedName))
{
return BAD_PACKAGE_NAME;
}
/* Check to see if the PackageName ends in a '/'. If it does nuke it. */
if (qualifiedName.Last() == '/')
{
PRInt32 index = qualifiedName.Length();
qualifiedName.Truncate(--index);
}
return SUCCESS;
}
/**
* GetQualifiedRegName
*
* This routine converts a package-relative component registry name
* into a full name that can be used in calls to the version registry.
*/
PRInt32
nsInstall::GetQualifiedRegName(const nsString& name, nsString& qualifiedRegName )
{
nsString startOfName;
name.Left(startOfName, 7);
nsString usr ();
if ( startOfName.EqualsWithConversion("=COMM=/") || startOfName.EqualsWithConversion("=USER=/"))
{
qualifiedRegName = name;
qualifiedRegName.Cut( 0, 7 );
}
else if ( name.CharAt(0) != '/' )
{
if (!mRegistryPackageName.IsEmpty())
{
qualifiedRegName = mRegistryPackageName;
qualifiedRegName.AppendWithConversion("/");
qualifiedRegName += name;
}
else
{
qualifiedRegName = name;
}
}
else
{
qualifiedRegName = name;
}
if (BadRegName(qualifiedRegName))
{
return BAD_PACKAGE_NAME;
}
return SUCCESS;
}
static NS_DEFINE_IID(kPrefsIID, NS_IPREF_IID);
static NS_DEFINE_IID(kPrefsCID, NS_PREF_CID);
void
nsInstall::CurrentUserNode(nsString& userRegNode)
{
char *profname;
nsIPref * prefs;
nsresult rv = nsServiceManager::GetService(kPrefsCID,
kPrefsIID,
(nsISupports**) &prefs);
if ( NS_SUCCEEDED(rv) )
{
rv = prefs->CopyCharPref("profile.name", &profname);
if ( NS_FAILED(rv) )
{
PR_FREEIF(profname); // Allocated by PREF_CopyCharPref
profname = NULL;
}
NS_RELEASE(prefs);
}
else
{
profname = NULL;
}
userRegNode.AssignWithConversion("/Netscape/Users/");
if (profname != nsnull)
{
userRegNode.AppendWithConversion(profname);
userRegNode.AppendWithConversion("/");
PR_FREEIF(profname);
}
}
// catch obvious registry name errors proactively
// rather than returning some cryptic libreg error
PRBool
nsInstall::BadRegName(const nsString& regName)
{
if ( regName.Length() == 0 )
return PR_TRUE;
if ((regName.First() == ' ' ) || (regName.Last() == ' ' ))
return PR_TRUE;
if ( regName.Find("//") != -1 )
return PR_TRUE;
if ( regName.Find(" /") != -1 )
return PR_TRUE;
if ( regName.Find("/ ") != -1 )
return PR_TRUE;
if ( regName.Find("=") != -1 )
return PR_TRUE;
return PR_FALSE;
}
PRInt32
nsInstall::SaveError(PRInt32 errcode)
{
if ( errcode != nsInstall::SUCCESS )
mLastError = errcode;
return errcode;
}
/*
* CleanUp
* call it when done with the install
*
*/
void
nsInstall::CleanUp(void)
{
nsInstallObject* ie;
if ( mInstalledFiles != nsnull )
{
for (PRInt32 i=0; i < mInstalledFiles->Count(); i++)
{
ie = (nsInstallObject*)mInstalledFiles->ElementAt(i);
if (ie)
delete ie;
}
mInstalledFiles->Clear();
delete (mInstalledFiles);
mInstalledFiles = nsnull;
}
if (mPatchList != nsnull)
{
mPatchList->Reset();
delete mPatchList;
mPatchList = nsnull;
}
if (mPackageFolder != nsnull)
{
delete (mPackageFolder);
mPackageFolder = nsnull;
}
mRegistryPackageName.SetLength(0); // used to see if StartInstall() has been called
mStartInstallCompleted = PR_FALSE;
}
void
nsInstall::SetJarFileLocation(nsIFile* aFile)
{
mJarFileLocation = aFile;
}
void
nsInstall::GetInstallArguments(nsString& args)
{
args = mInstallArguments;
}
void
nsInstall::SetInstallArguments(const nsString& args)
{
mInstallArguments = args;
}
void nsInstall::GetInstallURL(nsString& url) { url = mInstallURL; }
void nsInstall::SetInstallURL(const nsString& url) { mInstallURL = url; }
//-----------------------------------------------------------------------------
// GetTranslatedString :
// This is a utility function that translates "Alert" or
// "Confirm" to pass as the title to the CommonDialogs Alert and Confirm
// functions as the title. If you pass nsnull as the title, you get garbage
// instead of a blank title.
//-----------------------------------------------------------------------------
PRUnichar *GetTranslatedString(const PRUnichar* aString)
{
nsCOMPtr<nsIStringBundleService> stringService = do_GetService(kStringBundleServiceCID);
nsCOMPtr<nsIStringBundle> stringBundle;
nsILocale* locale = nsnull;
PRUnichar* translatedString;
nsresult rv = stringService->CreateBundle(kInstallLocaleProperties, locale, getter_AddRefs(stringBundle));
if (NS_FAILED(rv)) return nsnull;
rv = stringBundle->GetStringFromName(aString, &translatedString);
if (NS_FAILED(rv)) return nsnull;
return translatedString;
}
PRInt32
nsInstall::Alert(nsString& string)
{
nsresult res;
NS_WITH_PROXIED_SERVICE(nsICommonDialogs, dialog, kCommonDialogsCID, NS_UI_THREAD_EVENTQ, &res);
if (NS_FAILED(res))
return res;
PRUnichar *title = GetTranslatedString(NS_ConvertASCIItoUCS2("Alert").get());
return dialog->Alert(mParent, title, string.GetUnicode());
}
PRInt32
nsInstall::Confirm(nsString& string, PRBool* aReturn)
{
*aReturn = PR_FALSE; /* default value */
nsresult res;
NS_WITH_PROXIED_SERVICE(nsICommonDialogs, dialog, kCommonDialogsCID, NS_UI_THREAD_EVENTQ, &res);
if (NS_FAILED(res))
return res;
PRUnichar *title = GetTranslatedString(NS_ConvertASCIItoUCS2("Confirm").get());
return dialog->Confirm(mParent, title, string.GetUnicode(), aReturn);
}
// aJarFile - This is the filepath within the jar file.
// aSuggestedName - This is the name that we should try to extract to. If we can, we will create a new temporary file.
// aRealName - This is the name that we did extract to. This will be allocated by use and should be disposed by the caller.
PRInt32
nsInstall::ExtractFileFromJar(const nsString& aJarfile, nsIFile* aSuggestedName, nsIFile** aRealName)
{
PRInt32 extpos = 0;
nsCOMPtr<nsIFile> extractHereSpec;
nsCOMPtr<nsILocalFile> tempFile;
nsresult rv;
if (aSuggestedName == nsnull)
{
NS_WITH_SERVICE(nsIProperties, directoryService, NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
directoryService->Get(NS_OS_TEMP_DIR, NS_GET_IID(nsIFile), getter_AddRefs(tempFile));
nsString tempFileName; tempFileName.AssignWithConversion("xpinstall");
// Get the extension of the file in the JAR
extpos = aJarfile.RFindChar('.');
if (extpos != -1)
{
// We found the extension; add it to the tempFileName string
nsString extension;
aJarfile.Right(extension, (aJarfile.Length() - extpos) );
tempFileName += extension;
}
nsAutoCString temp(tempFileName);
tempFile->Append(temp);
// Create a temporary file to extract to
MakeUnique(tempFile);
tempFile->Clone(getter_AddRefs(extractHereSpec));
if (extractHereSpec == nsnull)
return nsInstall::OUT_OF_MEMORY;
}
else
{
nsCOMPtr<nsIFile> temp;
aSuggestedName->Clone(getter_AddRefs(temp));
PRBool exists;
temp->Exists(&exists);
if (exists)
{
tempFile = do_QueryInterface(temp, &rv); //convert to an nsILocalFile
if (tempFile == nsnull)
return nsInstall::OUT_OF_MEMORY;
//get the leafname so we can convert its extension to .new
nsXPIDLCString leafName;
tempFile->GetLeafName(getter_Copies(leafName));
nsCString newLeafName (leafName);
PRInt32 extpos = newLeafName.RFindChar('.');
if (extpos != -1)
{
// We found the extension;
newLeafName.Truncate(extpos + 1); //strip off the old extension
}
newLeafName.Append("new");
//Now reset the leafname
tempFile->SetLeafName(newLeafName.get());
MakeUnique(tempFile);
extractHereSpec = tempFile;
}
extractHereSpec = temp;
}
rv = mJarFileData->Extract(nsAutoCString(aJarfile), extractHereSpec);
if (NS_FAILED(rv))
{
switch (rv) {
case NS_ERROR_FILE_ACCESS_DENIED: return ACCESS_DENIED;
case NS_ERROR_FILE_DISK_FULL: return INSUFFICIENT_DISK_SPACE;
case NS_ERROR_FILE_TARGET_DOES_NOT_EXIST: return DOES_NOT_EXIST;
default: return EXTRACTION_FAILED;
}
}
#ifdef XP_MAC
FSSpec finalSpec, extractedSpec;
nsCOMPtr<nsILocalFileMac> tempExtractHereSpec;
tempExtractHereSpec = do_QueryInterface(extractHereSpec, &rv);
tempExtractHereSpec->GetResolvedFSSpec(&extractedSpec);
if ( nsAppleSingleDecoder::IsAppleSingleFile(&extractedSpec) )
{
nsAppleSingleDecoder *asd = new nsAppleSingleDecoder(&extractedSpec, &finalSpec);
OSErr decodeErr = fnfErr;
if (asd)
decodeErr = asd->Decode();
if (decodeErr != noErr)
{
if (asd)
delete asd;
return EXTRACTION_FAILED;
}
if ( !(extractedSpec.vRefNum == finalSpec.vRefNum) ||
!(extractedSpec.parID == finalSpec.parID) ||
!(nsAppleSingleDecoder::PLstrcmp(extractedSpec.name, finalSpec.name)) )
{
// delete the unique extracted file that got renamed in AS decoding
FSpDelete(&extractedSpec);
// "real name" in AppleSingle entry may cause file rename
tempExtractHereSpec->InitWithFSSpec(&finalSpec);
extractHereSpec = do_QueryInterface(tempExtractHereSpec, &rv);
}
}
#endif
extractHereSpec->Clone(getter_AddRefs(aRealName));
return nsInstall::SUCCESS;
}
/**
* GetResourcedString
*
* Obtains the string resource for actions and messages that are displayed
* in user interface confirmation and progress dialogs.
*
* @param aResName - property name/identifier of string resource
* @return rscdStr - corresponding resourced value in the string bundle
*/
char*
nsInstall::GetResourcedString(const nsString& aResName)
{
nsString rscdStr;
PRBool bStrBdlSuccess = PR_FALSE;
if (mStringBundle)
{
const PRUnichar *ucResName = aResName.GetUnicode();
PRUnichar *ucRscdStr = nsnull;
nsresult rv = mStringBundle->GetStringFromName(ucResName, &ucRscdStr);
if (NS_SUCCEEDED(rv))
{
bStrBdlSuccess = PR_TRUE;
rscdStr = ucRscdStr;
}
}
/*
** We don't have a string bundle, the necessary libs, or something went wrong
** so we failover to hardcoded english strings so we log something rather
** than nothing due to failure above: always the case for the Install Wizards.
*/
if (!bStrBdlSuccess)
{
nsAutoCString temp(aResName);
rscdStr.AssignWithConversion(nsInstallResources::GetDefaultVal(temp));
}
return rscdStr.ToNewCString();
}
PRInt32
nsInstall::ExtractDirEntries(const nsString& directory, nsVoidArray *paths)
{
char *buf;
nsISimpleEnumerator *jarEnum = nsnull;
nsIZipEntry *currZipEntry = nsnull;
if ( paths )
{
nsString pattern(directory);
pattern.AppendWithConversion("/*");
PRInt32 prefix_length = directory.Length()+1; // account for slash
nsresult rv = mJarFileData->FindEntries( nsAutoCString(pattern), &jarEnum );
if (NS_FAILED(rv) || !jarEnum)
goto handle_err;
PRBool bMore;
rv = jarEnum->HasMoreElements(&bMore);
while (bMore && NS_SUCCEEDED(rv))
{
rv = jarEnum->GetNext( (nsISupports**) &currZipEntry );
if (currZipEntry)
{
// expensive 'buf' callee malloc per iteration!
rv = currZipEntry->GetName(&buf);
if (NS_FAILED(rv))
goto handle_err;
if (buf)
{
PRInt32 namelen = PL_strlen(buf);
NS_ASSERTION( prefix_length <= namelen, "Match must be longer than pattern!" );
if ( buf[namelen-1] != '/' )
{
// XXX manipulation should be in caller
nsString* tempString = new nsString; tempString->AssignWithConversion(buf+prefix_length);
paths->AppendElement(tempString);
}
PR_FREEIF( buf );
}
NS_IF_RELEASE(currZipEntry);
}
rv = jarEnum->HasMoreElements(&bMore);
}
}
NS_IF_RELEASE(jarEnum);
return SUCCESS;
handle_err:
NS_IF_RELEASE(jarEnum);
NS_IF_RELEASE(currZipEntry);
return EXTRACTION_FAILED;
}
void
nsInstall::DeleteVector(nsVoidArray* vector)
{
if (vector != nsnull)
{
for (PRInt32 i=0; i < vector->Count(); i++)
{
nsString* element = (nsString*)vector->ElementAt(i);
if (element != nsnull)
delete element;
}
vector->Clear();
delete (vector);
vector = nsnull;
}
}
nsresult MakeUnique(nsILocalFile* file)
{
PRBool flagExists;
nsresult rv = file->Exists(&flagExists);
if (NS_FAILED(rv)) return rv;
if (!flagExists) return NS_ERROR_FAILURE;
char* leafName;
rv = file->GetLeafName(&leafName);
if (NS_FAILED(rv)) return rv;
char* lastDot = strrchr(leafName, '.');
char* suffix = "";
if (lastDot)
{
suffix = nsCRT::strdup(lastDot); // include '.'
*lastDot = '\0'; // strip suffix and dot.
}
// 27 should work on Macintosh, Unix, and Win32.
const int maxRootLength = 27 - nsCRT::strlen(suffix) - 1;
if ((int)nsCRT::strlen(leafName) > (int)maxRootLength)
leafName[maxRootLength] = '\0';
for (short indx = 1; indx < 1000 && flagExists; indx++)
{
// start with "Picture-1.jpg" after "Picture.jpg" exists
char newName[32];
sprintf(newName, "%s-%d%s", leafName, indx, suffix);
file->SetLeafName(newName);
rv = file->Exists(&flagExists);
if (NS_FAILED(rv)) return rv;
}
return NS_OK;
}