Back to index

lightning-sunbird  0.9+nobinonly
nsInstall.cpp
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is Mozilla Communicator client code, released
00015  * March 31, 1998.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *     Daniel Veditz <dveditz@netscape.com>
00024  *     Douglas Turner <dougt@netscape.com>
00025  *     Jens Bannmann <jens.b@web.de>
00026  *     Pierre Phaneuf <pp@ludusdesign.com>
00027  *     Sean Su <ssu@netscape.com>
00028  *     Samir Gehani <sgehani@netscape.com>
00029  *
00030  * Alternatively, the contents of this file may be used under the terms of
00031  * either of the GNU General Public License Version 2 or later (the "GPL"),
00032  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00033  * in which case the provisions of the GPL or the LGPL are applicable instead
00034  * of those above. If you wish to allow use of your version of this file only
00035  * under the terms of either the GPL or the LGPL, and not to allow others to
00036  * use your version of this file under the terms of the MPL, indicate your
00037  * decision by deleting the provisions above and replace them with the notice
00038  * and other provisions required by the GPL or the LGPL. If you do not delete
00039  * the provisions above, a recipient may use your version of this file under
00040  * the terms of any one of the MPL, the GPL or the LGPL.
00041  *
00042  * ***** END LICENSE BLOCK ***** */
00043 
00044 #include "nscore.h"
00045 #include "nsIFactory.h"
00046 #include "nsISupports.h"
00047 #include "nsNativeCharsetUtils.h"
00048 
00049 #include "nsIComponentManager.h"
00050 #include "nsIServiceManager.h"
00051 
00052 #include "nsHashtable.h"
00053 #include "nsIFileChannel.h"
00054 #include "nsDirectoryService.h"
00055 #include "nsDirectoryServiceDefs.h"
00056 #include "nsAppDirectoryServiceDefs.h"
00057 #include "nsDirectoryServiceUtils.h"
00058 
00059 #include "nsNetUtil.h"
00060 
00061 #include "nsIPrefBranch.h"
00062 #include "nsIPrefService.h"
00063 
00064 #include "prmem.h"
00065 #include "plstr.h"
00066 #include "prprf.h"
00067 #include "nsCRT.h"
00068 
00069 #include "VerReg.h"
00070 
00071 #include "nsInstall.h"
00072 #include "nsInstallFolder.h"
00073 #include "nsInstallVersion.h"
00074 #include "nsInstallFile.h"
00075 #include "nsInstallExecute.h"
00076 #include "nsInstallPatch.h"
00077 #include "nsInstallUninstall.h"
00078 #include "nsInstallResources.h"
00079 #include "nsXPIProxy.h"
00080 #include "nsRegisterItem.h"
00081 #include "nsNetUtil.h"
00082 #include "ScheduledTasks.h"
00083 #include "nsIPersistentProperties2.h"
00084 
00085 #include "nsIProxyObjectManager.h"
00086 #include "nsProxiedService.h"
00087 
00088 #ifdef _WINDOWS
00089 #include "nsWinReg.h"
00090 #include "nsWinProfile.h"
00091 #endif
00092 
00093 #include "nsInstallFileOpEnums.h"
00094 #include "nsInstallFileOpItem.h"
00095 
00096 #if defined(XP_MAC) || defined(XP_MACOSX)
00097 #include <Gestalt.h>
00098 #include "nsAppleSingleDecoder.h"
00099 #include "nsILocalFileMac.h"
00100 #endif
00101 
00102 #include "nsILocalFile.h"
00103 #include "nsIURL.h"
00104 
00105 #if defined(XP_UNIX) || defined(XP_BEOS)
00106 #include <sys/utsname.h>
00107 #endif /* XP_UNIX */
00108 
00109 #if defined(XP_WIN)
00110 #include <windows.h>
00111 #endif
00112 
00113 static NS_DEFINE_IID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
00114 static NS_DEFINE_IID(kProxyObjectManagerCID, NS_PROXYEVENT_MANAGER_CID);
00115 
00116 static NS_DEFINE_CID(kStringBundleServiceCID, NS_STRINGBUNDLESERVICE_CID);
00117 
00118 #define kInstallLocaleProperties "chrome://global/locale/commonDialogs.properties"
00119 
00126 static void
00127 NS_SoftwareUpdateRequestAutoReg()
00128 {
00129   nsresult rv;
00130   nsCOMPtr<nsIFile> file;
00131 
00132   if (nsSoftwareUpdate::GetProgramDirectory())
00133     // xpistub case, use target directory instead
00134     nsSoftwareUpdate::GetProgramDirectory()->Clone(getter_AddRefs(file));
00135   else
00136     NS_GetSpecialDirectory(NS_XPCOM_CURRENT_PROCESS_DIR,
00137                            getter_AddRefs(file));
00138 
00139   if (!file) {
00140     NS_WARNING("Getting NS_XPCOM_CURRENT_PROCESS_DIR failed");
00141     return;
00142   }
00143 
00144   file->AppendNative(nsDependentCString(".autoreg"));
00145 #ifdef DEBUG_timeless
00146   PRBool condition;
00147   if (NS_SUCCEEDED(file->IsDirectory(&condition)) && condition) {
00148     /* someone did this intentionally, no point in complaining */
00149     return;
00150   }
00151 #endif
00152 
00153   // Remove and recreate the file to update its timestamp.
00154   // .autoreg must be newer than compreg.dat for component registration
00155   // to occur.
00156 
00157   file->Remove(PR_FALSE);
00158   rv = file->Create(nsIFile::NORMAL_FILE_TYPE, 0666);
00159 
00160   if (NS_FAILED(rv)) {
00161     NS_WARNING("creating file failed");
00162     return;
00163   }
00164 }
00165 
00166 
00167 
00168 MOZ_DECL_CTOR_COUNTER(nsInstallInfo)
00169 
00170 nsInstallInfo::nsInstallInfo(PRUint32           aInstallType,
00171                              nsIFile*           aFile,
00172                              const PRUnichar*   aURL,
00173                              const PRUnichar*   aArgs,
00174                              nsIPrincipal*      aPrincipal,
00175                              PRUint32           flags,
00176                              nsIXPIListener*    aListener)
00177 : mPrincipal(aPrincipal),
00178   mError(0),
00179   mType(aInstallType),
00180   mFlags(flags),
00181   mURL(aURL),
00182   mArgs(aArgs),
00183   mFile(aFile),
00184   mListener(aListener)
00185 {
00186     MOZ_COUNT_CTOR(nsInstallInfo);
00187 
00188     nsresult rv;
00189 
00190     // Failure is an option, and will occur in the stub installer.
00191 
00192     NS_WITH_ALWAYS_PROXIED_SERVICE(CHROMEREG_IFACE, cr,
00193                                    NS_CHROMEREGISTRY_CONTRACTID,
00194                                    NS_UI_THREAD_EVENTQ, &rv);
00195     if (NS_SUCCEEDED(rv)) {
00196       mChromeRegistry = cr;
00197 
00198       nsCAutoString spec;
00199       rv = NS_GetURLSpecFromFile(aFile, spec);
00200       if (NS_SUCCEEDED(rv)) {
00201         spec.Insert(NS_LITERAL_CSTRING("jar:"), 0);
00202         spec.AppendLiteral("!/");
00203 #ifdef MOZ_XUL_APP
00204         NS_NewURI(getter_AddRefs(mFileJARURL), spec);
00205 #else
00206         mFileJARSpec.Assign(spec);
00207 #endif
00208       }
00209     }
00210 
00211 #ifdef MOZ_XUL_APP
00212     NS_WITH_ALWAYS_PROXIED_SERVICE(nsIExtensionManager, em,
00213                                    "@mozilla.org/extensions/manager;1",
00214                                    NS_UI_THREAD_EVENTQ, &rv);
00215     if (NS_SUCCEEDED(rv))
00216       mExtensionManager = em;
00217 
00218     nsCOMPtr<nsIFile> manifest;
00219     rv = NS_GetSpecialDirectory(NS_APP_CHROME_DIR, getter_AddRefs(manifest));
00220     if (NS_SUCCEEDED(rv))
00221       NS_NewFileURI(getter_AddRefs(mManifestURL), manifest);
00222 #endif
00223 }
00224 
00225 
00226 nsInstallInfo::~nsInstallInfo()
00227 {
00228   MOZ_COUNT_DTOR(nsInstallInfo);
00229 }
00230 
00231 static NS_DEFINE_IID(kSoftwareUpdateCID,  NS_SoftwareUpdate_CID);
00232 
00233 
00234 MOZ_DECL_CTOR_COUNTER(nsInstall)
00235 
00236 nsInstall::nsInstall(nsIZipReader * theJARFile)
00237 {
00238     MOZ_COUNT_CTOR(nsInstall);
00239 
00240     mScriptObject           = nsnull;           // this is the jsobject for our context
00241     mVersionInfo            = nsnull;           // this is the version information passed to us in StartInstall()
00242     mInstalledFiles         = nsnull;           // the list of installed objects
00243 //  mRegistryPackageName    = "";               // this is the name that we will add into the registry for the component we are installing
00244 //  mUIName                 = "";               // this is the name that will be displayed in UI.
00245     mPatchList              = nsnull;
00246     mUninstallPackage       = PR_FALSE;
00247     mRegisterPackage        = PR_FALSE;
00248     mFinalStatus            = SUCCESS;
00249     mStartInstallCompleted  = PR_FALSE;
00250     mJarFileLocation        = nsnull;
00251     //mInstallArguments       = "";
00252     mPackageFolder          = nsnull;
00253 
00254     // mJarFileData is an opaque handle to the jarfile.
00255     mJarFileData = theJARFile;
00256 
00257     nsISoftwareUpdate *su;
00258     nsresult rv = CallGetService(kSoftwareUpdateCID, &su);
00259 
00260     if (NS_SUCCEEDED(rv))
00261     {
00262         su->GetMasterListener( getter_AddRefs(mListener) );
00263     }
00264 
00265     su->Release();
00266 
00267     // get the resourced xpinstall string bundle
00268     mStringBundle = nsnull;
00269     NS_WITH_PROXIED_SERVICE( nsIStringBundleService,
00270                              service,
00271                              kStringBundleServiceCID,
00272                              NS_UI_THREAD_EVENTQ,
00273                              &rv );
00274 
00275     if (NS_SUCCEEDED(rv) && service)
00276     {
00277         rv = service->CreateBundle( XPINSTALL_BUNDLE_URL,
00278                                     getter_AddRefs(mStringBundle) );
00279     }
00280 }
00281 
00282 nsInstall::~nsInstall()
00283 {
00284     if (mVersionInfo != nsnull)
00285         delete mVersionInfo;
00286 
00287     if (mPackageFolder)
00288         delete mPackageFolder;
00289 
00290     MOZ_COUNT_DTOR(nsInstall);
00291 }
00292 
00293 PRInt32
00294 nsInstall::SetScriptObject(void *aScriptObject)
00295 {
00296   mScriptObject = (JSObject*) aScriptObject;
00297   return NS_OK;
00298 }
00299 
00300 #ifdef _WINDOWS
00301 PRInt32
00302 nsInstall::SaveWinRegPrototype(void *aScriptObject)
00303 {
00304   mWinRegObject = (JSObject*) aScriptObject;
00305   return NS_OK;
00306 }
00307 PRInt32
00308 nsInstall::SaveWinProfilePrototype(void *aScriptObject)
00309 {
00310   mWinProfileObject = (JSObject*) aScriptObject;
00311   return NS_OK;
00312 }
00313 
00314 JSObject*
00315 nsInstall::RetrieveWinRegPrototype()
00316 {
00317   return mWinRegObject;
00318 }
00319 
00320 JSObject*
00321 nsInstall::RetrieveWinProfilePrototype()
00322 {
00323   return mWinProfileObject;
00324 }
00325 #endif
00326 
00327 
00328 PRInt32
00329 nsInstall::GetInstallPlatform(nsCString& aPlatform)
00330 {
00331   if (mInstallPlatform.IsEmpty())
00332   {
00333     // Duplicated from mozilla/netwerk/protocol/http/src/nsHTTPHandler.cpp
00334     // which is not yet available in a wizard install
00335 
00336     // Gather platform.
00337 #if defined(XP_WIN)
00338     mInstallPlatform = "Windows";
00339 #elif defined(XP_MAC) || defined(XP_MACOSX)
00340     mInstallPlatform = "Macintosh";
00341 #elif defined (XP_UNIX)
00342     mInstallPlatform = "X11";
00343 #elif defined(XP_BEOS)
00344     mInstallPlatform = "BeOS";
00345 #elif defined(XP_OS2)
00346     mInstallPlatform = "OS/2";
00347 #endif
00348 
00349     mInstallPlatform += "; ";
00350 
00351     // Gather OS/CPU.
00352 #if defined(XP_WIN)
00353     OSVERSIONINFO info = { sizeof(OSVERSIONINFO) };
00354     if (GetVersionEx(&info)) {
00355         if ( info.dwPlatformId == VER_PLATFORM_WIN32_NT ) {
00356             if (info.dwMajorVersion      == 3) {
00357                 mInstallPlatform += "WinNT3.51";
00358             }
00359             else if (info.dwMajorVersion == 4) {
00360                 mInstallPlatform += "WinNT4.0";
00361             }
00362             else if (info.dwMajorVersion == 5) {
00363                 mInstallPlatform += "Windows NT 5.0";
00364             }
00365             else {
00366                 mInstallPlatform += "WinNT";
00367             }
00368         } else if (info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
00369             if (info.dwMinorVersion == 90)
00370                 mInstallPlatform += "Win 9x 4.90";
00371             else if (info.dwMinorVersion > 0)
00372                 mInstallPlatform += "Win98";
00373             else
00374                 mInstallPlatform += "Win95";
00375         }
00376     }
00377 #elif defined (XP_UNIX) || defined (XP_BEOS)
00378     struct utsname name;
00379 
00380     int ret = uname(&name);
00381     if (ret >= 0) {
00382        mInstallPlatform +=  (char*)name.sysname;
00383        mInstallPlatform += ' ';
00384        mInstallPlatform += (char*)name.release;
00385        mInstallPlatform += ' ';
00386        mInstallPlatform += (char*)name.machine;
00387     }
00388 #elif defined (XP_MAC) || defined (XP_MACOSX)
00389     mInstallPlatform += "PPC";
00390 #elif defined(XP_OS2)
00391     ULONG os2ver = 0;
00392     DosQuerySysInfo(QSV_VERSION_MINOR, QSV_VERSION_MINOR,
00393                     &os2ver, sizeof(os2ver));
00394     if (os2ver == 11)
00395         mInstallPlatform += "2.11";
00396     else if (os2ver == 30)
00397         mInstallPlatform += "Warp 3";
00398     else if (os2ver == 40)
00399         mInstallPlatform += "Warp 4";
00400     else if (os2ver == 45)
00401         mInstallPlatform += "Warp 4.5";
00402     else
00403         mInstallPlatform += "Warp ???";
00404 #endif
00405   }
00406 
00407   aPlatform = mInstallPlatform;
00408   return NS_OK;
00409 }
00410 
00411 
00412 void
00413 nsInstall::InternalAbort(PRInt32 errcode)
00414 {
00415     mFinalStatus = errcode;
00416 
00417     nsInstallObject* ie;
00418     if (mInstalledFiles != nsnull)
00419     {
00420         // abort must work backwards through the list so cleanup can
00421         // happen in the correct order
00422         for (PRInt32 i = mInstalledFiles->Count()-1; i >= 0; i--)
00423         {
00424             ie = (nsInstallObject *)mInstalledFiles->ElementAt(i);
00425             if (ie)
00426                 ie->Abort();
00427         }
00428     }
00429 
00430     CleanUp();
00431 }
00432 
00433 PRInt32
00434 nsInstall::AbortInstall(PRInt32 aErrorNumber)
00435 {
00436     InternalAbort(aErrorNumber);
00437     return NS_OK;
00438 }
00439 
00440 PRInt32
00441 nsInstall::AddDirectory(const nsString& aRegName,
00442                         const nsString& aVersion,
00443                         const nsString& aJarSource,
00444                         nsInstallFolder *aFolder,
00445                         const nsString& aSubdir,
00446                         PRInt32 aMode,
00447                         PRInt32* aReturn)
00448 {
00449     nsInstallFile* ie = nsnull;
00450     PRInt32 result;
00451 
00452     if ( aJarSource.IsEmpty() || aFolder == nsnull )
00453     {
00454         *aReturn = SaveError(nsInstall::INVALID_ARGUMENTS);
00455         return NS_OK;
00456     }
00457 
00458     result = SanityCheck();
00459 
00460     if (result != nsInstall::SUCCESS)
00461     {
00462         *aReturn = SaveError( result );
00463         return NS_OK;
00464     }
00465 
00466     nsString qualifiedRegName;
00467 
00468     if ( aRegName.IsEmpty())
00469     {
00470         // Default subName = location in jar file
00471         *aReturn = GetQualifiedRegName( aJarSource, qualifiedRegName);
00472     }
00473     else
00474     {
00475         *aReturn = GetQualifiedRegName( aRegName, qualifiedRegName );
00476     }
00477 
00478     if (*aReturn != SUCCESS)
00479     {
00480         return NS_OK;
00481     }
00482 
00483     nsString qualifiedVersion = aVersion;
00484     if (qualifiedVersion.IsEmpty())
00485     {
00486         // assume package version for overriden forms that don't take version info
00487         *aReturn = mVersionInfo->ToString(qualifiedVersion);
00488 
00489         if (NS_FAILED(*aReturn))
00490         {
00491             SaveError( nsInstall::UNEXPECTED_ERROR );
00492             return NS_OK;
00493         }
00494     }
00495 
00496     nsString subdirectory(aSubdir);
00497 
00498     if (!subdirectory.IsEmpty())
00499     {
00500         subdirectory.AppendLiteral("/");
00501     }
00502 
00503 
00504     nsVoidArray *paths = new nsVoidArray();
00505 
00506     if (paths == nsnull)
00507     {
00508         *aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
00509         return NS_OK;
00510     }
00511 
00512     PRInt32 count = 0;
00513     result = ExtractDirEntries(aJarSource, paths);
00514     if (result == nsInstall::SUCCESS)
00515     {
00516         count = paths->Count();
00517         if (count == 0)
00518             result = nsInstall::DOES_NOT_EXIST;
00519     }
00520 
00521     for (PRInt32 i=0; i < count && result == nsInstall::SUCCESS; i++)
00522     {
00523         nsString *thisPath = (nsString *)paths->ElementAt(i);
00524 
00525         nsString newJarSource = aJarSource;
00526         newJarSource.AppendLiteral("/");
00527         newJarSource += *thisPath;
00528 
00529         nsString newSubDir;
00530 
00531         if (!subdirectory.IsEmpty())
00532         {
00533             newSubDir = subdirectory;
00534         }
00535 
00536         newSubDir += *thisPath;
00537 
00538         ie = new nsInstallFile( this,
00539                                 qualifiedRegName,
00540                                 qualifiedVersion,
00541                                 newJarSource,
00542                                 aFolder,
00543                                 newSubDir,
00544                                 aMode,
00545                                 (i == 0), // register the first one only
00546                                 &result);
00547 
00548         if (ie == nsnull)
00549         {
00550             result = nsInstall::OUT_OF_MEMORY;
00551         }
00552         else if (result != nsInstall::SUCCESS)
00553         {
00554             delete ie;
00555         }
00556         else
00557         {
00558             result = ScheduleForInstall( ie );
00559         }
00560     }
00561 
00562     DeleteVector(paths);
00563 
00564     *aReturn = SaveError( result );
00565     return NS_OK;
00566 }
00567 
00568 PRInt32
00569 nsInstall::AddDirectory(const nsString& aRegName,
00570                         const nsString& aVersion,
00571                         const nsString& aJarSource,
00572                         nsInstallFolder *aFolder,
00573                         const nsString& aSubdir,
00574                         PRInt32* aReturn)
00575 {
00576     return AddDirectory(aRegName,
00577                         aVersion,
00578                         aJarSource,
00579                         aFolder,
00580                         aSubdir,
00581                         INSTALL_NO_COMPARE,
00582                         aReturn);
00583 }
00584 
00585 PRInt32
00586 nsInstall::AddDirectory(const nsString& aRegName,
00587                         const nsString& aJarSource,
00588                         nsInstallFolder *aFolder,
00589                         const nsString& aSubdir,
00590                         PRInt32* aReturn)
00591 {
00592     return AddDirectory(aRegName,
00593                         EmptyString(),
00594                         aJarSource,
00595                         aFolder,
00596                         aSubdir,
00597                         INSTALL_NO_COMPARE,
00598                         aReturn);
00599 }
00600 
00601 PRInt32
00602 nsInstall::AddDirectory(const nsString& aJarSource,
00603                         PRInt32* aReturn)
00604 {
00605     if(mPackageFolder == nsnull)
00606     {
00607         *aReturn = SaveError( nsInstall::PACKAGE_FOLDER_NOT_SET );
00608         return NS_OK;
00609     }
00610 
00611     return AddDirectory(EmptyString(),
00612                         EmptyString(),
00613                         aJarSource,
00614                         mPackageFolder,
00615                         EmptyString(),
00616                         INSTALL_NO_COMPARE,
00617                         aReturn);
00618 }
00619 
00620 PRInt32
00621 nsInstall::AddSubcomponent(const nsString& aRegName,
00622                            const nsString& aVersion,
00623                            const nsString& aJarSource,
00624                            nsInstallFolder *aFolder,
00625                            const nsString& aTargetName,
00626                            PRInt32 aMode,
00627                            PRInt32* aReturn)
00628 {
00629     nsInstallFile*  ie;
00630     nsString        qualifiedRegName;
00631     nsString        qualifiedVersion = aVersion;
00632     nsString        tempTargetName   = aTargetName;
00633 
00634     PRInt32         errcode = nsInstall::SUCCESS;
00635 
00636 
00637     if(aJarSource.IsEmpty() || aFolder == nsnull )
00638     {
00639         *aReturn = SaveError( nsInstall::INVALID_ARGUMENTS );
00640         return NS_OK;
00641     }
00642 
00643     PRInt32 result = SanityCheck();
00644 
00645     if (result != nsInstall::SUCCESS)
00646     {
00647         *aReturn = SaveError( result );
00648         return NS_OK;
00649     }
00650 
00651     if( aTargetName.IsEmpty() )
00652     {
00653         PRInt32 pos = aJarSource.RFindChar('/');
00654 
00655         if ( pos == kNotFound )
00656             tempTargetName = aJarSource;
00657         else
00658             aJarSource.Right(tempTargetName, aJarSource.Length() - (pos+1));
00659     }
00660 
00661     if (qualifiedVersion.IsEmpty())
00662         qualifiedVersion.AssignLiteral("0.0.0.0");
00663 
00664 
00665     if ( aRegName.IsEmpty() )
00666     {
00667         // Default subName = location in jar file
00668         *aReturn = GetQualifiedRegName( aJarSource, qualifiedRegName);
00669     }
00670     else
00671     {
00672         *aReturn = GetQualifiedRegName( aRegName, qualifiedRegName );
00673     }
00674 
00675     if (*aReturn != SUCCESS)
00676     {
00677         return NS_OK;
00678     }
00679 
00680 
00681     ie = new nsInstallFile( this,
00682                             qualifiedRegName,
00683                             qualifiedVersion,
00684                             aJarSource,
00685                             aFolder,
00686                             tempTargetName,
00687                             aMode,
00688                             PR_TRUE,
00689                             &errcode );
00690 
00691     if (ie == nsnull)
00692     {
00693         *aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
00694             return NS_OK;
00695     }
00696 
00697     if (errcode == nsInstall::SUCCESS)
00698     {
00699         errcode = ScheduleForInstall( ie );
00700     }
00701     else
00702     {
00703         delete ie;
00704     }
00705 
00706     *aReturn = SaveError( errcode );
00707     return NS_OK;
00708 }
00709 
00710 PRInt32
00711 nsInstall::AddSubcomponent(const nsString& aRegName,
00712                            const nsString& aVersion,
00713                            const nsString& aJarSource,
00714                            nsInstallFolder* aFolder,
00715                            const nsString& aTargetName,
00716                            PRInt32* aReturn)
00717 {
00718     return AddSubcomponent(aRegName,
00719                            aVersion,
00720                            aJarSource,
00721                            aFolder,
00722                            aTargetName,
00723                            INSTALL_NO_COMPARE,
00724                            aReturn);
00725 }
00726 
00727 PRInt32
00728 nsInstall::AddSubcomponent(const nsString& aRegName,
00729                            const nsString& aJarSource,
00730                            nsInstallFolder* aFolder,
00731                            const nsString& aTargetName,
00732                            PRInt32* aReturn)
00733 {
00734     PRInt32 result = SanityCheck();
00735 
00736     if (result != nsInstall::SUCCESS)
00737     {
00738         *aReturn = SaveError( result );
00739         return NS_OK;
00740     }
00741 
00742     nsString version;
00743     *aReturn = mVersionInfo->ToString(version);
00744 
00745     if (NS_FAILED(*aReturn))
00746     {
00747         SaveError( nsInstall::UNEXPECTED_ERROR );
00748         return NS_OK;
00749     }
00750 
00751     return AddSubcomponent(aRegName,
00752                            version,
00753                            aJarSource,
00754                            aFolder,
00755                            aTargetName,
00756                            INSTALL_NO_COMPARE,
00757                            aReturn);
00758 }
00759 
00760 PRInt32
00761 nsInstall::AddSubcomponent(const nsString& aJarSource,
00762                            PRInt32* aReturn)
00763 {
00764     if(mPackageFolder == nsnull)
00765     {
00766         *aReturn = SaveError( nsInstall::PACKAGE_FOLDER_NOT_SET );
00767         return NS_OK;
00768     }
00769     PRInt32 result = SanityCheck();
00770 
00771     if (result != nsInstall::SUCCESS)
00772     {
00773         *aReturn = SaveError( result );
00774         return NS_OK;
00775     }
00776 
00777     nsString version;
00778     *aReturn = mVersionInfo->ToString(version);
00779 
00780     if (NS_FAILED(*aReturn))
00781     {
00782         SaveError( nsInstall::UNEXPECTED_ERROR );
00783         return NS_OK;
00784     }
00785 
00786     return AddSubcomponent(EmptyString(),
00787                            version,
00788                            aJarSource,
00789                            mPackageFolder,
00790                            EmptyString(),
00791                            INSTALL_NO_COMPARE,
00792                            aReturn);
00793 }
00794 
00795 
00796 PRInt32
00797 nsInstall::DiskSpaceAvailable(const nsString& aFolder, PRInt64* aReturn)
00798 {
00799     PRInt32 result = SanityCheck();
00800 
00801     if (result != nsInstall::SUCCESS)
00802     {
00803         double d = SaveError( result );
00804         LL_L2D(d, *aReturn);
00805         return NS_OK;
00806     }
00807     nsCOMPtr<nsILocalFile> folder;
00808     NS_NewLocalFile(aFolder, PR_TRUE, getter_AddRefs(folder));
00809 
00810     result = folder->GetDiskSpaceAvailable(aReturn);
00811     return NS_OK;
00812 }
00813 
00814 PRInt32
00815 nsInstall::Execute(const nsString& aJarSource, const nsString& aArgs, PRBool aBlocking, PRInt32* aReturn)
00816 {
00817     PRInt32 result = SanityCheck();
00818 
00819     if (result != nsInstall::SUCCESS)
00820     {
00821         *aReturn = SaveError( result );
00822         return NS_OK;
00823     }
00824 
00825     nsInstallExecute* ie = new nsInstallExecute(this, aJarSource, aArgs, aBlocking, &result);
00826 
00827     if (ie == nsnull)
00828     {
00829         *aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
00830         return NS_OK;
00831     }
00832 
00833     if (result == nsInstall::SUCCESS)
00834     {
00835         result = ScheduleForInstall( ie );
00836     }
00837 
00838     *aReturn = SaveError(result);
00839     return NS_OK;
00840 }
00841 
00842 
00843 PRInt32
00844 nsInstall::FinalizeInstall(PRInt32* aReturn)
00845 {
00846     PRInt32 result = SUCCESS;
00847     PRBool  rebootNeeded = PR_FALSE;
00848 
00849     *aReturn = SanityCheck();
00850 
00851     if (*aReturn != nsInstall::SUCCESS)
00852     {
00853         SaveError( *aReturn );
00854         mFinalStatus = *aReturn;
00855         return NS_OK;
00856     }
00857 
00858 
00859     if ( mInstalledFiles->Count() > 0 )
00860     {
00861         if ( mUninstallPackage )
00862         {
00863             VR_UninstallCreateNode( NS_CONST_CAST(char *, NS_ConvertUCS2toUTF8(mRegistryPackageName).get()),
00864                                     NS_CONST_CAST(char *, NS_ConvertUCS2toUTF8(mUIName).get()));
00865         }
00866 
00867         // Install the Component into the Version Registry.
00868         if (mVersionInfo)
00869         {
00870             nsString versionString;
00871             nsCString path;
00872 
00873             mVersionInfo->ToString(versionString);
00874             nsCAutoString versionCString;
00875             versionCString.AssignWithConversion(versionString);
00876 
00877             if (mPackageFolder)
00878                 mPackageFolder->GetDirectoryPath(path);
00879 
00880             VR_Install( NS_CONST_CAST(char *, NS_ConvertUCS2toUTF8(mRegistryPackageName).get()),
00881                         NS_CONST_CAST(char *, path.get()),
00882                         NS_CONST_CAST(char *, versionCString.get()),
00883                         PR_TRUE );
00884         }
00885 
00886         nsInstallObject* ie = nsnull;
00887 
00888         for (PRInt32 i=0; i < mInstalledFiles->Count(); i++)
00889         {
00890             ie = (nsInstallObject*)mInstalledFiles->ElementAt(i);
00891             NS_ASSERTION(ie, "NULL object in install queue!");
00892             if (ie == NULL)
00893                 continue;
00894 
00895             if (mListener)
00896             {
00897                 char *objString = ie->toString();
00898                 if (objString)
00899                 {
00900                     mListener->OnFinalizeProgress(
00901                                     NS_ConvertASCIItoUCS2(objString).get(),
00902                                     (i+1), mInstalledFiles->Count());
00903                     delete [] objString;
00904                 }
00905             }
00906 
00907             result = ie->Complete();
00908 
00909             if (result != nsInstall::SUCCESS)
00910             {
00911                 if ( result == REBOOT_NEEDED )
00912                 {
00913                     rebootNeeded = PR_TRUE;
00914                     result = SUCCESS;
00915                 }
00916                 else
00917                 {
00918                     InternalAbort( result );
00919                     break;
00920                 }
00921             }
00922         }
00923 
00924         if ( result == SUCCESS )
00925         {
00926             if ( rebootNeeded )
00927                 *aReturn = SaveError( REBOOT_NEEDED );
00928 
00929             if ( nsSoftwareUpdate::mNeedCleanup )
00930             {
00931                 // Broadcast the fact that we have an incomplete install so
00932                 // parts of Mozilla can take defensive action if necessary.
00933                 //
00934                 // This notification turns off turbo/server mode, for example
00935                 nsPIXPIProxy* proxy = GetUIThreadProxy();
00936                 if (proxy)
00937                     proxy->NotifyRestartNeeded();
00938             }
00939 
00940             // XXX for now all successful installs will trigger an Autoreg.
00941             // We eventually want to do this only when flagged.
00942             NS_SoftwareUpdateRequestAutoReg();
00943         }
00944         else
00945             *aReturn = SaveError( result );
00946 
00947         mFinalStatus = *aReturn;
00948     }
00949     else
00950     {
00951         // no actions queued: don't register the package version
00952         // and no need for user confirmation
00953 
00954         mFinalStatus = *aReturn;
00955     }
00956 
00957     CleanUp();
00958 
00959     return NS_OK;
00960 }
00961 
00962 #if defined(XP_MAC) || defined(XP_MACOSX)
00963 #define GESTALT_CHAR_CODE(x)          (((unsigned long) ((x[0]) & 0x000000FF)) << 24) \
00964                                     | (((unsigned long) ((x[1]) & 0x000000FF)) << 16) \
00965                                     | (((unsigned long) ((x[2]) & 0x000000FF)) << 8)  \
00966                                     | (((unsigned long) ((x[3]) & 0x000000FF)))
00967 #endif /* XP_MACOS || XP_MACOSX */
00968 
00969 PRInt32
00970 nsInstall::Gestalt(const nsString& aSelector, PRInt32* aReturn)
00971 {
00972     *aReturn = nsnull;
00973 
00974     PRInt32 result = SanityCheck();
00975 
00976     if (result != nsInstall::SUCCESS)
00977     {
00978         *aReturn = SaveError( result );
00979         return NS_OK;
00980     }
00981 #if defined(XP_MAC) || defined(XP_MACOSX)
00982 
00983     long    response = 0;
00984     char    selectorChars[4];
00985     int     i;
00986     OSErr   err = noErr;
00987     OSType  selector;
00988 
00989     if (aSelector.IsEmpty())
00990     {
00991         return NS_OK;
00992     }
00993 
00994     for (i=0; i<4; i++)
00995         selectorChars[i] = aSelector.CharAt(i);
00996     selector = GESTALT_CHAR_CODE(selectorChars);
00997 
00998     err = ::Gestalt(selector, &response);
00999 
01000     if (err != noErr)
01001         *aReturn = err;
01002     else
01003         *aReturn = response;
01004 
01005 #endif /* XP_MAC || XP_MACOSX */
01006     return NS_OK;
01007 }
01008 
01009 PRInt32
01010 nsInstall::GetComponentFolder(const nsString& aComponentName, const nsString& aSubdirectory, nsInstallFolder** aNewFolder)
01011 {
01012     long        err;
01013     char        dir[MAXREGPATHLEN];
01014     nsresult    res = NS_OK;
01015 
01016     if(!aNewFolder)
01017         return INVALID_ARGUMENTS;
01018 
01019     *aNewFolder = nsnull;
01020 
01021 
01022     nsString tempString;
01023 
01024     if ( GetQualifiedPackageName(aComponentName, tempString) != SUCCESS )
01025     {
01026         return NS_OK;
01027     }
01028 
01029     NS_ConvertUCS2toUTF8 componentCString(tempString);
01030 
01031     if((err = VR_GetDefaultDirectory( NS_CONST_CAST(char *, componentCString.get()), sizeof(dir), dir )) != REGERR_OK)
01032     {
01033         // if there's not a default directory, try to see if the component
01034         // // is registered as a file and then strip the filename off the path
01035         if((err = VR_GetPath( NS_CONST_CAST(char *, componentCString.get()), sizeof(dir), dir )) != REGERR_OK)
01036         {
01037           // no path, either
01038           *dir = '\0';
01039         }
01040     }
01041 
01042     nsCOMPtr<nsILocalFile> componentDir;
01043     nsCOMPtr<nsIFile> componentIFile;
01044     if(*dir != '\0')
01045         NS_NewNativeLocalFile( nsDependentCString(dir), PR_FALSE, getter_AddRefs(componentDir) );
01046 
01047     if ( componentDir )
01048     {
01049         PRBool isFile;
01050 
01051         res = componentDir->IsFile(&isFile);
01052         if (NS_SUCCEEDED(res) && isFile)
01053             componentDir->GetParent(getter_AddRefs(componentIFile));
01054         else
01055             componentIFile = do_QueryInterface(componentDir);
01056 
01057         nsInstallFolder * folder = new nsInstallFolder();
01058         if (!folder)
01059             return NS_ERROR_OUT_OF_MEMORY;
01060 
01061         res = folder->Init(componentIFile, aSubdirectory);
01062         if (NS_FAILED(res))
01063         {
01064             delete folder;
01065         }
01066         else
01067         {
01068             *aNewFolder = folder;
01069         }
01070     }
01071 
01072     return res;
01073 }
01074 
01075 PRInt32
01076 nsInstall::GetComponentFolder(const nsString& aComponentName, nsInstallFolder** aNewFolder)
01077 {
01078     return GetComponentFolder(aComponentName, EmptyString(), aNewFolder);
01079 }
01080 
01081 PRInt32
01082 nsInstall::GetFolder(const nsString& targetFolder, const nsString& aSubdirectory, nsInstallFolder** aNewFolder)
01083 {
01084     /* This version of GetFolder takes an nsString object as the first param */
01085     if (!aNewFolder)
01086         return INVALID_ARGUMENTS;
01087 
01088     * aNewFolder = nsnull;
01089 
01090     nsInstallFolder* folder = new nsInstallFolder();
01091     if (folder == nsnull)
01092     {
01093         return NS_ERROR_OUT_OF_MEMORY;
01094     }
01095     nsresult res = folder->Init(targetFolder, aSubdirectory);
01096 
01097     if (NS_FAILED(res))
01098     {
01099         delete folder;
01100         return res;
01101     }
01102     *aNewFolder = folder;
01103     return NS_OK;
01104 }
01105 
01106 PRInt32
01107 nsInstall::GetFolder(const nsString& targetFolder, nsInstallFolder** aNewFolder)
01108 {
01109     /* This version of GetFolder takes an nsString object as the only param */
01110     return GetFolder(targetFolder, EmptyString(), aNewFolder);
01111 }
01112 
01113 PRInt32
01114 nsInstall::GetFolder( nsInstallFolder& aTargetFolderObj, const nsString& aSubdirectory, nsInstallFolder** aNewFolder )
01115 {
01116     /* This version of GetFolder takes an nsString object as the first param */
01117     if (!aNewFolder)
01118         return INVALID_ARGUMENTS;
01119 
01120     * aNewFolder = nsnull;
01121 
01122     nsInstallFolder* folder = new nsInstallFolder();
01123     if (folder == nsnull)
01124     {
01125         return NS_ERROR_OUT_OF_MEMORY;
01126     }
01127     nsresult res = folder->Init(aTargetFolderObj, aSubdirectory);
01128 
01129     if (NS_FAILED(res))
01130     {
01131         delete folder;
01132         return res;
01133     }
01134     *aNewFolder = folder;
01135     return NS_OK;
01136 }
01137 
01138 
01139 
01140 
01141 PRInt32
01142 nsInstall::GetLastError(PRInt32* aReturn)
01143 {
01144     *aReturn = mLastError;
01145     return NS_OK;
01146 }
01147 
01148 PRInt32
01149 nsInstall::GetWinProfile(const nsString& aFolder, const nsString& aFile, JSContext* jscontext, JSClass* WinProfileClass, jsval* aReturn)
01150 {
01151     *aReturn = JSVAL_NULL;
01152 
01153     if (SanityCheck() != nsInstall::SUCCESS)
01154     {
01155         return NS_OK;
01156     }
01157 
01158 #ifdef _WINDOWS
01159     JSObject*     winProfileObject;
01160     nsWinProfile* nativeWinProfileObject = new nsWinProfile(this, aFolder, aFile);
01161 
01162     if (nativeWinProfileObject == nsnull)
01163         return NS_OK;
01164 
01165     JSObject*     winProfilePrototype    = this->RetrieveWinProfilePrototype();
01166 
01167     winProfileObject = JS_NewObject(jscontext, WinProfileClass, winProfilePrototype, NULL);
01168     if(winProfileObject == NULL)
01169         return NS_OK;
01170 
01171     JS_SetPrivate(jscontext, winProfileObject, nativeWinProfileObject);
01172 
01173     *aReturn = OBJECT_TO_JSVAL(winProfileObject);
01174 #endif /* _WINDOWS */
01175 
01176     return NS_OK;
01177 }
01178 
01179 PRInt32
01180 nsInstall::GetWinRegistry(JSContext* jscontext, JSClass* WinRegClass, jsval* aReturn)
01181 {
01182     *aReturn = JSVAL_NULL;
01183 
01184     if (SanityCheck() != nsInstall::SUCCESS)
01185     {
01186         return NS_OK;
01187     }
01188 
01189 #ifdef _WINDOWS
01190     JSObject* winRegObject;
01191     nsWinReg* nativeWinRegObject = new nsWinReg(this);
01192 
01193     if (nativeWinRegObject == nsnull)
01194         return NS_OK;
01195 
01196     JSObject* winRegPrototype    = this->RetrieveWinRegPrototype();
01197 
01198     winRegObject = JS_NewObject(jscontext, WinRegClass, winRegPrototype, NULL);
01199     if(winRegObject == NULL)
01200         return NS_OK;
01201 
01202     JS_SetPrivate(jscontext, winRegObject, nativeWinRegObject);
01203 
01204     *aReturn = OBJECT_TO_JSVAL(winRegObject);
01205 #endif /* _WINDOWS */
01206 
01207     return NS_OK;
01208 }
01209 
01210 PRInt32
01211 nsInstall::LoadResources(JSContext* cx, const nsString& aBaseName, jsval* aReturn)
01212 {
01213     *aReturn = JSVAL_NULL;
01214  
01215     if (SanityCheck() != nsInstall::SUCCESS)
01216     {
01217         return NS_OK;
01218     }
01219     nsresult ret;
01220     nsCOMPtr<nsIFile> resFile;
01221     nsIURI *url = nsnull;
01222     nsIStringBundleService* service = nsnull;
01223     nsIEventQueueService* pEventQueueService = nsnull;
01224     nsIStringBundle* bundle = nsnull;
01225     nsCOMPtr<nsISimpleEnumerator> propEnum;
01226     jsval v = JSVAL_NULL;
01227 
01228     // set up JSObject to return
01229     JS_GetProperty( cx, JS_GetGlobalObject( cx ), "Object", &v );
01230     if (!v)
01231     {
01232         return NS_ERROR_NULL_POINTER;
01233     }
01234     JSClass *objclass = JS_GetClass( cx, JSVAL_TO_OBJECT(v) );
01235     JSObject *res = JS_NewObject( cx, objclass, JSVAL_TO_OBJECT(v), 0 );
01236 
01237     // extract properties file
01238     // XXX append locale info: lang code, country code, .properties suffix to aBaseName
01239     PRInt32 err = ExtractFileFromJar(aBaseName, nsnull, getter_AddRefs(resFile));
01240     if ( (!resFile) || (err != nsInstall::SUCCESS)  )
01241     {
01242         SaveError( err );
01243         return NS_OK;
01244     }
01245 
01246     // initialize string bundle and related services
01247     ret = CallGetService(kStringBundleServiceCID, &service);
01248     if (NS_FAILED(ret))
01249         goto cleanup;
01250     ret = CallGetService(kEventQueueServiceCID, &pEventQueueService);
01251     if (NS_FAILED(ret))
01252         goto cleanup;
01253     ret = pEventQueueService->CreateThreadEventQueue();
01254     NS_RELEASE(pEventQueueService);
01255     if (NS_FAILED(ret))
01256         goto cleanup;
01257 
01258     // get the string bundle using the extracted properties file
01259 #if 1
01260     {
01261       nsCAutoString spec;
01262       ret = NS_GetURLSpecFromFile(resFile, spec);
01263       if (NS_FAILED(ret)) {
01264         NS_WARNING("cannot get url spec\n");
01265         NS_RELEASE(service);
01266         return ret;
01267       }
01268       ret = service->CreateBundle(spec.get(), &bundle);
01269     }
01270 #else
01271     ret = service->CreateBundle(url, &bundle);
01272 #endif
01273     if (NS_FAILED(ret))
01274         goto cleanup;
01275     ret = bundle->GetSimpleEnumeration(getter_AddRefs(propEnum));
01276     if (NS_FAILED(ret))
01277         goto cleanup;
01278 
01279     // set the variables of the JSObject to return using the StringBundle's
01280     // enumeration service
01281     PRBool hasMore;
01282     while (NS_SUCCEEDED(propEnum->HasMoreElements(&hasMore)) && hasMore)
01283     {
01284         nsCOMPtr<nsISupports> nextProp;
01285         ret = propEnum->GetNext(getter_AddRefs(nextProp));
01286         if (NS_FAILED(ret))
01287             goto cleanup;
01288 
01289         nsCOMPtr<nsIPropertyElement> propElem =
01290             do_QueryInterface(nextProp);
01291         if (!propElem)
01292             continue;
01293 
01294         nsAutoString pVal;
01295         nsCAutoString pKey;
01296         ret = propElem->GetKey(pKey);
01297         if (NS_FAILED(ret))
01298             goto cleanup;
01299         ret = propElem->GetValue(pVal);
01300         if (NS_FAILED(ret))
01301             goto cleanup;
01302 
01303         if (!pKey.IsEmpty() && !pVal.IsEmpty())
01304         {
01305             JSString* propValJSStr = JS_NewUCStringCopyZ(cx, NS_REINTERPRET_CAST(const jschar*, pVal.get()));
01306             jsval propValJSVal = STRING_TO_JSVAL(propValJSStr);
01307             NS_ConvertUTF8toUTF16 UCKey(pKey);
01308             JS_SetUCProperty(cx, res, (jschar*)UCKey.get(), UCKey.Length(), &propValJSVal);
01309         }
01310     }
01311 
01312     *aReturn = OBJECT_TO_JSVAL(res);
01313     ret = nsInstall::SUCCESS;
01314 
01315 cleanup:
01316     SaveError( ret );
01317 
01318     // release services
01319     NS_IF_RELEASE( service );
01320 
01321     // release file, URL, StringBundle, Enumerator
01322     NS_IF_RELEASE( url );
01323     NS_IF_RELEASE( bundle );
01324 
01325     return NS_OK;
01326 }
01327 
01328 PRInt32
01329 nsInstall::Patch(const nsString& aRegName, const nsString& aVersion, const nsString& aJarSource, nsInstallFolder* aFolder, const nsString& aTargetName, PRInt32* aReturn)
01330 {
01331     PRInt32 result = SanityCheck();
01332 
01333     if (result != nsInstall::SUCCESS)
01334     {
01335         *aReturn = SaveError( result );
01336         return NS_OK;
01337     }
01338 
01339     nsString qualifiedRegName;
01340 
01341     *aReturn = GetQualifiedRegName( aRegName, qualifiedRegName);
01342 
01343     if (*aReturn != SUCCESS)
01344     {
01345         return NS_OK;
01346     }
01347 
01348     if (!mPatchList)
01349     {
01350         mPatchList = new nsHashtable();
01351         if (mPatchList == nsnull)
01352         {
01353             *aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
01354             return NS_OK;
01355         }
01356     }
01357 
01358     nsInstallPatch* ip = new nsInstallPatch( this,
01359                                              qualifiedRegName,
01360                                              aVersion,
01361                                              aJarSource,
01362                                              aFolder,
01363                                              aTargetName,
01364                                              &result);
01365 
01366     if (ip == nsnull)
01367     {
01368         *aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
01369         return NS_OK;
01370     }
01371 
01372     if (result == nsInstall::SUCCESS)
01373     {
01374         result = ScheduleForInstall( ip );
01375     }
01376 
01377     *aReturn = SaveError(result);
01378     return NS_OK;
01379 }
01380 
01381 PRInt32
01382 nsInstall::Patch(const nsString& aRegName, const nsString& aJarSource, nsInstallFolder* aFolder, const nsString& aTargetName, PRInt32* aReturn)
01383 {
01384     return Patch(aRegName, EmptyString(), aJarSource, aFolder, aTargetName, aReturn);
01385 }
01386 
01387 PRInt32
01388 nsInstall::RegisterChrome(nsIFile* chrome, PRUint32 chromeType, const char* path)
01389 {
01390     PRInt32 result = SanityCheck();
01391     if (result != SUCCESS)
01392         return SaveError( result );
01393 
01394     if (!chrome || !chromeType)
01395         return SaveError( INVALID_ARGUMENTS );
01396 
01397     nsRegisterItem* ri = new nsRegisterItem(this, chrome, chromeType, path);
01398     if (ri == nsnull)
01399         return SaveError(OUT_OF_MEMORY);
01400     else
01401         return SaveError(ScheduleForInstall( ri ));
01402 }
01403 
01404 nsPIXPIProxy* nsInstall::GetUIThreadProxy()
01405 {
01406     if (!mUIThreadProxy)
01407     {
01408         nsresult rv;
01409         nsCOMPtr<nsIProxyObjectManager> pmgr =
01410                  do_GetService(kProxyObjectManagerCID, &rv);
01411         if (NS_SUCCEEDED(rv))
01412         {
01413             nsCOMPtr<nsPIXPIProxy> tmp(do_QueryInterface(new nsXPIProxy()));
01414             rv = pmgr->GetProxyForObject( NS_UI_THREAD_EVENTQ, NS_GET_IID(nsPIXPIProxy),
01415                     tmp, PROXY_SYNC | PROXY_ALWAYS, getter_AddRefs(mUIThreadProxy) );
01416         }
01417     }
01418 
01419     return mUIThreadProxy;
01420 }
01421 
01422 PRInt32
01423 nsInstall::RefreshPlugins(PRBool aReloadPages)
01424 {
01425     nsPIXPIProxy* proxy = GetUIThreadProxy();
01426     if (!proxy)
01427         return UNEXPECTED_ERROR;
01428 
01429     return proxy->RefreshPlugins(aReloadPages);
01430 }
01431 
01432 
01433 PRInt32
01434 nsInstall::ResetError(PRInt32 aError)
01435 {
01436     mLastError = aError;
01437     return SUCCESS;
01438 }
01439 
01440 PRInt32
01441 nsInstall::SetPackageFolder(nsInstallFolder& aFolder)
01442 {
01443     if (mPackageFolder)
01444         delete mPackageFolder;
01445 
01446     nsInstallFolder* folder = new nsInstallFolder();
01447     if (folder == nsnull)
01448     {
01449         return OUT_OF_MEMORY;
01450     }
01451     nsresult res = folder->Init(aFolder, EmptyString());
01452 
01453     if (NS_FAILED(res))
01454     {
01455         delete folder;
01456         return UNEXPECTED_ERROR;
01457     }
01458     mPackageFolder = folder;
01459     return SUCCESS;
01460 }
01461 
01462 
01463 PRInt32
01464 nsInstall::StartInstall(const nsString& aUserPackageName, const nsString& aRegistryPackageName, const nsString& aVersion, PRInt32* aReturn)
01465 {
01466     if ( aUserPackageName.IsEmpty() )
01467     {
01468         // There must be some pretty name for the UI and the uninstall list
01469         *aReturn = SaveError(INVALID_ARGUMENTS);
01470         return NS_OK;
01471     }
01472 
01473     char szRegPackagePath[MAXREGPATHLEN];
01474 
01475     *szRegPackagePath = '0';
01476     *aReturn   = nsInstall::SUCCESS;
01477 
01478     ResetError(nsInstall::SUCCESS);
01479 
01480     mUserCancelled = PR_FALSE;
01481 
01482     mUIName = aUserPackageName;
01483 
01484     *aReturn = GetQualifiedPackageName( aRegistryPackageName, mRegistryPackageName );
01485 
01486     if (*aReturn != nsInstall::SUCCESS)
01487     {
01488         SaveError( *aReturn );
01489         return NS_OK;
01490     }
01491 
01492     // initialize default version
01493     if (mVersionInfo != nsnull)
01494         delete mVersionInfo;
01495 
01496     mVersionInfo    = new nsInstallVersion();
01497     if (mVersionInfo == nsnull)
01498     {
01499         *aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
01500         return NS_OK;
01501     }
01502     mVersionInfo->Init(aVersion);
01503 
01504     // initialize item queue
01505     mInstalledFiles = new nsVoidArray();
01506 
01507     if (mInstalledFiles == nsnull)
01508     {
01509         *aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
01510         return NS_OK;
01511     }
01512 
01513     // initialize default folder if any (errors are OK)
01514     if (mPackageFolder != nsnull)
01515         delete mPackageFolder;
01516 
01517     mPackageFolder = nsnull;
01518     if(REGERR_OK == VR_GetDefaultDirectory(
01519                         NS_CONST_CAST(char *, NS_ConvertUCS2toUTF8(mRegistryPackageName).get()),
01520                         sizeof(szRegPackagePath), szRegPackagePath))
01521     {
01522         // found one saved in the registry
01523         mPackageFolder = new nsInstallFolder();
01524         nsCOMPtr<nsILocalFile> packageDir;
01525         NS_NewNativeLocalFile(
01526                             nsDependentCString(szRegPackagePath), // native path
01527                             PR_FALSE, getter_AddRefs(packageDir) );
01528 
01529         if (mPackageFolder && packageDir)
01530         {
01531             if (NS_FAILED( mPackageFolder->Init(packageDir, EmptyString()) ))
01532             {
01533                 delete mPackageFolder;
01534                 mPackageFolder = nsnull;
01535             }
01536         }
01537     }
01538 
01539     // We've correctly initialized an install transaction
01540     // - note that for commands that are only valid within one
01541     // - save error in case script doesn't call performInstall or cancelInstall
01542     // - broadcast to listeners
01543     mStartInstallCompleted = PR_TRUE;
01544     mFinalStatus = MALFORMED_INSTALL;
01545     if (mListener)
01546         mListener->OnPackageNameSet(mInstallURL.get(), mUIName.get(), aVersion.get());
01547 
01548     return NS_OK;
01549 }
01550 
01551 
01552 PRInt32
01553 nsInstall::Uninstall(const nsString& aRegistryPackageName, PRInt32* aReturn)
01554 {
01555     PRInt32 result = SanityCheck();
01556 
01557     if (result != nsInstall::SUCCESS)
01558     {
01559         *aReturn = SaveError( result );
01560         return NS_OK;
01561     }
01562 
01563     nsString qualifiedPackageName;
01564 
01565     *aReturn = GetQualifiedPackageName( aRegistryPackageName, qualifiedPackageName );
01566 
01567     if (*aReturn != SUCCESS)
01568     {
01569         return NS_OK;
01570     }
01571 
01572     nsInstallUninstall *ie = new nsInstallUninstall( this,
01573                                                      qualifiedPackageName,
01574                                                      &result );
01575 
01576     if (ie == nsnull)
01577     {
01578         *aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
01579         return NS_OK;
01580     }
01581 
01582     if (result == nsInstall::SUCCESS)
01583     {
01584         result = ScheduleForInstall( ie );
01585     }
01586     else
01587     {
01588         delete ie;
01589     }
01590 
01591     *aReturn = SaveError(result);
01592 
01593     return NS_OK;
01594 }
01595 
01597 
01598 
01599 void
01600 nsInstall::AddPatch(nsHashKey *aKey, nsIFile* fileName)
01601 {
01602     if (mPatchList != nsnull)
01603     {
01604         mPatchList->Put(aKey, fileName);
01605     }
01606 }
01607 
01608 void
01609 nsInstall::GetPatch(nsHashKey *aKey, nsIFile** fileName)
01610 {
01611     if (!fileName)
01612         return;
01613     else
01614         *fileName = nsnull;
01615 
01616     if (mPatchList)
01617     {
01618         NS_IF_ADDREF(*fileName = (nsIFile*) mPatchList->Get(aKey));
01619     }
01620 }
01621 
01622 PRInt32
01623 nsInstall::FileOpDirCreate(nsInstallFolder& aTarget, PRInt32* aReturn)
01624 {
01625   nsCOMPtr<nsIFile> localFile = aTarget.GetFileSpec();
01626   if (localFile == nsnull)
01627   {
01628      *aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
01629      return NS_OK;
01630   }
01631 
01632   nsInstallFileOpItem* ifop = new nsInstallFileOpItem(this, NS_FOP_DIR_CREATE, localFile, aReturn);
01633   if (ifop == nsnull)
01634   {
01635       *aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
01636       return NS_OK;
01637   }
01638 
01639   PRInt32 result = SanityCheck();
01640   if (result != nsInstall::SUCCESS)
01641   {
01642       delete ifop;
01643       *aReturn = SaveError( result );
01644       return NS_OK;
01645   }
01646 
01647   if (*aReturn == nsInstall::SUCCESS)
01648   {
01649       *aReturn = ScheduleForInstall( ifop );
01650   }
01651 
01652   SaveError(*aReturn);
01653 
01654   return NS_OK;
01655 }
01656 
01657 PRInt32
01658 nsInstall::FileOpDirGetParent(nsInstallFolder& aTarget, nsInstallFolder** theParentFolder)
01659 {
01660   nsCOMPtr<nsIFile> parent;
01661   nsCOMPtr<nsIFile> localFile = aTarget.GetFileSpec();
01662 
01663   nsresult rv = localFile->GetParent(getter_AddRefs(parent));
01664   if (NS_SUCCEEDED(rv) && parent)
01665   {
01666     nsInstallFolder* folder = new nsInstallFolder();
01667     if (folder == nsnull)
01668     {
01669         return NS_ERROR_OUT_OF_MEMORY;
01670     }
01671       folder->Init(parent, EmptyString());
01672       *theParentFolder = folder;
01673   }
01674   else
01675       theParentFolder = nsnull;
01676 
01677   return NS_OK;
01678 }
01679 
01680 PRInt32
01681 nsInstall::FileOpDirRemove(nsInstallFolder& aTarget, PRInt32 aFlags, PRInt32* aReturn)
01682 {
01683   nsCOMPtr<nsIFile> localFile = aTarget.GetFileSpec();
01684   if (localFile == nsnull)
01685   {
01686      *aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
01687      return NS_OK;
01688   }
01689 
01690   nsInstallFileOpItem* ifop = new nsInstallFileOpItem(this, NS_FOP_DIR_REMOVE, localFile, aFlags, aReturn);
01691   if (ifop == nsnull)
01692   {
01693       *aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
01694       return NS_OK;
01695   }
01696 
01697   PRInt32 result = SanityCheck();
01698   if (result != nsInstall::SUCCESS)
01699   {
01700       delete ifop;
01701       *aReturn = SaveError( result );
01702       return NS_OK;
01703   }
01704 
01705   if (*aReturn == nsInstall::SUCCESS)
01706   {
01707       *aReturn = ScheduleForInstall( ifop );
01708   }
01709 
01710   SaveError(*aReturn);
01711 
01712   return NS_OK;
01713 }
01714 
01715 PRInt32
01716 nsInstall::FileOpDirRename(nsInstallFolder& aSrc, nsString& aTarget, PRInt32* aReturn)
01717 {
01718   nsCOMPtr<nsIFile> localFile = aSrc.GetFileSpec();
01719   if (localFile == nsnull)
01720   {
01721      *aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
01722      return NS_OK;
01723   }
01724 
01725   nsInstallFileOpItem* ifop = new nsInstallFileOpItem(this, NS_FOP_DIR_RENAME, localFile, aTarget, PR_FALSE, aReturn);
01726   if (ifop == nsnull)
01727   {
01728       *aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
01729       return NS_OK;
01730   }
01731 
01732   PRInt32 result = SanityCheck();
01733   if (result != nsInstall::SUCCESS)
01734   {
01735       delete ifop;
01736       *aReturn = SaveError( result );
01737       return NS_OK;
01738   }
01739 
01740   if (*aReturn == nsInstall::SUCCESS)
01741   {
01742       *aReturn = ScheduleForInstall( ifop );
01743   }
01744 
01745   SaveError(*aReturn);
01746 
01747   return NS_OK;
01748 }
01749 
01750 PRInt32
01751 nsInstall::FileOpFileCopy(nsInstallFolder& aSrc, nsInstallFolder& aTarget, PRInt32* aReturn)
01752 {
01753   nsCOMPtr<nsIFile> localSrcFile = aSrc.GetFileSpec();
01754   if (localSrcFile == nsnull)
01755   {
01756      *aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
01757      return NS_OK;
01758   }
01759 
01760   nsCOMPtr<nsIFile>localTargetFile = aTarget.GetFileSpec();
01761   if (localTargetFile == nsnull)
01762   {
01763      *aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
01764      return NS_OK;
01765   }
01766 
01767   nsInstallFileOpItem* ifop = new nsInstallFileOpItem(this, NS_FOP_FILE_COPY, localSrcFile, localTargetFile, aReturn);
01768   if (ifop == nsnull)
01769   {
01770       *aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
01771       return NS_OK;
01772   }
01773 
01774   PRInt32 result = SanityCheck();
01775   if (result != nsInstall::SUCCESS)
01776   {
01777       delete ifop;
01778       *aReturn = SaveError( result );
01779       return NS_OK;
01780   }
01781 
01782   if (*aReturn == nsInstall::SUCCESS)
01783   {
01784       *aReturn = ScheduleForInstall( ifop );
01785   }
01786 
01787   SaveError(*aReturn);
01788 
01789   return NS_OK;
01790 }
01791 
01792 PRInt32
01793 nsInstall::FileOpFileDelete(nsInstallFolder& aTarget, PRInt32 aFlags, PRInt32* aReturn)
01794 {
01795   nsCOMPtr<nsIFile> localFile = aTarget.GetFileSpec();
01796   if (localFile == nsnull)
01797   {
01798      *aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
01799      return NS_OK;
01800   }
01801 
01802   nsInstallFileOpItem* ifop = new nsInstallFileOpItem(this, NS_FOP_FILE_DELETE, localFile, aFlags, aReturn);
01803   if (ifop == nsnull)
01804   {
01805       *aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
01806       return NS_OK;
01807   }
01808 
01809   PRInt32 result = SanityCheck();
01810   if (result != nsInstall::SUCCESS)
01811   {
01812       delete ifop;
01813       *aReturn = SaveError( result );
01814       return NS_OK;
01815   }
01816 
01817   if (*aReturn == nsInstall::SUCCESS)
01818   {
01819       *aReturn = ScheduleForInstall( ifop );
01820   }
01821 
01822   SaveError(*aReturn);
01823 
01824   return NS_OK;
01825 }
01826 
01827 PRInt32
01828 nsInstall::FileOpFileExecute(nsInstallFolder& aTarget, nsString& aParams, PRBool aBlocking, PRInt32* aReturn)
01829 {
01830   nsCOMPtr<nsIFile> localFile = aTarget.GetFileSpec();
01831   if (localFile == nsnull)
01832   {
01833      *aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
01834      return NS_OK;
01835   }
01836 
01837   nsInstallFileOpItem* ifop = new nsInstallFileOpItem(this, NS_FOP_FILE_EXECUTE, localFile, aParams, aBlocking, aReturn);
01838   if (ifop == nsnull)
01839   {
01840       *aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
01841       return NS_OK;
01842   }
01843 
01844   PRInt32 result = SanityCheck();
01845   if (result != nsInstall::SUCCESS)
01846   {
01847       delete ifop;
01848       *aReturn = SaveError( result );
01849       return NS_OK;
01850   }
01851 
01852   if (*aReturn == nsInstall::SUCCESS)
01853   {
01854       *aReturn = ScheduleForInstall( ifop );
01855   }
01856 
01857   SaveError(*aReturn);
01858 
01859   return NS_OK;
01860 }
01861 
01862 PRInt32
01863 nsInstall::FileOpFileExists(nsInstallFolder& aTarget, PRBool* aReturn)
01864 {
01865   nsCOMPtr<nsIFile> localFile = aTarget.GetFileSpec();
01866 
01867   localFile->Exists(aReturn);
01868   return NS_OK;
01869 }
01870 
01871 #ifdef XP_WIN
01872 #include <winver.h>
01873 #endif
01874 
01875 PRInt32
01876 nsInstall::FileOpFileGetNativeVersion(nsInstallFolder& aTarget, nsString* aReturn)
01877 {
01878   PRInt32           rv = NS_OK;
01879 
01880 #ifdef XP_WIN
01881   PRBool            flagExists;
01882   nsCOMPtr<nsILocalFile> localTarget(do_QueryInterface(aTarget.GetFileSpec()));
01883   UINT              uLen;
01884   UINT              dwLen;
01885   DWORD             dwHandle;
01886   LPVOID            lpData;
01887   LPVOID            lpBuffer;
01888   VS_FIXEDFILEINFO  *lpBuffer2;
01889   DWORD             dwMajor   = 0;
01890   DWORD             dwMinor   = 0;
01891   DWORD             dwRelease = 0;
01892   DWORD             dwBuild   = 0;
01893   nsCAutoString     nativeTargetPath;
01894   char              *nativeVersionString = nsnull;
01895 
01896   if(localTarget == nsnull)
01897     return(rv);
01898 
01899   flagExists = PR_FALSE;
01900   localTarget->Exists(&flagExists);
01901   if(flagExists)
01902   {
01903     localTarget->GetNativePath(nativeTargetPath);
01904     uLen   = 0;
01905     /* GetFileVersionInfoSize() requires a char *, but the api doesn't
01906      * indicate that it will modify it */
01907     dwLen  = GetFileVersionInfoSize((char *)nativeTargetPath.get(), &dwHandle);
01908     lpData = (LPVOID)PR_Malloc(sizeof(long)*dwLen);
01909     if(!lpData)
01910       return(nsInstall::OUT_OF_MEMORY);
01911 
01912     /* GetFileVersionInfo() requires a char *, but the api doesn't
01913      * indicate that it will modify it */
01914     if(GetFileVersionInfo((char *)nativeTargetPath.get(), dwHandle, dwLen, lpData) != 0)
01915     {
01916       if(VerQueryValue(lpData, "\\", &lpBuffer, &uLen) != 0)
01917       {
01918         lpBuffer2 = (VS_FIXEDFILEINFO *)lpBuffer;
01919         dwMajor   = HIWORD(lpBuffer2->dwFileVersionMS);
01920         dwMinor   = LOWORD(lpBuffer2->dwFileVersionMS);
01921         dwRelease = HIWORD(lpBuffer2->dwFileVersionLS);
01922         dwBuild   = LOWORD(lpBuffer2->dwFileVersionLS);
01923       }
01924     }
01925 
01926     nativeVersionString = PR_smprintf("%d.%d.%d.%d", dwMajor, dwMinor, dwRelease, dwBuild);
01927     if(!nativeVersionString)
01928       rv = nsInstall::OUT_OF_MEMORY;
01929     else
01930     {
01931       aReturn->AssignASCII(nativeVersionString);
01932       PR_smprintf_free(nativeVersionString);
01933     }
01934 
01935     PR_FREEIF(lpData);
01936   }
01937 #endif
01938 
01939   return(rv);
01940 }
01941 
01942 PRInt32
01943 nsInstall::FileOpFileGetDiskSpaceAvailable(nsInstallFolder& aTarget, PRInt64* aReturn)
01944 {
01945   nsresult rv;
01946   nsCOMPtr<nsIFile> file = aTarget.GetFileSpec();
01947   nsCOMPtr<nsILocalFile> localFile = do_QueryInterface(file, &rv);
01948 
01949   localFile->GetDiskSpaceAvailable(aReturn);  //nsIFileXXX: need to figure out how to call GetDiskSpaceAvailable
01950   return NS_OK;
01951 }
01952 
01953 //nsIFileXXX: need to get nsIFile equivalent to GetModDate
01954 PRInt32
01955 nsInstall::FileOpFileGetModDate(nsInstallFolder& aTarget, double* aReturn)
01956 {
01957     * aReturn = 0;
01958 
01959     nsCOMPtr<nsIFile> localFile = aTarget.GetFileSpec();
01960 
01961     if (localFile)
01962     {
01963         double newStamp;
01964         PRInt64 lastModDate = LL_ZERO;
01965         localFile->GetLastModifiedTime(&lastModDate);
01966 
01967         LL_L2D(newStamp, lastModDate);
01968 
01969         *aReturn = newStamp;
01970     }
01971 
01972   return NS_OK;
01973 }
01974 
01975 PRInt32
01976 nsInstall::FileOpFileGetSize(nsInstallFolder& aTarget, PRInt64* aReturn)
01977 {
01978   nsCOMPtr<nsIFile> localFile = aTarget.GetFileSpec();
01979 
01980   localFile->GetFileSize(aReturn);
01981   return NS_OK;
01982 }
01983 
01984 PRInt32
01985 nsInstall::FileOpFileIsDirectory(nsInstallFolder& aTarget, PRBool* aReturn)
01986 {
01987   nsCOMPtr<nsIFile> localFile = aTarget.GetFileSpec();
01988 
01989   localFile->IsDirectory(aReturn);
01990   return NS_OK;
01991 }
01992 
01993 PRInt32
01994 nsInstall::FileOpFileIsWritable(nsInstallFolder& aTarget, PRBool* aReturn)
01995 {
01996   nsCOMPtr<nsIFile> localFile = aTarget.GetFileSpec();
01997 
01998   localFile->IsWritable(aReturn);
01999   return NS_OK;
02000 }
02001 
02002 PRInt32
02003 nsInstall::FileOpFileIsFile(nsInstallFolder& aTarget, PRBool* aReturn)
02004 {
02005   nsCOMPtr<nsIFile> localFile = aTarget.GetFileSpec();
02006 
02007   localFile->IsFile(aReturn);
02008   return NS_OK;
02009 }
02010 
02011 //nsIFileXXX: need to get the ModDateChanged equivalent for nsIFile
02012 PRInt32
02013 nsInstall::FileOpFileModDateChanged(nsInstallFolder& aTarget, double aOldStamp, PRBool* aReturn)
02014 {
02015     *aReturn = PR_TRUE;
02016 
02017     nsCOMPtr<nsIFile> localFile = aTarget.GetFileSpec();
02018     if (localFile)
02019     {
02020         double newStamp;
02021         PRInt64 lastModDate = LL_ZERO;
02022         localFile->GetLastModifiedTime(&lastModDate);
02023 
02024         LL_L2D(newStamp, lastModDate);
02025 
02026         *aReturn = !(newStamp == aOldStamp);
02027     }
02028     return NS_OK;
02029 }
02030 
02031 PRInt32
02032 nsInstall::FileOpFileMove(nsInstallFolder& aSrc, nsInstallFolder& aTarget, PRInt32* aReturn)
02033 {
02034   nsCOMPtr<nsIFile> localSrcFile = aSrc.GetFileSpec();
02035   if (localSrcFile == nsnull)
02036   {
02037      *aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
02038      return NS_OK;
02039   }
02040   nsCOMPtr<nsIFile> localTargetFile = aTarget.GetFileSpec();
02041   if (localTargetFile == nsnull)
02042   {
02043      *aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
02044      return NS_OK;
02045   }
02046 
02047   nsInstallFileOpItem* ifop = new nsInstallFileOpItem(this, NS_FOP_FILE_MOVE, localSrcFile, localTargetFile, aReturn);
02048   if (ifop == nsnull)
02049   {
02050       *aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
02051       return NS_OK;
02052   }
02053 
02054   PRInt32 result = SanityCheck();
02055   if (result != nsInstall::SUCCESS)
02056   {
02057       delete ifop;
02058       *aReturn = SaveError( result );
02059       return NS_OK;
02060   }
02061 
02062   if (*aReturn == nsInstall::SUCCESS)
02063   {
02064       *aReturn = ScheduleForInstall( ifop );
02065   }
02066 
02067   SaveError(*aReturn);
02068 
02069   return NS_OK;
02070 }
02071 
02072 PRInt32
02073 nsInstall::FileOpFileRename(nsInstallFolder& aSrc, nsString& aTarget, PRInt32* aReturn)
02074 {
02075   nsCOMPtr<nsIFile> localFile = aSrc.GetFileSpec();
02076   if (localFile == nsnull)
02077   {
02078      *aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
02079      return NS_OK;
02080   }
02081 
02082   nsInstallFileOpItem* ifop = new nsInstallFileOpItem(this, NS_FOP_FILE_RENAME, localFile, aTarget, PR_FALSE, aReturn);
02083   if (ifop == nsnull)
02084   {
02085       *aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
02086       return NS_OK;
02087   }
02088 
02089   PRInt32 result = SanityCheck();
02090   if (result != nsInstall::SUCCESS)
02091   {
02092       delete ifop;
02093       *aReturn = SaveError( result );
02094       return NS_OK;
02095   }
02096 
02097   if (*aReturn == nsInstall::SUCCESS)
02098   {
02099       *aReturn = ScheduleForInstall( ifop );
02100   }
02101 
02102   SaveError(*aReturn);
02103 
02104   return NS_OK;
02105 }
02106 
02107 #ifdef _WINDOWS
02108 #include <winbase.h>
02109 #endif
02110 
02111 
02112 PRInt32
02113 nsInstall::FileOpFileWindowsGetShortName(nsInstallFolder& aTarget, nsString& aShortPathName)
02114 {
02115 #ifdef _WINDOWS
02116 
02117   PRInt32             err;
02118   PRBool              flagExists;
02119   nsString            tmpNsString;
02120   nsCAutoString       nativeTargetPath;
02121   nsAutoString        unicodePath;
02122   char                nativeShortPathName[MAX_PATH];
02123   nsCOMPtr<nsIFile>   localTarget(aTarget.GetFileSpec());
02124 
02125   if(localTarget == nsnull)
02126     return NS_OK;
02127 
02128   localTarget->Exists(&flagExists);
02129   if(flagExists)
02130   {
02131     memset(nativeShortPathName, 0, MAX_PATH);
02132     localTarget->GetNativePath(nativeTargetPath);
02133 
02134     err = GetShortPathName(nativeTargetPath.get(), nativeShortPathName, MAX_PATH);
02135     if((err > 0) && (*nativeShortPathName == '\0'))
02136     {
02137       // NativeShortPathName buffer not big enough.
02138       // Reallocate and try again.
02139       // err will have the required size.
02140       char *nativeShortPathNameTmp = new char[err + 1];
02141       if(nativeShortPathNameTmp == nsnull)
02142         return NS_OK;
02143 
02144       err = GetShortPathName(nativeTargetPath.get(), nativeShortPathNameTmp, err + 1);
02145       // It is safe to assume that the second time around the buffer is big
02146       // enough and not to worry about it unless it's a different problem.  If
02147       // it failed the first time because of buffer size being too small, err
02148       // will be the buffer size required.  If it's any other error, err will
02149       // be 0 and GetLastError() will have the actual error.
02150       if(err != 0)
02151       {
02152         // if err is 0, it's not a buffer size problem.  It's something else unexpected.
02153         NS_CopyNativeToUnicode(nsDependentCString(nativeShortPathNameTmp), unicodePath);
02154       }
02155 
02156       if(nativeShortPathNameTmp)
02157         delete [] nativeShortPathNameTmp;
02158     }
02159     else if(err != 0)
02160     {
02161       // if err is 0, it's not a buffer size problem.  It's something else unexpected.
02162       NS_CopyNativeToUnicode(nsDependentCString(nativeShortPathName), unicodePath);
02163     }
02164   }
02165 
02166   if (!unicodePath.IsEmpty())
02167     aShortPathName = unicodePath;
02168 
02169 #endif
02170 
02171   return NS_OK;
02172 }
02173 
02174 PRInt32
02175 nsInstall::FileOpFileWindowsShortcut(nsIFile* aTarget, nsIFile* aShortcutPath, nsString& aDescription, nsIFile* aWorkingPath, nsString& aParams, nsIFile* aIcon, PRInt32 aIconId, PRInt32* aReturn)
02176 {
02177 
02178   nsInstallFileOpItem* ifop = new nsInstallFileOpItem(this, NS_FOP_WIN_SHORTCUT, aTarget, aShortcutPath, aDescription, aWorkingPath, aParams, aIcon, aIconId, aReturn);
02179   if (ifop == nsnull)
02180   {
02181       *aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
02182       return NS_OK;
02183   }
02184 
02185   PRInt32 result = SanityCheck();
02186   if (result != nsInstall::SUCCESS)
02187   {
02188       delete ifop;
02189       *aReturn = SaveError( result );
02190       return NS_OK;
02191   }
02192 
02193   if (*aReturn == nsInstall::SUCCESS)
02194   {
02195       *aReturn = ScheduleForInstall( ifop );
02196   }
02197 
02198   SaveError(*aReturn);
02199 
02200   return NS_OK;
02201 }
02202 
02203 PRInt32
02204 nsInstall::FileOpFileMacAlias(nsIFile *aSourceFile, nsIFile *aAliasFile, PRInt32* aReturn)
02205 {
02206 
02207   *aReturn = nsInstall::SUCCESS;
02208 
02209 #if defined(XP_MAC) || defined(XP_MACOSX)
02210 
02211   nsInstallFileOpItem* ifop = new nsInstallFileOpItem(this, NS_FOP_MAC_ALIAS, aSourceFile, aAliasFile, aReturn);
02212   if (!ifop)
02213   {
02214       *aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
02215       return NS_OK;
02216   }
02217 
02218   PRInt32 result = SanityCheck();
02219   if (result != nsInstall::SUCCESS)
02220   {
02221       *aReturn = SaveError( result );
02222       return NS_OK;
02223   }
02224 
02225   if (ifop == nsnull)
02226   {
02227       *aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
02228       return NS_OK;
02229   }
02230 
02231   if (*aReturn == nsInstall::SUCCESS)
02232   {
02233       *aReturn = ScheduleForInstall( ifop );
02234   }
02235 
02236   SaveError(*aReturn);
02237 
02238 #endif /* XP_MAC || XP_MACOSX */
02239 
02240   return NS_OK;
02241 }
02242 
02243 PRInt32
02244 nsInstall::FileOpFileUnixLink(nsInstallFolder& aTarget, PRInt32 aFlags, PRInt32* aReturn)
02245 {
02246   return NS_OK;
02247 }
02248 
02249 PRInt32
02250 nsInstall::FileOpWinRegisterServer(nsInstallFolder& aTarget, PRInt32* aReturn)
02251 {
02252   nsCOMPtr<nsIFile> localFile = aTarget.GetFileSpec();
02253   if (localFile == nsnull)
02254   {
02255      *aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
02256      return NS_OK;
02257   }
02258 
02259   nsInstallFileOpItem* ifop = new nsInstallFileOpItem(this, NS_FOP_WIN_REGISTER_SERVER, localFile, aReturn);
02260   if (ifop == nsnull)
02261   {
02262       *aReturn = SaveError(nsInstall::OUT_OF_MEMORY);
02263       return NS_OK;
02264   }
02265 
02266   PRInt32 result = SanityCheck();
02267   if (result != nsInstall::SUCCESS)
02268   {
02269       delete ifop;
02270       *aReturn = SaveError( result );
02271       return NS_OK;
02272   }
02273 
02274   if (*aReturn == nsInstall::SUCCESS)
02275   {
02276       *aReturn = ScheduleForInstall( ifop );
02277   }
02278 
02279   SaveError(*aReturn);
02280 
02281   return NS_OK;
02282 }
02283 
02284 void
02285 nsInstall::LogComment(const nsAString& aComment)
02286 {
02287   if(mListener)
02288     mListener->OnLogComment(PromiseFlatString(aComment).get());
02289 }
02290 
02292 // Private Methods
02294 
02301 PRInt32
02302 nsInstall::ScheduleForInstall(nsInstallObject* ob)
02303 {
02304     PRInt32 error = nsInstall::SUCCESS;
02305 
02306     char *objString = ob->toString();
02307 
02308     // flash current item
02309 
02310     if (mListener)
02311         mListener->OnItemScheduled(NS_ConvertASCIItoUCS2(objString).get());
02312 
02313 
02314     // do any unpacking or other set-up
02315     error = ob->Prepare();
02316 
02317     if (error == nsInstall::SUCCESS)
02318     {
02319         // Add to installation list
02320         mInstalledFiles->AppendElement( ob );
02321 
02322         // turn on flags for creating the uninstall node and
02323         // the package node for each InstallObject
02324 
02325         if (ob->CanUninstall())
02326             mUninstallPackage = PR_TRUE;
02327 
02328         if (ob->RegisterPackageNode())
02329             mRegisterPackage = PR_TRUE;
02330     }
02331     else if ( mListener )
02332     {
02333         // error in preparation step -- log it
02334         char* errRsrc = GetResourcedString(NS_LITERAL_STRING("ERROR"));
02335         if (errRsrc)
02336         {
02337             char* errprefix = PR_smprintf("%s (%d): ", errRsrc, error);
02338             nsString errstr; errstr.AssignWithConversion(errprefix);
02339             errstr.AppendWithConversion(objString);
02340 
02341             mListener->OnLogComment( errstr.get() );
02342 
02343             PR_smprintf_free(errprefix);
02344             nsCRT::free(errRsrc);
02345         }
02346     }
02347 
02348     if (error != SUCCESS)
02349         SaveError(error);
02350 
02351     if (objString)
02352         delete [] objString;
02353 
02354     return error;
02355 }
02356 
02357 
02364 PRInt32
02365 nsInstall::SanityCheck(void)
02366 {
02367     if ( mInstalledFiles == nsnull || mStartInstallCompleted == PR_FALSE )
02368     {
02369         return INSTALL_NOT_STARTED;
02370     }
02371 
02372     if (mUserCancelled)
02373     {
02374         InternalAbort(USER_CANCELLED);
02375         return USER_CANCELLED;
02376     }
02377 
02378     return 0;
02379 }
02380 
02388 PRInt32
02389 nsInstall::GetQualifiedPackageName( const nsString& name, nsString& qualifiedName )
02390 {
02391     nsString startOfName;
02392     name.Left(startOfName, 7);
02393 
02394     if ( startOfName.EqualsLiteral("=USER=/") )
02395     {
02396         CurrentUserNode(qualifiedName);
02397         qualifiedName += name;
02398     }
02399     else
02400     {
02401         qualifiedName = name;
02402     }
02403 
02404     if (BadRegName(qualifiedName))
02405     {
02406         return BAD_PACKAGE_NAME;
02407     }
02408 
02409 
02410     /* Check to see if the PackageName ends in a '/'.  If it does nuke it. */
02411 
02412     if (qualifiedName.Last() == '/')
02413     {
02414         PRInt32 index = qualifiedName.Length();
02415         qualifiedName.Truncate(--index);
02416     }
02417 
02418     return SUCCESS;
02419 }
02420 
02421 
02428 PRInt32
02429 nsInstall::GetQualifiedRegName(const nsString& name, nsString& qualifiedRegName )
02430 {
02431     nsString startOfName;
02432     name.Left(startOfName, 7);
02433 
02434     if ( startOfName.EqualsLiteral("=COMM=/") || startOfName.EqualsLiteral("=USER=/"))
02435     {
02436         qualifiedRegName = startOfName;
02437     }
02438     else if (name.CharAt(0) != '/' &&
02439              !mRegistryPackageName.IsEmpty())
02440     {
02441         qualifiedRegName = mRegistryPackageName
02442                          + NS_LITERAL_STRING("/")
02443                          + name;
02444     }
02445     else
02446     {
02447         qualifiedRegName = name;
02448     }
02449 
02450     if (BadRegName(qualifiedRegName))
02451     {
02452         return BAD_PACKAGE_NAME;
02453     }
02454 
02455     return SUCCESS;
02456 }
02457 
02458 
02459 void
02460 nsInstall::CurrentUserNode(nsString& userRegNode)
02461 {
02462     nsXPIDLCString profname;
02463     nsCOMPtr<nsIPrefBranch> prefBranch = do_GetService(NS_PREFSERVICE_CONTRACTID);
02464 
02465     if ( prefBranch )
02466     {
02467         prefBranch->GetCharPref("profile.name", getter_Copies(profname));
02468     }
02469 
02470     userRegNode.AssignLiteral("/Netscape/Users/");
02471     if ( !profname.IsEmpty() )
02472     {
02473         userRegNode.AppendWithConversion(profname);
02474         userRegNode.AppendLiteral("/");
02475     }
02476 }
02477 
02478 // catch obvious registry name errors proactively
02479 // rather than returning some cryptic libreg error
02480 PRBool
02481 nsInstall::BadRegName(const nsString& regName)
02482 {
02483     if ( regName.IsEmpty() )
02484         return PR_TRUE;
02485 
02486     if ((regName.First() == ' ' ) || (regName.Last() == ' ' ))
02487         return PR_TRUE;
02488 
02489     if ( regName.Find("//") != -1 )
02490         return PR_TRUE;
02491 
02492     if ( regName.Find(" /") != -1 )
02493         return PR_TRUE;
02494 
02495     if ( regName.Find("/ ") != -1  )
02496         return PR_TRUE;
02497 
02498     return PR_FALSE;
02499 }
02500 
02501 PRInt32
02502 nsInstall::SaveError(PRInt32 errcode)
02503 {
02504   if ( errcode != nsInstall::SUCCESS )
02505     mLastError = errcode;
02506 
02507   return errcode;
02508 }
02509 
02510 
02511 /*
02512  * CleanUp
02513  * call it when done with the install
02514  *
02515  */
02516 void
02517 nsInstall::CleanUp(void)
02518 {
02519     nsInstallObject* ie;
02520 
02521     if ( mInstalledFiles != nsnull )
02522     {
02523         for (PRInt32 i=0; i < mInstalledFiles->Count(); i++)
02524         {
02525             ie = (nsInstallObject*)mInstalledFiles->ElementAt(i);
02526             if (ie)
02527                 delete ie;
02528         }
02529 
02530         mInstalledFiles->Clear();
02531         delete (mInstalledFiles);
02532         mInstalledFiles = nsnull;
02533     }
02534 
02535     if (mPatchList != nsnull)
02536     {
02537         mPatchList->Reset();
02538         delete mPatchList;
02539         mPatchList = nsnull;
02540     }
02541 
02542     if (mPackageFolder != nsnull)
02543     {
02544       delete (mPackageFolder);
02545       mPackageFolder = nsnull;
02546     }
02547 
02548     mRegistryPackageName.SetLength(0); // used to see if StartInstall() has been called
02549     mStartInstallCompleted = PR_FALSE;
02550 }
02551 
02552 
02553 void
02554 nsInstall::SetJarFileLocation(nsIFile* aFile)
02555 {
02556     mJarFileLocation = aFile;
02557 }
02558 
02559 void
02560 nsInstall::GetInstallArguments(nsString& args)
02561 {
02562     args = mInstallArguments;
02563 }
02564 
02565 void
02566 nsInstall::SetInstallArguments(const nsString& args)
02567 {
02568     mInstallArguments = args;
02569 }
02570 
02571 
02572 void nsInstall::GetInstallURL(nsString& url)        { url = mInstallURL; }
02573 void nsInstall::SetInstallURL(const nsString& url)  { mInstallURL = url; }
02574 
02575 //-----------------------------------------------------------------------------
02576 // GetTranslatedString :
02577 // This is a utility function that translates "Alert" or
02578 // "Confirm" to pass as the title to the PromptService Alert and Confirm
02579 // functions as the title.  If you pass nsnull as the title, you get garbage
02580 // instead of a blank title.
02581 //-----------------------------------------------------------------------------
02582 PRUnichar *GetTranslatedString(const PRUnichar* aString)
02583 {
02584     nsCOMPtr<nsIStringBundleService> stringService = do_GetService(kStringBundleServiceCID);
02585     nsCOMPtr<nsIStringBundle> stringBundle;
02586     PRUnichar* translatedString;
02587 
02588     nsresult rv = stringService->CreateBundle(kInstallLocaleProperties, getter_AddRefs(stringBundle));
02589     if (NS_FAILED(rv)) return nsnull;
02590 
02591     rv = stringBundle->GetStringFromName(aString, &translatedString);
02592     if (NS_FAILED(rv)) return nsnull;
02593 
02594     return translatedString;
02595 }
02596 
02597 PRInt32
02598 nsInstall::Alert(nsString& string)
02599 {
02600     nsPIXPIProxy *ui = GetUIThreadProxy();
02601     if (!ui)
02602         return UNEXPECTED_ERROR;
02603 
02604     nsAutoString title;
02605     title.AssignLiteral("Alert");
02606     if (!mUIName.IsEmpty())
02607     {
02608         title = mUIName;
02609     }
02610     else
02611     {
02612         PRUnichar *t = GetTranslatedString(title.get());
02613         if (t)
02614             title.Adopt(t);
02615     }
02616     return ui->Alert( title.get(), string.get());
02617 }
02618 
02619 PRInt32
02620 nsInstall::ConfirmEx(nsString& aDialogTitle, nsString& aText, PRUint32 aButtonFlags, nsString& aButton0Title, nsString& aButton1Title, nsString& aButton2Title, nsString& aCheckMsg, PRBool* aCheckState, PRInt32* aReturn)
02621 {
02622     *aReturn = -1; /* default value */
02623 
02624     nsPIXPIProxy *ui = GetUIThreadProxy();
02625     if (!ui)
02626         return UNEXPECTED_ERROR;
02627 
02628     nsAutoString title;
02629     title.AssignLiteral("Confirm");
02630     if (!aDialogTitle.IsEmpty())
02631     {
02632         title = aDialogTitle;
02633     }
02634     else if (!mUIName.IsEmpty())
02635     {
02636         title = mUIName;
02637     }
02638     else
02639     {
02640         PRUnichar *t = GetTranslatedString(title.get());
02641         if (t)
02642             title.Adopt(t);
02643     }
02644     return ui->ConfirmEx( title.get(),
02645                           aText.get(),
02646                           aButtonFlags,
02647                           aButton0Title.get(),
02648                           aButton1Title.get(),
02649                           aButton2Title.get(),
02650                           aCheckMsg.get(),
02651                           aCheckState,
02652                           aReturn);
02653 }
02654 
02655 
02656 // aJarFile         - This is the filepath within the jar file.
02657 // aSuggestedName   - This is the name that we should try to extract to.  If we can, we will create a new temporary file.
02658 // aRealName        - This is the name that we did extract to.  This will be allocated by use and should be disposed by the caller.
02659 
02660 PRInt32
02661 nsInstall::ExtractFileFromJar(const nsString& aJarfile, nsIFile* aSuggestedName, nsIFile** aRealName)
02662 {
02663     PRInt32 extpos = 0;
02664     nsCOMPtr<nsIFile> extractHereSpec;
02665     nsCOMPtr<nsILocalFile> tempFile;
02666     nsresult rv;
02667 
02668     if (aSuggestedName == nsnull)
02669     {
02670         nsCOMPtr<nsIProperties> directoryService =
02671                  do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
02672 
02673         directoryService->Get(NS_OS_TEMP_DIR, NS_GET_IID(nsIFile), getter_AddRefs(tempFile));
02674 
02675         nsAutoString tempFileName(NS_LITERAL_STRING("xpinstall"));
02676 
02677         // Get the extension of the file in the JAR
02678         extpos = aJarfile.RFindChar('.');
02679         if (extpos != -1)
02680         {
02681             // We found the extension; add it to the tempFileName string
02682             nsString extension;
02683             aJarfile.Right(extension, (aJarfile.Length() - extpos) );
02684             tempFileName += extension;
02685         }
02686         tempFile->Append(tempFileName);
02687         tempFile->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0664);
02688         tempFile->Clone(getter_AddRefs(extractHereSpec));
02689 
02690         if (extractHereSpec == nsnull)
02691             return nsInstall::OUT_OF_MEMORY;
02692     }
02693     else
02694     {
02695         nsCOMPtr<nsIFile> temp;
02696         aSuggestedName->Clone(getter_AddRefs(temp));
02697 
02698         PRBool exists;
02699         temp->Exists(&exists);
02700         if (exists)
02701         {
02702             PRBool writable;
02703             temp->IsWritable(&writable);
02704             if (!writable) // Can't extract. Target is readonly.
02705                 return nsInstall::READ_ONLY;
02706 
02707             tempFile = do_QueryInterface(temp, &rv); //convert to an nsILocalFile
02708             if (tempFile == nsnull)
02709                 return nsInstall::OUT_OF_MEMORY;
02710 
02711             //get the leafname so we can convert its extension to .new
02712             nsAutoString newLeafName;
02713             tempFile->GetLeafName(newLeafName);
02714 
02715             PRInt32 extpos = newLeafName.RFindChar('.');
02716             if (extpos != -1)
02717             {
02718                 // We found the extension;
02719                 newLeafName.Truncate(extpos + 1); //strip off the old extension
02720             }
02721             newLeafName.AppendLiteral("new");
02722 
02723             //Now reset the leafname
02724             tempFile->SetLeafName(newLeafName);
02725             tempFile->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0644);
02726             extractHereSpec = tempFile;
02727         }
02728         extractHereSpec = temp;
02729     }
02730 
02731     rv = mJarFileData->Extract(NS_LossyConvertUCS2toASCII(aJarfile).get(),
02732                                extractHereSpec);
02733     if (NS_FAILED(rv))
02734     {
02735         switch (rv) {
02736           case NS_ERROR_FILE_ACCESS_DENIED:         return ACCESS_DENIED;
02737           case NS_ERROR_FILE_DISK_FULL:             return INSUFFICIENT_DISK_SPACE;
02738           case NS_ERROR_FILE_TARGET_DOES_NOT_EXIST: return DOES_NOT_EXIST;
02739           default:                                  return EXTRACTION_FAILED;
02740         }
02741     }
02742 
02743 #if defined(XP_MAC) || defined(XP_MACOSX)
02744     FSRef finalRef, extractedRef;
02745 
02746     nsCOMPtr<nsILocalFileMac> tempExtractHereSpec;
02747     tempExtractHereSpec = do_QueryInterface(extractHereSpec, &rv);
02748     tempExtractHereSpec->GetFSRef(&extractedRef);
02749 
02750     if ( nsAppleSingleDecoder::IsAppleSingleFile(&extractedRef) )
02751     {
02752         nsAppleSingleDecoder *asd = 
02753           new nsAppleSingleDecoder(&extractedRef, &finalRef);
02754         OSErr decodeErr = fnfErr;
02755 
02756         if (asd)
02757             decodeErr = asd->Decode();
02758 
02759         if (decodeErr != noErr)
02760         {
02761             if (asd)
02762                 delete asd;
02763             return EXTRACTION_FAILED;
02764         }
02765 
02766         if (noErr != FSCompareFSRefs(&extractedRef, &finalRef))
02767         {
02768             // delete the unique extracted file that got renamed in AS decoding
02769             FSDeleteObject(&extractedRef);
02770 
02771             // "real name" in AppleSingle entry may cause file rename
02772             tempExtractHereSpec->InitWithFSRef(&finalRef);
02773             extractHereSpec = do_QueryInterface(tempExtractHereSpec, &rv);
02774         }
02775     }
02776 #endif /* XP_MAC || XP_MACOSX */
02777 
02778     extractHereSpec->Clone(aRealName);
02779     
02780     return nsInstall::SUCCESS;
02781 }
02782 
02792 char*
02793 nsInstall::GetResourcedString(const nsAString& aResName)
02794 {
02795     if (mStringBundle)
02796     {
02797         nsXPIDLString ucRscdStr;
02798         nsresult rv = mStringBundle->GetStringFromName(PromiseFlatString(aResName).get(),
02799                                                      getter_Copies(ucRscdStr));
02800         if (NS_SUCCEEDED(rv))
02801             return ToNewCString(ucRscdStr);
02802     }
02803 
02804     /*
02805     ** We don't have a string bundle, the necessary libs, or something went wrong
02806     ** so we failover to hardcoded english strings so we log something rather
02807     ** than nothing due to failure above: always the case for the Install Wizards.
02808     */
02809     return nsCRT::strdup(nsInstallResources::GetDefaultVal(
02810                     NS_LossyConvertUCS2toASCII(aResName).get()));
02811 }
02812 
02813 
02814 PRInt32
02815 nsInstall::ExtractDirEntries(const nsString& directory, nsVoidArray *paths)
02816 {
02817     char                *buf;
02818     nsISimpleEnumerator *jarEnum = nsnull;
02819     nsIZipEntry         *currZipEntry = nsnull;
02820 
02821     if ( paths )
02822     {
02823         nsString pattern(directory + NS_LITERAL_STRING("/*"));
02824         PRInt32 prefix_length = directory.Length()+1; // account for slash
02825 
02826         nsresult rv = mJarFileData->FindEntries(
02827                           NS_LossyConvertUCS2toASCII(pattern).get(),
02828                           &jarEnum );
02829         if (NS_FAILED(rv) || !jarEnum)
02830             goto handle_err;
02831 
02832         PRBool bMore;
02833         rv = jarEnum->HasMoreElements(&bMore);
02834         while (bMore && NS_SUCCEEDED(rv))
02835         {
02836             rv = jarEnum->GetNext( (nsISupports**) &currZipEntry );
02837             if (currZipEntry)
02838             {
02839                 // expensive 'buf' callee malloc per iteration!
02840                 rv = currZipEntry->GetName(&buf);
02841                 if (NS_FAILED(rv))
02842                     goto handle_err;
02843                 if (buf)
02844                 {
02845                     PRInt32 namelen = PL_strlen(buf);
02846                     NS_ASSERTION( prefix_length <= namelen, "Match must be longer than pattern!" );
02847 
02848                     if ( buf[namelen-1] != '/' )
02849                     {
02850                         // XXX manipulation should be in caller
02851                         nsString* tempString = new nsString; tempString->AssignWithConversion(buf+prefix_length);
02852                         paths->AppendElement(tempString);
02853                     }
02854 
02855                     PR_FREEIF( buf );
02856                 }
02857                 NS_IF_RELEASE(currZipEntry);
02858             }
02859             rv = jarEnum->HasMoreElements(&bMore);
02860         }
02861     }
02862 
02863     NS_IF_RELEASE(jarEnum);
02864     return SUCCESS;
02865 
02866 handle_err:
02867     NS_IF_RELEASE(jarEnum);
02868     NS_IF_RELEASE(currZipEntry);
02869     return EXTRACTION_FAILED;
02870 }
02871 
02872 void
02873 nsInstall::DeleteVector(nsVoidArray* vector)
02874 {
02875     if (vector != nsnull)
02876     {
02877         for (PRInt32 i=0; i < vector->Count(); i++)
02878         {
02879             nsString* element = (nsString*)vector->ElementAt(i);
02880             if (element != nsnull)
02881                 delete element;
02882         }
02883 
02884         vector->Clear();
02885         delete (vector);
02886         vector = nsnull;
02887     }
02888 }