Example #1
0
 def connection_didReceiveResponse_(self, connection, response):
     LogDebug("%@ status code %d", self.package.name(),
              response.statusCode())
     if response.statusCode() >= 400:
         connection.cancel()
         self.fileHandle.closeFile()
         error = "%s failed with HTTP %d" % (self.package.name(),
                                             response.statusCode())
         self.delegate.downloadFailed_withError_(self.package, error)
         self.delegate.downloadAllDone()
Example #2
0
 def setSource_(self, path):
     LogDebug(u"setSource:%@", path)
     
     self._source = None
     self.newSourcePath = path
     if self.installerMountPoint:
         self.delegate.ejectingSource()
         self.dmgHelper.detachAll_(self.continueSetSource_)
     else:
         self.continueSetSource_({})
Example #3
0
 def detachAll_(self, selector):
     LogDebug("detachAll:%@", selector)
     self.detachAllFailed = dict()
     self.detachAllRemaining = len(self.dmgs)
     self.detachAllSelector = selector
     if self.dmgs:
         for dmgPath in self.dmgs.iterkeys():
             self.performSelectorInBackground_withObject_(self.hdiutilDetach_, [dmgPath, self, self.handleDetachAllResult_])
     else:
         if self.delegate.respondsToSelector_(selector):
             self.delegate.performSelector_withObject_(selector, {})
Example #4
0
 def calculateInstalledPkgSize_(cls, pkgPath):
     if os.path.isdir(pkgPath):
         size = cls.getBundlePkgInfo_(pkgPath)
     else:
         size = cls.getFlatPkgInfo_(pkgPath)
     if size is None:
         # If all else fails, estimate package size requirements.
         LogWarning("Estimating package size for '%@'", pkgPath)
         size = cls.getPackageSize_(pkgPath) * 2
     LogDebug("%@ needs %@", pkgPath, cls.formatByteSize_(size))
     return size
Example #5
0
 def setFilesystem_(self, filesystem):
     LogDebug("Setting filesystem for workflow to '%@'", filesystem)
     if filesystem == "hfs":
         if IEDUtil.hostMajorVersion() > 13:
             LogWarning("Ignoring filesystem setting, only apfs is supported")
     elif filesystem == "apfs":
         if IEDUtil.hostMajorVersion() < 13:
             LogWarning("Ignoring filesystem setting, only hfs is supported")
     else:
         LogWarning("Unrecognized filesystem setting '%@'", filesystem)
     self._filesystem = filesystem
Example #6
0
 def handleSourceMountResult_(self, result):
     LogDebug("handleSourceMountResult:%@", result)
     
     if not result["success"]:
         self.delegate.sourceFailed_text_("Failed to mount %s" % result["dmg-path"],
                                          result["error-message"])
         return
     
     mountPoint = result["mount-point"]
     
     # Update the icon if we find an installer app.
     for path in glob.glob(os.path.join(mountPoint, "Install*.app")):
         self.delegate.foundSourceForIcon_(path)
     
     # Don't set this again since 10.9 mounts BaseSystem.dmg after InstallESD.dmg.
     if self.installerMountPoint is None:
         # Check if the source is an InstallESD, BaseSystem or system image.
         if os.path.exists(os.path.join(mountPoint, "Packages", "OSInstall.mpkg")):
             self.installerMountPoint = mountPoint
             self.sourceType = IEDWorkflow.INSTALL_ESD
             LogDebug("sourceType = INSTALL_ESD")
         elif glob.glob(os.path.join(mountPoint, "Install*.app")):
             self.sourceType = IEDWorkflow.INSTALL_INFO
             LogDebug("sourceType = INSTALL_INFO")
         else:
             self.installerMountPoint = mountPoint
             self.sourceType = IEDWorkflow.SYSTEM_IMAGE
             LogDebug("sourceType = SYSTEM_IMAGE")
     
     baseSystemPath = os.path.join(mountPoint, "BaseSystem.dmg")
     
     # If we find a SystemVersion.plist we proceed to the next step.
     if os.path.exists(os.path.join(mountPoint, IEDUtil.VERSIONPLIST_PATH)):
         self.checkVersion_(mountPoint)
     # Otherwise check if there's a BaseSystem.dmg that we need to examine.
     elif os.path.exists(baseSystemPath):
         self.baseSystemMountedFromPath = baseSystemPath
         self.dmgHelper.attach_selector_(baseSystemPath, self.handleSourceMountResult_)
     else:
         self.delegate.sourceFailed_text_("Invalid source",
                                          "Couldn't find system version.")
