Files
Mozilla/mozilla/xpinstall/src/nsInstall.cpp
dougt%netscape.com e209534fbb change return type to void to avoid warnings.
git-svn-id: svn://10.0.0.236/trunk@24925 18797224-902f-48f8-a5cc-f745e15eee43
1999-03-24 00:10:37 +00:00

1378 lines
32 KiB
C++

/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (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.
*
* Contributors:
* Daniel Veditz <dveditz@netscape.com>
* Douglas Turner <dougt@netscape.com>
*/
#include "nscore.h"
#include "nsIFactory.h"
#include "nsISupports.h"
#include "nsVector.h"
#include "nsHashtable.h"
#include "nsFileSpec.h"
#include "nsSpecialSystemDirectory.h"
#include "prmem.h"
#include "pratom.h"
#include "prefapi.h"
#include "VerReg.h"
#include "zipfile.h"
#include "nsInstall.h"
#include "nsInstallFolder.h"
#include "nsIDOMInstallVersion.h"
#include "nsInstallFile.h"
#include "nsInstallDelete.h"
#include "nsInstallExecute.h"
#include "nsInstallPatch.h"
#ifdef XP_PC
#define FILESEP "\\"
#elif defined(XP_MAC)
#define FILESEP ":"
#else
#define FILESEP "/"
#endif
nsInstallInfo::nsInstallInfo(const nsString& fromURL)
{
nsInstallInfo(fromURL, "", "");
}
nsInstallInfo::nsInstallInfo(const nsString& fromURL, const nsString& arguments)
{
nsInstallInfo(fromURL, arguments, "");
}
nsInstallInfo::nsInstallInfo(const nsString& fromURL, const nsString& arguments, const nsString& flags)
{
mFromURL = new nsString(fromURL);
mArguments = new nsString(arguments);
mFlags = new nsString(flags);
mLocalFile = new nsString();
mInstalled = PR_FALSE;
mMultipleTrigger = PR_FALSE;
mFromURLs = nsnull;
mLocalFiles = nsnull;
MakeTempFile(fromURL, *mLocalFile);
}
nsInstallInfo::nsInstallInfo(nsVector* fromURL, const nsString& arguments, const nsString& flags)
{
mMultipleTrigger = PR_TRUE;
mFromURLs = fromURL;
mLocalFiles = new nsVector();
mArguments = new nsString(arguments);
mFlags = new nsString(flags);
mInstalled = PR_FALSE;
mMultipleTrigger = PR_FALSE;
// The following are not to be used with the Multiple Trigger
mLocalFile = nsnull;
mFromURL = nsnull;
}
void
nsInstallInfo::DeleteVector(nsVector* vector)
{
if (vector != nsnull)
{
PRUint32 i=0;
for (; i < vector->GetSize(); i++)
{
nsString* element = (nsString*)vector->Get(i);
if (element != nsnull)
delete element;
}
vector->RemoveAll();
delete (vector);
vector = nsnull;
}
}
nsInstallInfo::~nsInstallInfo()
{
if (mMultipleTrigger)
{
DeleteVector(mFromURLs);
DeleteVector(mLocalFiles);
}
else
{
if (mLocalFile)
delete mLocalFile;
delete mFromURL;
}
delete mArguments;
delete mFlags;
}
void
nsInstallInfo::MakeTempFile(nsString aURL, nsString& tempFileString)
{
// Checking to see if the url is local is a hack. I should see if
// netlib could do this for me: given a url, give me path on the users
// if it is local otherwise return null to indicate that I need to
// create a tempfile.
if (aURL.Compare(nsString("file://"), false, 7) == 0)
{
tempFileString = nsFileSpec(nsFileURL(aURL)).GetCString();
}
else
{
nsSpecialSystemDirectory tempFile(nsSpecialSystemDirectory::OS_TemporaryDirectory);
PRInt32 result = aURL.RFind('/');
if (result != -1)
{
nsString jarName;
aURL.Right(jarName, (aURL.Length() - result) );
tempFile += jarName;
}
else
{
tempFile += "xpinstall.jar";
}
tempFile.MakeUnique();
tempFileString = nsString(tempFile.GetCString());
}
}
nsString&
nsInstallInfo::GetFromURL(PRUint32 index)
{
if (mMultipleTrigger)
{
nsString* element = (nsString*)mFromURLs->Get(index);
return *element;
}
else
{
return *mFromURL;
}
}
nsString&
nsInstallInfo::GetLocalFile(PRUint32 index)
{
if (mMultipleTrigger)
{
nsString* element = (nsString*)mLocalFiles->Get(index);
return *element;
}
else
{
return *mLocalFile;
}
}
nsString&
nsInstallInfo::GetArguments()
{
return *mArguments;
}
nsString& nsInstallInfo::GetFlags()
{
return *mFlags;
}
PRBool
nsInstallInfo::IsMultipleTrigger()
{
return mMultipleTrigger;
}
nsInstall::nsInstall()
{
mScriptObject = nsnull; // this is the jsobject for our context
mVersionInfo = nsnull; // this is the version information passed to us in StartInstall()
mJarFileData = nsnull; // this is an opaque handle to the jarfile.
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.
mUninstallPackage = PR_FALSE;
mRegisterPackage = PR_FALSE;
mJarFileLocation = "";
mInstallArguments = "";
}
nsInstall::~nsInstall()
{
if (mVersionInfo != nsnull)
delete mVersionInfo;
}
nsInstall::SetScriptObject(void *aScriptObject)
{
mScriptObject = (JSObject*) aScriptObject;
return NS_OK;
}
PRInt32
nsInstall::GetUserPackageName(nsString& aUserPackageName)
{
aUserPackageName = mUIName;
return NS_OK;
}
PRInt32
nsInstall::GetRegPackageName(nsString& aRegPackageName)
{
aRegPackageName = mRegistryPackageName;
return NS_OK;
}
PRInt32
nsInstall::AbortInstall()
{
nsInstallObject* ie;
if (mInstalledFiles != nsnull)
{
PRUint32 i=0;
for (i=0; i < mInstalledFiles->GetSize(); i++)
{
ie = (nsInstallObject *)mInstalledFiles->Get(i);
if (ie == nsnull)
continue;
ie->Abort();
}
}
CleanUp();
return NS_OK;
}
PRInt32
nsInstall::AddDirectory(const nsString& aRegName,
const nsString& aVersion,
const nsString& aJarSource,
const nsString& aFolder,
const nsString& aSubdir,
PRBool aForceMode,
PRInt32* aReturn)
{
nsInstallFile* ie = nsnull;
PRInt32 result;
if ( aJarSource == "null" || aFolder == "null")
{
*aReturn = SaveError(nsInstall::INVALID_ARGUMENTS);
return NS_OK;
}
result = SanityCheck();
if (result != nsInstall::SUCCESS)
{
*aReturn = SaveError( result );
return NS_OK;
}
nsString* qualifiedRegName = nsnull;
if ( aRegName == "" )
{
// Default subName = location in jar file
qualifiedRegName = GetQualifiedRegName( aJarSource );
}
else
{
qualifiedRegName = GetQualifiedRegName( aRegName );
}
if (qualifiedRegName == nsnull)
{
*aReturn = SaveError( BAD_PACKAGE_NAME );
return NS_OK;
}
nsString subdirectory(aSubdir);
if (subdirectory != "")
{
subdirectory.Append("/");
}
PRBool bInstall;
nsVector paths;
result = ExtractDirEntries(aJarSource, &paths);
PRInt32 pathsUpperBound = paths.GetUpperBound();
if (result != nsInstall::SUCCESS)
{
*aReturn = SaveError( result );
return NS_OK;
}
for (int i=0; i< pathsUpperBound; i++)
{
nsInstallVersion* newVersion = new nsInstallVersion();
nsString *fullRegName = new nsString(*qualifiedRegName);
fullRegName->Append("/");
fullRegName->Append(*(nsString *)paths[i]);
char* fullRegNameCString = fullRegName->ToNewCString();
if ( (aForceMode == PR_FALSE) && (aVersion == "null") &&
(VR_ValidateComponent(fullRegNameCString) == 0))
{
VERSION versionStruct;
VR_GetVersion( fullRegNameCString, &versionStruct);
//fix: when we have overloading!
nsInstallVersion* oldVer = new nsInstallVersion();
oldVer->Init(versionStruct.major,
versionStruct.minor,
versionStruct.release,
versionStruct.build);
newVersion->Init(aVersion);
PRInt32 areTheyEqual;
newVersion->CompareTo(oldVer, &areTheyEqual);
delete newVersion;
bInstall = ( areTheyEqual > 0 );
if (oldVer)
delete oldVer;
}
else
{
// file doesn't exist or "forced" install
bInstall = PR_TRUE;
}
delete fullRegNameCString;
if (bInstall)
{
nsString *newJarSource = new nsString(aJarSource);
newJarSource->Append("/");
newJarSource->Append(*(nsString *)paths[i]);
nsString* newSubDir;
if (subdirectory != "")
{
newSubDir = new nsString(subdirectory);
newSubDir->Append(*(nsString*)paths[i]);
}
else
{
newSubDir = new nsString(*(nsString*)paths[i]);
}
ie = new nsInstallFile( this,
*fullRegName,
newVersion,
*newJarSource,
aFolder,
*newSubDir,
aForceMode,
&result);
delete fullRegName;
delete newJarSource;
delete newSubDir;
delete newVersion;
if (result == nsInstall::SUCCESS)
{
result = ScheduleForInstall( ie );
}
else
{
delete ie;
}
}
}
if (qualifiedRegName != nsnull)
delete qualifiedRegName;
*aReturn = SaveError( result );
return NS_OK;
}
PRInt32
nsInstall::AddSubcomponent(const nsString& aRegName,
const nsString& aVersion,
const nsString& aJarSource,
const nsString& aFolder,
const nsString& aTargetName,
PRBool aForceMode,
PRInt32* aReturn)
{
nsInstallFile* ie;
nsString* qualifiedRegName = nsnull;
PRInt32 errcode = nsInstall::SUCCESS;
if ( aJarSource == "null" || aFolder == "null")
{
*aReturn = SaveError( nsInstall::INVALID_ARGUMENTS );
return NS_OK;
}
PRInt32 result = SanityCheck();
if (result != nsInstall::SUCCESS)
{
*aReturn = SaveError( result );
return NS_OK;
}
if ( aRegName == "" )
{
// Default subName = location in jar file
qualifiedRegName = GetQualifiedRegName( aJarSource );
}
else
{
qualifiedRegName = GetQualifiedRegName( aRegName );
}
if (qualifiedRegName == nsnull)
{
*aReturn = SaveError( BAD_PACKAGE_NAME );
return NS_OK;
}
/* Check for existence of the newer version */
nsInstallVersion *newVersion = new nsInstallVersion();
newVersion->Init(aVersion);
PRBool versionNewer = PR_FALSE;
char* qualifiedRegNameString = qualifiedRegName->ToNewCString();
if ( (aForceMode == PR_FALSE ) && (aVersion != "null") && ( VR_ValidateComponent( qualifiedRegNameString ) == 0 ) )
{
VERSION versionStruct;
VR_GetVersion( qualifiedRegNameString, &versionStruct );
nsInstallVersion* oldVersion = new nsInstallVersion();
// FIX. Once we move to XPConnect, we can have parameterized constructors.
oldVersion->Init(versionStruct.major,
versionStruct.minor,
versionStruct.release,
versionStruct.build);
PRInt32 areTheyEqual;
newVersion->CompareTo((nsInstallVersion*)oldVersion, &areTheyEqual);
if ( areTheyEqual != nsIDOMInstallVersion::EQUAL )
versionNewer = PR_TRUE;
if ( oldVersion )
delete oldVersion;
}
else
{
versionNewer = PR_TRUE;
}
if (qualifiedRegNameString != nsnull)
delete qualifiedRegNameString;
if (versionNewer)
{
ie = new nsInstallFile( this,
*qualifiedRegName,
newVersion,
aJarSource,
aFolder,
aTargetName,
aForceMode,
&errcode );
if (errcode == nsInstall::SUCCESS)
{
errcode = ScheduleForInstall( ie );
}
else
{
delete ie;
}
}
if (qualifiedRegName != nsnull)
delete qualifiedRegName;
if (newVersion != nsnull)
delete newVersion;
*aReturn = SaveError( errcode );
return NS_OK;
}
PRInt32
nsInstall::DeleteComponent(const nsString& aRegistryName, PRInt32* aReturn)
{
PRInt32 result = SanityCheck();
if (result != nsInstall::SUCCESS)
{
*aReturn = SaveError( result );
return NS_OK;
}
nsString* qualifiedRegName = GetQualifiedRegName( aRegistryName);
if (qualifiedRegName == nsnull)
{
*aReturn = SaveError( BAD_PACKAGE_NAME );
return NS_OK;
}
nsInstallDelete* id = new nsInstallDelete(this, "", *qualifiedRegName, &result);
if (result == nsInstall::SUCCESS)
{
result = ScheduleForInstall( id );
}
delete qualifiedRegName;
*aReturn = SaveError(result);
return NS_OK;
}
PRInt32
nsInstall::DeleteFile(const nsString& aFolder, const nsString& aRelativeFileName, PRInt32* aReturn)
{
PRInt32 result = SanityCheck();
if (result != nsInstall::SUCCESS)
{
*aReturn = SaveError( result );
return NS_OK;
}
nsInstallDelete* id = new nsInstallDelete(this, aFolder, aRelativeFileName, &result);
if (result == nsInstall::SUCCESS)
{
result = ScheduleForInstall( id );
}
if (result == nsInstall::FILE_DOES_NOT_EXIST)
{
result = nsInstall::SUCCESS;
}
*aReturn = SaveError(result);
return NS_OK;
}
PRInt32
nsInstall::DiskSpaceAvailable(const nsString& aFolder, PRInt32* aReturn)
{
return NS_OK;
}
PRInt32
nsInstall::Execute(const nsString& aJarSource, const nsString& aArgs, PRInt32* aReturn)
{
PRInt32 result = SanityCheck();
if (result != nsInstall::SUCCESS)
{
*aReturn = SaveError( result );
return NS_OK;
}
nsInstallExecute* ie = new nsInstallExecute(this, aJarSource, aArgs, &result);
if (result == nsInstall::SUCCESS)
{
result = ScheduleForInstall( ie );
}
*aReturn = SaveError(result);
return NS_OK;
}
PRInt32
nsInstall::FinalizeInstall(PRInt32* aReturn)
{
PRBool rebootNeeded = PR_FALSE;
PRInt32 result = SanityCheck();
if (result != nsInstall::SUCCESS)
{
*aReturn = SaveError( result );
return NS_OK;
}
if ( mInstalledFiles == NULL || mInstalledFiles->GetSize() == 0 )
{
// no actions queued: don't register the package version
// and no need for user confirmation
CleanUp();
return NS_OK;
}
nsInstallObject* ie = nsnull;
if ( mUninstallPackage )
{
// The Version Registry is not real. FIX!
//
//VR_UninstallCreateNode( nsAutoCString(mRegistryPackageName), nsAutoCString(mUIName));
}
PRUint32 i=0;
for (i=0; i < mInstalledFiles->GetSize(); i++)
{
ie = (nsInstallObject*)mInstalledFiles->Get(i);
if (ie == NULL)
continue;
ie->Complete();
if (result != nsInstall::SUCCESS)
{
ie->Abort();
*aReturn = SaveError( result );
return NS_OK;
}
//SetProgressDialogThermo(++count);
}
*aReturn = NS_OK;
return NS_OK;
}
PRInt32
nsInstall::Gestalt(const nsString& aSelector, PRInt32* aReturn)
{
*aReturn = nsnull;
return NS_OK;
}
PRInt32
nsInstall::GetComponentFolder(const nsString& aComponentName, const nsString& aSubdirectory, nsString** aFolder)
{
long err;
char* dir;
char* componentCString;
*aFolder = nsnull;
nsString *tempString = GetQualifiedPackageName( aComponentName );
if (tempString == nsnull)
return NS_OK;
componentCString = tempString->ToNewCString();
delete tempString;
dir = (char*)PR_Malloc(MAXREGPATHLEN);
err = VR_GetDefaultDirectory( componentCString, MAXREGPATHLEN, dir );
if (err != REGERR_OK)
{
PR_FREEIF(dir);
}
if ( dir == NULL )
{
dir = (char*)PR_Malloc(MAXREGPATHLEN);
err = VR_GetPath( componentCString, MAXREGPATHLEN, dir );
if (err != REGERR_OK)
{
PR_FREEIF(dir);
}
if ( dir != nsnull )
{
int i;
nsString dirStr(dir);
if ( (i = dirStr.RFind(FILESEP)) > 0 )
{
PR_FREEIF(dir);
dir = (char*)PR_Malloc(i);
dir = dirStr.ToCString(dir, i);
}
}
}
if ( dir != NULL )
{
*aFolder = new nsString(dir);
}
PR_FREEIF(dir);
delete [] componentCString;
return NS_OK;
}
PRInt32
nsInstall::GetFolder(const nsString& targetFolder, const nsString& aSubdirectory, nsString** aFolder)
{
nsInstallFolder* spec = nsnull;
*aFolder = nsnull;
spec = new nsInstallFolder(targetFolder, aSubdirectory);
nsString dirString;
spec->GetDirectoryPath(dirString);
*aFolder = new nsString(dirString);
return NS_OK;
}
PRInt32
nsInstall::GetLastError(PRInt32* aReturn)
{
*aReturn = mLastError;
return NS_OK;
}
PRInt32
nsInstall::GetWinProfile(const nsString& aFolder, const nsString& aFile, PRInt32* aReturn)
{
return NS_OK;
}
PRInt32
nsInstall::GetWinRegistry(PRInt32* aReturn)
{
return NS_OK;
}
PRInt32
nsInstall::Patch(const nsString& aRegName, const nsString& aVersion, const nsString& aJarSource, const nsString& aFolder, const nsString& aTargetName, PRInt32* aReturn)
{
PRInt32 result = SanityCheck();
if (result != nsInstall::SUCCESS)
{
*aReturn = SaveError( result );
return NS_OK;
}
nsString* qualifiedRegName = GetQualifiedRegName( aRegName );
if (qualifiedRegName == nsnull)
{
*aReturn = SaveError( nsInstall::BAD_PACKAGE_NAME );
return NS_OK;
}
nsInstallVersion *newVersion = new nsInstallVersion();
newVersion->Init(aVersion);
nsInstallPatch* ip = new nsInstallPatch( this,
*qualifiedRegName,
newVersion,
aJarSource,
&result);
delete newVersion;
if (result == nsInstall::SUCCESS)
{
result = ScheduleForInstall( ip );
}
*aReturn = SaveError(result);
return NS_OK;
}
PRInt32
nsInstall::ResetError()
{
mLastError = nsInstall::SUCCESS;
return NS_OK;
}
PRInt32
nsInstall::SetPackageFolder(const nsString& aFolder)
{
if (mPackageFolder != nsnull)
delete mPackageFolder;
mPackageFolder = new nsString(aFolder);
return NS_OK;
}
/**
* Call this to initialize the update
* Opens the jar file and gets the certificate of the installer
* Opens up the gui, and asks for proper security privileges
*
* @param aUserPackageName
*
* @param aPackageName Full qualified version registry name of the package
* (ex: "/Plugins/Adobe/Acrobat")
* NULL or empty package names are errors
*
* @param inVInfo version of the package installed.
* Can be NULL, in which case package is installed
* without a version. Having a NULL version, this
* package is automatically updated in the future
* (ie. no version check is performed).
*
* @param flags Once was securityLevel(LIMITED_INSTALL or FULL_INSTALL). Now
* can be either NO_STATUS_DLG or NO_FINALIZE_DLG
*/
PRInt32
nsInstall::StartInstall(const nsString& aUserPackageName, const nsString& aPackageName, const nsString& aVersion, PRInt32 aFlags, PRInt32* aReturn)
{
*aReturn = nsInstall::SUCCESS;
ResetError();
mUserCancelled = PR_FALSE;
mUIName = aUserPackageName;
if ( aPackageName.Equals("") )
{
*aReturn = nsInstall::INVALID_ARGUMENTS;
return NS_OK;
}
nsString *tempString = GetQualifiedPackageName( aPackageName );
mRegistryPackageName.SetLength(0);
mRegistryPackageName.Append( *tempString );
delete tempString;
/* Check to see if the PackageName ends in a '/'. If it does nuke it. */
if (mRegistryPackageName.Last() == '/')
{
PRInt32 index = mRegistryPackageName.Length();
mRegistryPackageName.Truncate(--index);
}
if (mVersionInfo != nsnull)
delete mVersionInfo;
mVersionInfo = new nsInstallVersion();
mVersionInfo->Init(aVersion);
mInstalledFiles = new nsVector();
mPatchList = new nsHashtable();
/* this function should also check security!!! */
*aReturn = OpenJARFile();
if (*aReturn != nsInstall::SUCCESS)
{
/* if we can not continue with the javascript return a JAR error*/
return -1; /* FIX: need real error code */
}
/* Show our window here */
SaveError(*aReturn);
if (*aReturn != nsInstall::SUCCESS)
{
mRegistryPackageName = ""; // Reset!
}
return NS_OK;
}
PRInt32
nsInstall::Uninstall(const nsString& aPackageName, PRInt32* aReturn)
{
PRInt32 result = SanityCheck();
if (result != nsInstall::SUCCESS)
{
*aReturn = SaveError( result );
return NS_OK;
}
nsString* qualifiedPackageName = GetQualifiedPackageName( aPackageName );
if (qualifiedPackageName == nsnull)
{
*aReturn = SaveError( BAD_PACKAGE_NAME );
return NS_OK;
}
// Create UNinstall object here FIX
delete qualifiedPackageName;
if (result == SUCCESS)
{
// result = ScheduleForInstall( ip );
}
*aReturn = SaveError(result);
return NS_OK;
}
////////////////////////////////////////
void
nsInstall::AddPatch(nsHashKey *aKey, nsFileSpec* fileName)
{
if (mPatchList != nsnull)
{
mPatchList->Put(aKey, fileName);
}
}
void
nsInstall::GetPatch(nsHashKey *aKey, nsFileSpec* fileName)
{
if (mPatchList != nsnull)
{
fileName = (nsFileSpec*) mPatchList->Get(aKey);
}
}
/////////////////////////////////////////////////////////////////////////
// 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
//SetProgressDialogItem( objString );
PR_FREEIF(objString);
// do any unpacking or other set-up
error = ob->Prepare();
if (error != nsInstall::SUCCESS)
return error;
// Add to installation list if we haven't thrown out
mInstalledFiles->Add( 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;
return nsInstall::SUCCESS;
}
/**
* 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 ( mRegistryPackageName == "" || mUIName == "")
{
return INSTALL_NOT_STARTED;
}
if (mUserCancelled)
{
AbortInstall();
SaveError(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.
*/
nsString *
nsInstall::GetQualifiedPackageName( const nsString& name )
{
nsString* qualifedName = nsnull;
/* this functions is really messed up. The original checkin is messed as well */
if ( name.Equals( "=USER=/") )
{
qualifedName = CurrentUserNode();
qualifedName->Insert( name, 7 );
}
else
{
qualifedName = new nsString(name);
}
if (BadRegName(qualifedName))
{
if (qualifedName != nsnull)
{
delete qualifedName;
qualifedName = nsnull;
}
}
return qualifedName;
}
/**
* GetQualifiedRegName
*
* Allocates a new string and returns it. Caller is supposed to free it
*
* This routine converts a package-relative component registry name
* into a full name that can be used in calls to the version registry.
*/
nsString *
nsInstall::GetQualifiedRegName(const nsString& name )
{
nsString *qualifiedRegName;
nsString comm("=COMM=/");
nsString usr ("=USER=/");
if ( name.Compare(comm, PR_TRUE, comm.Length()) == 0 )
{
qualifiedRegName = new nsString( name );
qualifiedRegName->Cut( 0, comm.Length() );
}
else if ( name.Compare(usr, PR_TRUE, usr.Length()) == 0 )
{
qualifiedRegName = new nsString( name );
qualifiedRegName->Cut( 0, usr.Length() );
}
else if ( name[0] != '/' )
{
if (mUIName != "")
{
qualifiedRegName = new nsString(mUIName);
qualifiedRegName->Append("/");
qualifiedRegName->Append(name);
}
else
{
qualifiedRegName = new nsString(name);
}
}
else
{
qualifiedRegName = new nsString(name);
}
if (BadRegName(qualifiedRegName))
{
delete qualifiedRegName;
qualifiedRegName = NULL;
}
return qualifiedRegName;
}
nsString*
nsInstall::CurrentUserNode()
{
nsString *qualifedName;
nsString *profileName;
char *profname;
int len = MAXREGNAMELEN;
int err;
profname = (char*) PR_Malloc(len);
err = PREF_GetCharPref( "profile.name", profname, &len );
if ( err != PREF_OK )
{
PR_FREEIF(profname);
profname = NULL;
}
profileName = new nsString(profname);
qualifedName = new nsString("/Netscape/Users/");
qualifedName->Append(*profileName);
qualifedName->Append("/");
if (profileName != nsnull)
delete profileName;
return qualifedName;
}
// catch obvious registry name errors proactively
// rather than returning some cryptic libreg error
PRBool
nsInstall::BadRegName(nsString* regName)
{
if (regName == nsnull)
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
*
* XXX: This is a synchronized method. FIX it.
*/
void
nsInstall::CleanUp(void)
{
nsInstallObject* ie;
CloseJARFile();
if ( mInstalledFiles != NULL )
{
PRUint32 i=0;
for (; i < mInstalledFiles->GetSize(); i++)
{
ie = (nsInstallObject*)mInstalledFiles->Get(i);
delete (ie);
}
mInstalledFiles->RemoveAll();
delete (mInstalledFiles);
mInstalledFiles = nsnull;
}
if (mPatchList)
{
// do I need to delete every entry?
delete mPatchList;
}
mRegistryPackageName = ""; // used to see if StartInstall() has been called
//CloseProgressDialog();
}
void
nsInstall::GetJarFileLocation(nsString& aFile)
{
aFile.SetString( mJarFileLocation );
}
void
nsInstall::SetJarFileLocation(const nsString& aFile)
{
mJarFileLocation.SetString(aFile);
}
void
nsInstall::GetInstallArguments(nsString& args)
{
args.SetString( mInstallArguments );
}
void
nsInstall::SetInstallArguments(const nsString& args)
{
mInstallArguments.SetString(args);
}
PRInt32
nsInstall::OpenJARFile(void)
{
PRInt32 result = ZIP_OpenArchive(nsAutoCString(mJarFileLocation), &mJarFileData);
return result;
}
void
nsInstall::CloseJARFile(void)
{
ZIP_CloseArchive(&mJarFileData);
mJarFileData = nsnull;
}
// 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, nsFileSpec* aSuggestedName, nsFileSpec** aRealName)
{
PRInt32 result;
nsFileSpec *extractHereSpec;
nsSpecialSystemDirectory tempFile(nsSpecialSystemDirectory::OS_TemporaryDirectory);
if (aSuggestedName == nsnull || aSuggestedName->Exists() )
{
nsString tempfileName = "xpinstall";
// Get the extention of the file in the jar.
PRInt32 result = aJarfile.RFind('.');
if (result != -1)
{
// We found an extention. Add it to the tempfileName string
nsString extention;
aJarfile.Right(extention, (aJarfile.Length() - result) );
tempfileName += extention;
}
tempFile += tempfileName;
// Create a temporary file to extract to.
tempFile.MakeUnique();
extractHereSpec = new nsFileSpec(tempFile);
}
else
{
// extract to the final destination.
extractHereSpec = new nsFileSpec(*aSuggestedName);
}
// FIX: We will overwrite what is in the way. is this something that we want to do?
extractHereSpec->Delete(PR_FALSE);
result = ZIP_ExtractFile( mJarFileData, nsAutoCString(aJarfile), extractHereSpec->GetCString() );
if (result == 0)
{
*aRealName = extractHereSpec;
}
else
{
if (extractHereSpec != nsnull)
delete extractHereSpec;
}
return result;
}
PRInt32
nsInstall::ExtractDirEntries(const nsString& directory, nsVector *paths)
{
return nsInstall::SUCCESS;
}