Example #7
0
 def nextTask(self):
     LogDebug("nextTask, currentTask == %@", self.currentTask)
     
     if self.currentTask:
         if self.currentTask["phases"]:
             for phase in self.currentTask["phases"]:
                 if not phase.get("optional", False):
                     details = NSString.stringWithFormat_("Phases remaining: %@", self.currentTask["phases"])
                     self.fail_details_("Task finished prematurely", details)
                     return
     if self.tasks:
         self.currentTask = self.tasks.pop(0)
         LogNotice("Starting task %@ with %d phases", self.currentTask["title"], len(self.currentTask["phases"]))
         self.nextPhase()
         LogDebug("Calling %@()", self.currentTask["title"])
         self.currentTask["method"]()
         LogDebug("Returned from %@()", self.currentTask["title"])
     else:
         LogNotice("Build finished successfully, image saved to %@", self.outputPath())
         self.delegate.buildSucceeded()
         self.stop()
Example #8
0
 def loadImageTemplate_(self, mountPoint):
     LogDebug("checkTemplate:%@", mountPoint)
     try:
         path = glob.glob(os.path.join(mountPoint, "private/var/log/*.adtmpl"))[0]
     except IndexError:
         return None
     template = IEDTemplate.alloc().init()
     error = template.loadTemplateAndReturnError_(path)
     if error:
         LogWarning("Error reading %@ from image: %@", os.path.basename(path), error)
         return None
     return template
Example #9
0
 def countDownloads(self):
     LogDebug(u"countDownloads")
     self.downloads = list()
     self.downloadTotalSize = 0
     for package in self.updates:
         if self.cache.isCached_(package.sha1()):
             package.setImage_(self.cachedImage)
         else:
             package.setImage_(self.uncachedImage)
             self.downloadTotalSize += package.size()
             self.downloads.append(package)
     self.updateTable.reloadData()
     self.showRemainingDownloads()
Example #10
0
 def taskPrepare(self):
     LogDebug("taskPrepare")
     
     # Attach any disk images containing update packages.
     self.attachedPackageDMGs = dict()
     self.numberOfDMGsToAttach = 0
     for package in self.additionalPackages:
         if package.path().endswith(".dmg"):
             self.numberOfDMGsToAttach += 1
             LogInfo("Attaching %@", package.path())
             self.dmgHelper.attach_selector_(package.path(), self.attachPackageDMG_)
     if self.numberOfDMGsToAttach == 0:
         self.continuePrepare()
Example #11
0
    def attachPackageDMG_(self, result):
        LogDebug("attachPackageDMG:%@", result)

        if not result["success"]:
            self.fail_details_("Failed to attach %s" % result["dmg-path"],
                               result["error-message"])
            return
        # Save result in a dictionary of dmg paths and their mount points.
        self.attachedPackageDMGs[result["dmg-path"]] = result["mount-point"]
        # If this was the last image we were waiting for, continue preparing
        # for install.
        if len(self.attachedPackageDMGs) == self.numberOfDMGsToAttach:
            self.continuePrepare()
Example #12
0
 def getInstalledPkgSize_(cls, pkgPath):
     # For apps just return the size on disk.
     name, ext = os.path.splitext(pkgPath)
     if ext == u".app":
         return cls.getPackageSize_(pkgPath)
     # For packages try to get the size requirements with installer.
     pkgFileName = os.path.os.path.basename(pkgPath)
     tempdir = tempfile.mkdtemp()
     try:
         symlinkPath = os.path.join(tempdir, pkgFileName)
         os.symlink(pkgPath, symlinkPath)
         p = subprocess.Popen([u"/usr/sbin/installer",
                               u"-pkginfo",
                               u"-verbose",
                               u"-plist",
                               u"-pkg",
                               symlinkPath],
                              stdout=subprocess.PIPE,
                              stderr=subprocess.PIPE)
         out, err = p.communicate()
     finally:
         try:
             shutil.rmtree(tempdir)
         except BaseException as e:
             LogWarning(u"Unable to remove tempdir: %@", unicode(e))
     # Try to handle some common scenarios when installer fails.
     if p.returncode == -11:
         LogWarning(u"Estimating package size since installer -pkginfo "
                    u"'%@' crashed", pkgPath)
         return cls.getPackageSize_(pkgPath) * 2
     elif p.returncode != 0:
         mountPoints = IEDMountInfo.getMountPoints()
         fsInfo = mountPoints[cls.findMountPoint_(pkgPath)]
         if not fsInfo[u"islocal"]:
             LogWarning(u"Estimating package size since installer -pkginfo "
                        u"failed and '%@' is on a remote (%@) filesystem",
                        pkgPath, fsInfo[u"fstypename"])
             return cls.getPackageSize_(pkgPath) * 2
         else:
             LogError(u"installer -pkginfo -pkg '%@' failed with exit code %d", pkgPath, p.returncode)
             return None
     outData = NSData.dataWithBytes_length_(out, len(out))
     plist, format, error = NSPropertyListSerialization.propertyListWithData_options_format_error_(outData,
                                                                                                   NSPropertyListImmutable,
                                                                                                   None,
                                                                                                   None)
     if not plist:
         LogError(u"Error decoding plist: %@", error)
         return None
     LogDebug(u"%@ requires %@", pkgPath, cls.formatBytes_(int(plist[u"Size"]) * 1024))
     return int(plist[u"Size"]) * 1024
Example #13
0
    def awakeFromNib(self):
        LogDebug("awakeFromNib")

        # Initialize UI.
        self.buildProgressBar.setMaxValue_(100.0)
        self.buildProgressMessage.setStringValue_("")
        self.setSourcePlaceholder()

        # We're a delegate for the drag and drop target, protocol:
        #   (void)acceptInstaller:(NSString *)path
        self.sourceBox.setDelegate_(self)
        self.sourceImage.setDelegate_(self)
        self.sourceLabel.setDelegate_(self)

        # We're a delegate for the update controller, protocol:
        #   (void)updateControllerChanged
        if self.updateController:
            self.updateController.setDelegate_(self)
        else:
            alert = NSAlert.alloc().init()
            alert.setMessageText_("Unable to initialize update controller")
            alert.setInformativeText_(
                "AutoDMG will not function correctly, check the log for details."
            )
            alert.runModal()

        # Main workflow logic.
        self.workflow = IEDWorkflow.alloc().initWithDelegate_(self)

        # Enabled state for main window.
        self.enabled = True

        # When busy is true quitting gets a confirmation prompt.
        self._busy = False

        # Currently loaded template.
        self.templateURL = None

        # Filesystem selection.
        self.filesystem.setAutoenablesItems_(False)
        self.filesystemHfs.setRepresentedObject_("hfs")
        self.filesystemApfs.setRepresentedObject_("apfs")
        if IEDUtil.hostMajorVersion() < 13:
            self.filesystem.selectItem_(self.filesystemHfs)
            self.filesystemApfs.setEnabled_(False)
        if IEDUtil.hostMajorVersion() == 13:
            self.filesystem.selectItem_(self.filesystemApfs)
            self.filesystemApfs.setEnabled_(True)
        else:
            self.filesystem.selectItem_(self.filesystemApfs)
            self.filesystemHfs.setEnabled_(False)
Example #14
0
 def continueSetSource_(self, failedUnmounts):
     LogDebug(u"continueSetSource:%@", failedUnmounts)
     
     self.alertFailedUnmounts_(failedUnmounts)
     
     self.installESDPath = os.path.join(self.newSourcePath, u"Contents/SharedSupport/InstallESD.dmg")
     if not os.path.exists(self.installESDPath):
         self.installESDPath = self.newSourcePath
     
     self.delegate.examiningSource_(self.newSourcePath)
     
     self.installerMountPoint = None
     self.baseSystemMountedFromPath = None
     self.dmgHelper.attach_selector_(self.installESDPath, self.handleSourceMountResult_)
Example #15
0
 def applicationShouldTerminate_(self, sender):
     LogDebug("applicationShouldTerminate:")
     if self.mainWindowController.busy():
         alert = NSAlert.alloc().init()
         alert.setAlertStyle_(NSCriticalAlertStyle)
         alert.setMessageText_("Application busy")
         alert.setInformativeText_("Quitting now could leave the "
                                   "system in an unpredictable state.")
         alert.addButtonWithTitle_("Quit")
         alert.addButtonWithTitle_("Stay")
         button = alert.runModal()
         if button == NSAlertSecondButtonReturn:
             return NSTerminateCancel
     return NSTerminateNow
Example #16
0
    def launchScript_(self, args):
        LogDebug("launchScript:")

        if (self.authPassword() is None) and (os.getuid() != 0):
            # Use GUI dialog to elevate privileges.
            task = STPrivilegedTask.alloc().init()
            task.setLaunchPath_(args[0])
            task.setArguments_(args[1:])
            status = task.launch()
            LogNotice("Install task launched with return code: %d", status)
            if status:
                self.performSelectorOnMainThread_withObject_waitUntilDone_(
                    self.handleLaunchScriptError_, status, False)
        else:
            task = NSTask.alloc().init()
            if os.getuid() == 0:
                # No privilege elevation necessary.
                task.setLaunchPath_(args[0])
                task.setArguments_(args[1:])
            else:
                # Use sudo to elevate privileges.
                task.setLaunchPath_("/usr/bin/sudo")
                task.setArguments_(["-kSE"] + args)
                # Send password to sudo on stdin.
                passwordpipe = NSPipe.alloc().init()
                task.setStandardInput_(passwordpipe.fileHandleForReading())
                task.setStandardOutput_(
                    NSFileHandle.fileHandleWithNullDevice())
                task.setStandardError_(NSFileHandle.fileHandleWithNullDevice())
                writer = passwordpipe.fileHandleForWriting()
                pwd = NSString.stringWithString_(self.authPassword() + "\n")
                writer.writeData_(pwd.dataUsingEncoding_(NSUTF8StringEncoding))
                writer.closeFile()
            try:
                task.launch()
                LogNotice("Install task launched%@",
                          " with sudo" if os.getuid() != 0 else "")
            except BaseException as e:
                LogWarning("Install task launch failed with exception")
                self.performSelectorOnMainThread_withObject_waitUntilDone_(
                    self.handleLaunchScriptError_, str(e), False)
                return
            task.waitUntilExit()
            LogNotice("Install task finished with exit status %d",
                      task.terminationStatus())
            if task.terminationStatus() != 0:
                self.performSelectorOnMainThread_withObject_waitUntilDone_(
                    self.handleLaunchScriptError_,
                    "Install task failed with status %d" %
                    task.terminationStatus(), False)
Example #17
0
    def updateFromURL_(self, url):
        """Download the latest UpdateProfiles.plist."""

        LogDebug("updateFromURL:%@", url)

        if self.profileUpdateWindow:
            # Show the progress window.
            self.progressBar.setIndeterminate_(True)
            self.progressBar.startAnimation_(self)
            self.profileUpdateWindow.makeKeyAndOrderFront_(self)

        # Create a buffer for data.
        self.profileUpdateData = NSMutableData.alloc().init()
        # Start download.
        request = NSURLRequest.requestWithURL_(url)
        self.connection = NSURLConnection.connectionWithRequest_delegate_(
            request, self)
        LogDebug("connection = %@", self.connection)
        if not self.connection:
            LogWarning("Connection to %@ failed", url)
            if self.profileUpdateWindow:
                self.profileUpdateWindow.orderOut_(self)
            self.delegate.profileUpdateFailed_(error)
Example #18
0
    def setSource_(self, path):
        LogDebug("setSource:%@", path)

        if not self.checkAppleBugWarning_(path):
            return

        self._source = None
        self.sourceType = None
        self.newSourcePath = path
        if self.installerMountPoint:
            self.delegate.ejectingSource()
            self.dmgHelper.detachAll_(self.continueSetSource_)
        else:
            self.continueSetSource_({})
Example #19
0
 def hdiutilDetach_(self, args):
     try:
         dmgPath, target, selector = args
         LogDebug(u"Detaching %@", dmgPath)
         try:
             cmd = [u"/usr/bin/hdiutil",
                    u"detach",
                    self.dmgs[dmgPath]]
         except KeyError:
             target.performSelectorOnMainThread_withObject_waitUntilDone_(selector,
                                                                          {u"success": False,
                                                                           u"dmg-path": dmgPath,
                                                                           u"error-message": u"%s not mounted" % dmgPath},
                                                                          False)
             return
         del self.dmgs[dmgPath]
         maxtries = 5
         for tries in range(maxtries):
             if tries == maxtries >> 1:
                 cmd.append(u"-force")
             p = subprocess.Popen(cmd,
                                  bufsize=1,
                                  stdout=subprocess.PIPE,
                                  stderr=subprocess.PIPE)
             out, err = p.communicate()
             if p.returncode == 0:
                 target.performSelectorOnMainThread_withObject_waitUntilDone_(selector,
                                                                              {u"success": True, u"dmg-path": dmgPath},
                                                                              False)
                 return
             elif tries == maxtries - 1:
                 errstr = u"hdiutil detach failed with return code %d" % p.returncode
                 if err:
                     errstr += u": %s" % err.decode(u"utf-8")
                 target.performSelectorOnMainThread_withObject_waitUntilDone_(selector,
                                                                              {u"success": False,
                                                                               u"dmg-path": dmgPath,
                                                                               u"error-message": errstr},
                                                                              False)
             else:
                 time.sleep(1)
     except Exception:
         exceptionInfo = traceback.format_exc()
         msg = u"Detach of %s crashed with exception:\n%s" % (dmgPath, exceptionInfo)
         target.performSelectorOnMainThread_withObject_waitUntilDone_(selector,
                                                                      {u"success": False,
                                                                       u"dmg-path": dmgPath,
                                                                       u"error-message": msg},
                                                                      False)
Example #20
0
 def openTemplateAtURL_(self, url):
     LogDebug("openTemplateAtURL:%@", url)
     self.templateURL = None
     template = IEDTemplate.alloc().init()
     error = template.loadTemplateAndReturnError_(url.path())
     if error:
         self.displayAlert_text_("Couldn't open template", error)
         return False
     self.templateURL = url
     NSDocumentController.sharedDocumentController(
     ).noteNewRecentDocumentURL_(url)
     # AdditionalPackages.
     LogDebug("Setting additional packages to %@",
              template.additionalPackages)
     self.addPkgController.replacePackagesWithPaths_(
         template.additionalPackages)
     # ApplyUpdates.
     if template.applyUpdates:
         LogDebug("Enable updates")
         self.updateController.applyUpdatesCheckbox.setState_(NSOnState)
     else:
         LogDebug("Disable updates")
         self.updateController.applyUpdatesCheckbox.setState_(NSOffState)
     # VolumeName.
     self.volumeName.setStringValue_("")
     if template.volumeName:
         LogDebug("Setting volume name to %@", template.volumeName)
         self.volumeName.setStringValue_(template.volumeName)
     # VolumeSize.
     self.volumeSize.setStringValue_("")
     if template.volumeSize:
         LogDebug("Setting volume size to %@", template.volumeSize)
         self.volumeSize.setIntValue_(template.volumeSize)
     # Finalize task: ASR imagescan.
     self.finalizeAsrImagescan.setState_(NSOnState)
     if template.finalizeAsrImagescan == False:
         LogDebug("Setting 'Finalize: Scan for restore' to %@",
                  template.finalizeAsrImagescan)
         self.finalizeAsrImagescan.setState_(NSOffState)
     # SourcePath.
     if template.sourcePath:
         LogDebug("Setting source to %@", template.sourcePath)
         self.setBusy_(True)
         self.workflow.setSource_(template.sourcePath)
     return True
Example #21
0
    def updateUsersProfilesIfNewer_(self, plist):
        """Update the user's update profiles if plist is newer. Returns
           whichever was the newest."""

        # Load UpdateProfiles from the user's application support directory.
        userUpdateProfiles = NSDictionary.dictionaryWithContentsOfFile_(
            self.userUpdateProfilesPath)

        # If the bundle's plist is newer, update the user's.
        if (not userUpdateProfiles) or (
                userUpdateProfiles[u"PublicationDate"].timeIntervalSinceDate_(
                    plist[u"PublicationDate"]) < 0):
            LogDebug(u"Saving updated UpdateProfiles.plist")
            self.saveUsersProfiles_(plist)
            return plist
        else:
            return userUpdateProfiles
Example #22
0
 def checkForAppUpdateSilently_(self, silently):
     self.checkSilently = silently
     # Create a buffer for data.
     self.plistData = NSMutableData.alloc().init()
     # Start download.
     osVer, osBuild = IEDUtil.readSystemVersion_("/")[1:3]
     appVer, appBuild = IEDUtil.getAppVersion()
     urlString = "%s?osVer=%s&osBuild=%s&appVer=%s&appBuild=%s" % (
         self.defaults.stringForKey_("AppVersionURL"), osVer, osBuild,
         appVer, appBuild)
     url = NSURL.URLWithString_(urlString)
     request = NSURLRequest.requestWithURL_(url)
     self.connection = NSURLConnection.connectionWithRequest_delegate_(
         request, self)
     LogDebug("connection = %@", self.connection)
     if not self.connection:
         LogWarning("Connection to %@ failed", url)
Example #23
0
    def nextPhase(self):
        LogDebug("nextPhase, currentPhase == %@", self.currentPhase)

        if self.currentPhase:
            self.progress += self.currentPhase["weight"]
            LogInfo("Phase %@ with weight %ld finished after %.3f seconds",
                    self.currentPhase["title"], self.currentPhase["weight"],
                    time.time() - self.phaseStartTime)
        self.phaseStartTime = time.time()
        try:
            self.currentPhase = self.currentTask["phases"].pop(0)
        except IndexError:
            self.fail_details_("No phase left in task",
                               traceback.format_stack())
            return
        LogNotice("Starting phase: %@", self.currentPhase["title"])
        self.delegate.buildSetPhase_(self.currentPhase["title"])
        self.delegate.buildSetProgress_(self.progress)
Example #24
0
 def hdiutilAttach_(self, args):
     dmgPath, selector = args
     LogDebug(u"Attaching %@", dmgPath)
     p = subprocess.Popen([
         u"/usr/bin/hdiutil", u"attach", dmgPath, u"-mountRandom", u"/tmp",
         u"-nobrowse", u"-noverify", u"-plist"
     ],
                          bufsize=1,
                          stdin=subprocess.PIPE,
                          stdout=subprocess.PIPE,
                          stderr=subprocess.PIPE)
     out, err = p.communicate(u"Y\n")
     if p.returncode != 0:
         errstr = u"hdiutil attach failed with return code %d" % p.returncode
         if err:
             errstr += u": %s" % err.decode(u"utf-8")
         self.tellDelegate_message_(selector, {
             u"success": False,
             u"dmg-path": dmgPath,
             u"error-message": errstr
         })
         return
     # Strip EULA text.
     xmlStartIndex = out.find("<?xml")
     plist = plistlib.readPlistFromString(out[xmlStartIndex:])
     for partition in plist[u"system-entities"]:
         if partition[u"content-hint"] == u"Apple_HFS":
             if u"mount-point" in partition:
                 self.dmgs[dmgPath] = partition[u"mount-point"]
                 break
     else:
         self.tellDelegate_message_(
             selector, {
                 u"success": False,
                 u"dmg-path": dmgPath,
                 u"error-message": u"No mounted filesystem in %s" % dmgPath
             })
         return
     self.tellDelegate_message_(
         selector, {
             u"success": True,
             u"dmg-path": dmgPath,
             u"mount-point": self.dmgs[dmgPath]
         })
Example #25
0
 def launchFinalize_(self, args):
     try:
         task = NSTask.alloc().init()
         task.setLaunchPath_(args[0])
         task.setArguments_(args[1:])
         task.launch()
         task.waitUntilExit()
         if task.terminationStatus() == 0:
             LogDebug("Finalize exited with status %d",
                      task.terminationStatus())
         else:
             errMsg = "Finalize task failed with status %d" % task.terminationStatus(
             )
             self.performSelectorOnMainThread_withObject_waitUntilDone_(
                 self.handleFinalizeError_, errMsg, False)
     except BaseException as e:
         errMsg = "Failed to launch finalize task: %s" % str(e)
         self.performSelectorOnMainThread_withObject_waitUntilDone_(
             self.handleFinalizeError_, errMsg, False)
Example #26
0
 def handleLaunchScriptError_(self, error):
     if isinstance(error, int):
         try:
             msg = {
                 -60001:
                 "The authorization rights are invalid.",
                 -60002:
                 "The authorization reference is invalid.",
                 -60003:
                 "The authorization tag is invalid.",
                 -60004:
                 "The returned authorization is invalid.",
                 -60005:
                 "The authorization was denied.",
                 -60006:
                 "The authorization was cancelled by the user.",
                 -60007:
                 "The authorization was denied since no user interaction was possible.",
                 -60008:
                 "Unable to obtain authorization for this operation.",
                 -60009:
                 "The authorization is not allowed to be converted to an external format.",
                 -60010:
                 "The authorization is not allowed to be created from an external format.",
                 -60011:
                 "The provided option flag(s) are invalid for this authorization operation.",
                 -60031:
                 "The specified program could not be executed.",
                 -60032:
                 "An invalid status was returned during execution of a privileged tool.",
                 -60033:
                 "The requested socket address is invalid (must be 0-1023 inclusive).",
             }[error]
         except KeyError:
             msg = "Unknown error (%d)." % error
     else:
         msg = error
     if error == -60006:
         LogDebug("User cancelled auth.")
         # User cancelled.
         self.stop()
     else:
         self.fail_details_("Build failed", msg)
Example #27
0
    def saveTemplateToURL_(self, url):
        LogDebug(u"saveTemplateToURL:%@", url)
        self.templateURL = url
        NSDocumentController.sharedDocumentController(
        ).noteNewRecentDocumentURL_(url)

        # Create a template from the current state.
        template = IEDTemplate.alloc().init()
        if self.workflow.source():
            template.setSourcePath_(self.workflow.source())
        if self.updateController.packagesToInstall():
            template.setApplyUpdates_(True)
        else:
            template.setApplyUpdates_(False)
        template.setAdditionalPackages_(
            [x.path() for x in self.addPkgController.packagesToInstall()])

        error = template.saveTemplateAndReturnError_(url.path())
        if error:
            self.displayAlert_text_(u"Couldn't save template", error)
Example #28
0
    def awakeFromNib(self):
        LogDebug("awakeFromNib")

        # Initialize UI.
        self.buildProgressBar.setMaxValue_(100.0)
        self.buildProgressMessage.setStringValue_("")
        self.setSourcePlaceholder()

        # We're a delegate for the drag and drop target, protocol:
        #   (void)acceptInstaller:(NSString *)path
        self.sourceBox.setDelegate_(self)
        self.sourceImage.setDelegate_(self)
        self.sourceLabel.setDelegate_(self)

        # We're a delegate for the update controller, protocol:
        #   (void)updateControllerChanged
        self.updateController.setDelegate_(self)

        # Main workflow logic.
        self.workflow = IEDWorkflow.alloc().initWithDelegate_(self)

        # Enabled state for main window.
        self.enabled = True

        # When busy is true quitting gets a confirmation prompt.
        self._busy = False

        # Currently loaded template.
        self.templateURL = None

        # Filesystem selection.
        self.filesystem.setAutoenablesItems_(False)
        self.filesystemHfs.setRepresentedObject_("hfs")
        self.filesystemApfs.setRepresentedObject_("apfs")
        osMajor = IEDUtil.hostVersionTuple()[1]
        if osMajor < 13:
            self.filesystem.selectItem_(self.filesystemHfs)
            self.filesystemApfs.setEnabled_(False)
        else:
            self.filesystem.selectItem_(self.filesystemApfs)
            self.filesystemApfs.setEnabled_(True)
Example #29
0
    def continueSetSource_(self, failedUnmounts):
        LogDebug("continueSetSource:%@", failedUnmounts)

        self.alertFailedUnmounts_(failedUnmounts)

        pathCandidates = [
            os.path.join(self.newSourcePath,
                         "Contents/SharedSupport/BaseSystem.dmg"),
            os.path.join(self.newSourcePath,
                         "Contents/SharedSupport/InstallESD.dmg"),
            self.newSourcePath,
        ]
        for path in pathCandidates:
            if os.path.isfile(path):
                dmgPath = path
                break
        else:
            iaToolPath = os.path.join(
                self.newSourcePath, "Contents/Resources/InstallAssistantTool")
            baseName = os.path.basename(self.newSourcePath)
            if os.path.exists(iaToolPath):
                self.delegate.sourceFailed_text_(
                    "Incomplete installer",
                    "Installation resources are missing from '%s'. " % baseName
                    +
                    "Try downloading a new installer from the App Store straight from "
                    +
                    "Apple without using an internal Software Update or caching server."
                )
            else:
                self.delegate.sourceFailed_text_(
                    "Failed to mount %s" % self.newSourcePath,
                    "No system dmg found")
            return

        self.delegate.examiningSource_(self.newSourcePath)

        self.installerMountPoint = None
        self.baseSystemMountedFromPath = None
        self.dmgHelper.attach_selector_(dmgPath, self.handleSourceMountResult_)
Example #30
0
    def checkVersion_(self, mountPoint):
        LogDebug("checkVersion:%@", mountPoint)

        # We're now examining InstallESD.dmg for 10.7/10.8, BaseSystem.dmg for
        # 10.9, or a system image.
        name, version, build = IEDUtil.readSystemVersion_(mountPoint)
        if self.baseSystemMountedFromPath:
            self.dmgHelper.detach_selector_(self.baseSystemMountedFromPath,
                                            self.handleDetachResult_)
        installerVersion = IEDUtil.splitVersion(version)
        runningVersion = IEDUtil.hostVersionTuple()
        LogNotice("Found source: %@ %@ %@", name, version, build)
        if installerVersion[:2] != runningVersion[:2]:
            self.delegate.ejectingSource()
            majorVersion = ".".join(str(x) for x in installerVersion[:2])
            self.delegate.sourceFailed_text_("OS version mismatch",
                                             "The major version of the installer and the current OS must match.\n\n" + \
                                             "%s %s %s installer requires running %s.x to build an image." % (
                                                name, version, build,
                                                majorVersion))
            self.dmgHelper.detachAll_(self.alertFailedUnmounts_)
            return
        LogNotice("Accepted source %@: %@ %@ %@", self.newSourcePath, name,
                  version, build)
        self._source = self.newSourcePath
        self.installerName = name
        self.installerVersion = version
        self.installerBuild = build
        info = {
            "name": name,
            "version": version,
            "build": build,
            "template": self.loadImageTemplate_(mountPoint),
            "sourceType": self.sourceType,
        }
        self.delegate.sourceSucceeded_(info)
        # There's no reason to keep the dmg mounted if it's not an InstallESD.
        if self.sourceType != IEDWorkflow.INSTALL_ESD:
            self.dmgHelper.detachAll_(self.ejectSystemImage_)