Exemple #1
0
	def refreshAddonsList(self,activeIndex=0):
		self.addonsList.DeleteAllItems()
		self.curAddons=[]
		shouldEnableIncompatAddonsButton = False
		for addon in addonHandler.getAvailableAddons():
			self.addonsList.Append((
				addon.manifest['summary'],
				self.getAddonStatus(addon),
				addon.manifest['version'],
				addon.manifest['author']
			))
			self.curAddons.append(addon)
			shouldEnableIncompatAddonsButton = (
				shouldEnableIncompatAddonsButton or (
					addonVersionCheck.hasAddonGotRequiredSupport(addon, version=addonVersionCheck.CURRENT_NVDA_VERSION)
					and not addonVersionCheck.isAddonTested(addon, version=addonVersionCheck.CURRENT_NVDA_VERSION)
				)
			)
		self.incompatAddonsButton.Enable(shouldEnableIncompatAddonsButton)
		# select the given active addon or the first addon if not given
		curAddonsLen=len(self.curAddons)
		if curAddonsLen>0:
			if activeIndex==-1:
				activeIndex=curAddonsLen-1
			elif activeIndex<0 or activeIndex>=curAddonsLen:
				activeIndex=0
			self.addonsList.Select(activeIndex,on=1)
			self.addonsList.SetItemState(activeIndex,wx.LIST_STATE_FOCUSED,wx.LIST_STATE_FOCUSED)
		else:
			self.aboutButton.Disable()
			self.helpButton.Disable()
			self.removeButton.Disable()
Exemple #2
0
	def refreshAddonsList(self,activeIndex=0):
		self.addonsList.DeleteAllItems()
		self.curAddons=[]
		anyAddonIncompatible = False
		for addon in addonHandler.getAvailableAddons():
			self.addonsList.Append((
				addon.manifest['summary'],
				self.getAddonStatus(addon),
				addon.manifest['version'],
				addon.manifest['author']
			))
			self.curAddons.append(addon)
			anyAddonIncompatible = (
				anyAddonIncompatible  # once we find one incompatible addon we don't need to continue
				or not addonVersionCheck.isAddonCompatible(
					addon,
					currentAPIVersion=addonAPIVersion.CURRENT,
					backwardsCompatToVersion=addonAPIVersion.BACK_COMPAT_TO
				)
			)
		self.incompatAddonsButton.Enable(anyAddonIncompatible)
		# select the given active addon or the first addon if not given
		curAddonsLen=len(self.curAddons)
		if curAddonsLen>0:
			if activeIndex==-1:
				activeIndex=curAddonsLen-1
			elif activeIndex<0 or activeIndex>=curAddonsLen:
				activeIndex=0
			self.addonsList.Select(activeIndex,on=1)
			self.addonsList.SetItemState(activeIndex,wx.LIST_STATE_FOCUSED,wx.LIST_STATE_FOCUSED)
		else:
			self.aboutButton.Disable()
			self.helpButton.Disable()
			self.removeButton.Disable()
Exemple #3
0
def onInstall():
	for addon in addonHandler.getAvailableAddons():
		if addon.manifest['name'] == "EloquenceAutoLanguageSwitching":
			gui.messageBox(
				"You have an older version of Eloquence Auto Language Switching installed, it is going to be uninstalled now to avoid compatibility issues.",
				"Older version installed",
				wx.ICON_WARNING)
			addon.requestRemove()
Exemple #4
0
def onInstall():
	for addon in addonHandler.getAvailableAddons():
		if addon.manifest['name'] == "CalibreNvda":
			if gui.messageBox(
				# Translators: the label of a message box dialog.
				_("You have installed an old and incompatible version of this add-on. Do you want to uninstall the old version?"),
				# Translators: the title of a message box dialog.
				_("Uninstall old add-on"),
				wx.YES|wx.NO|wx.ICON_WARNING) == wx.YES:
					addon.requestRemove()
			break
Exemple #5
0
		def afterDialog(res):
			# here we need to check if the compatibility has changed.
			# addons that have become incompat should be disabled, and a restart prompt shown
			# addons that have become compat should be visible, but not enabled unless they already were.
			from addonHandler.compatValues import MANUALLY_SET_INCOMPATIBLE
			getAddonCompatibility = AddonCompatibilityState.getAddonCompatibility
			manuallySetIncompatibleAddons = addonHandler.getAvailableAddons(
				filterFunc=lambda addon: ( MANUALLY_SET_INCOMPATIBLE == getAddonCompatibility(addon, CURRENT_NVDA_VERSION))
			)
			for addon in manuallySetIncompatibleAddons:
				addon.enable(shouldEnable=False)
			self.refreshAddonsList()
Exemple #6
0
	def refreshAddonsList(self,activeIndex=0):
		self.addonsList.DeleteAllItems()
		self.curAddons=[]
		for addon in addonHandler.getAvailableAddons():
			self.addonsList.Append((addon.manifest['summary'], self.getAddonStatus(addon), addon.manifest['version'], addon.manifest['author']))
			self.curAddons.append(addon)
		# select the given active addon or the first addon if not given
		curAddonsLen=len(self.curAddons)
		if curAddonsLen>0:
			if activeIndex==-1:
				activeIndex=curAddonsLen-1
			elif activeIndex<0 or activeIndex>=curAddonsLen:
				activeIndex=0
			self.addonsList.Select(activeIndex,on=1)
			self.addonsList.SetItemState(activeIndex,wx.LIST_STATE_FOCUSED,wx.LIST_STATE_FOCUSED)
		else:
			self.aboutButton.Disable()
			self.removeButton.Disable()
Exemple #7
0
def onInstall():
	for addon in addonHandler.getAvailableAddons():
		if addon.manifest['name'] == "zRadio":
			dirOrigen =os.path.join(globalVars.appArgs.configPath)
			dirDestino =os.path.join(globalVars.appArgs.configPath, "zRadio")
			fileOptions = os.path.join(dirOrigen, "opciones.dat")
			fileOptionsRadio = os.path.join(dirOrigen, "opt_radio.dat")
			fileFavRadio = os.path.join(dirOrigen, "fav_radios.dat")
			if os.path.exists(dirDestino):
				pass
			else:
				os.mkdir(os.path.join(dirOrigen, "zRadio"))
				if os.path.isfile(fileOptions):
					shutil.move(fileOptions, os.path.join(dirDestino, "opciones.dat"))
				if os.path.isfile(fileOptionsRadio):
					shutil.move(fileOptionsRadio, os.path.join(dirDestino, "opt_radio.dat"))
				if os.path.isfile(fileFavRadio):
					shutil.move(fileFavRadio, os.path.join(dirDestino, "fav_radios.dat"))


			break
Exemple #8
0
 def refreshAddonsList(self, activeIndex=0):
     self.addonsList.DeleteAllItems()
     self.curAddons = []
     for addon in addonHandler.getAvailableAddons():
         self.addonsList.Append(
             (addon.manifest['summary'], self.getAddonStatus(addon),
              addon.manifest['version'], addon.manifest['author']))
         self.curAddons.append(addon)
     # select the given active addon or the first addon if not given
     curAddonsLen = len(self.curAddons)
     if curAddonsLen > 0:
         if activeIndex == -1:
             activeIndex = curAddonsLen - 1
         elif activeIndex < 0 or activeIndex >= curAddonsLen:
             activeIndex = 0
         self.addonsList.Select(activeIndex, on=1)
         self.addonsList.SetItemState(activeIndex, wx.LIST_STATE_FOCUSED,
                                      wx.LIST_STATE_FOCUSED)
     else:
         self.aboutButton.Disable()
         self.removeButton.Disable()
Exemple #9
0
 def processUpdate(expectedSHA256Sum):
     url = addonInfos["url"]
     if url.endswith('/'):
         url = url[0:-1]
     url = "%s.nvda-addon?%s" % (url, urlencode(paramsDL()))
     fp = os.path.join(globalVars.appArgs.configPath,
                       "%s.nvda-addon" % sectionName)
     try:
         with urllib.request.urlopen(url) as res:
             with open(fp, "wb") as out:
                 out.write(res.read())
         actualSHA256Sum = SHA256Sum(fp)
         if expectedSHA256Sum != actualSHA256Sum:
             log.info("Invalid hash for %s. Actual: %s, expected: %s" %
                      (fp, actualSHA256Sum, expectedSHA256Sum))
             msg = _(
                 "Hashes do not match! Actual value is '{actualHash}'. Expected is '{expectedHash}'."
             ).format(actualHash=actualSHA256Sum,
                      expectedHash=expectedSHA256Sum)
             wx.CallAfter(errorUpdateDialog, msg)
             return
         curAddons = []
         for addon in addonHandler.getAvailableAddons():
             curAddons.append(addon)
         bundle = addonHandler.AddonBundle(fp)
         prevAddon = None
         bundleName = bundle.manifest['name']
         for addon in curAddons:
             if not addon.isPendingRemove and bundleName == addon.manifest[
                     "name"]:
                 prevAddon = addon
                 break
         if prevAddon:
             prevAddon.requestRemove()
         addonHandler.installAddonBundle(bundle)
         core.restart()
     except BaseException as e:
         log.error(e)
         return wx.CallAfter(errorUpdateDialog, e)
Exemple #10
0
    def __init__(self):
        """Initializes the global plugin object."""
        super(globalPluginHandler.GlobalPlugin, self).__init__()
        global _nvdaGetPropertiesSpeech, _nvdaSpeak, _gpObject

        # if on a secure Desktop, disable the Add-on
        if globalVars.appArgs.secure: return
        _gpObject = self
        try:
            self.language = config.conf["general"]["language"]
        except:
            self.language = None
            pass
        if self.language is None or self.language == 'Windows':
            try:
                self.language = languageHandler.getWindowsLanguage()[:2]
            except:
                self.language = 'en'
        self.updater = updater.ExtensionUpdater()
        self.updater.start()
        self.inTimer = False
        self.hasBeenUpdated = False
        wx.CallLater(1000, self.onTimer)
        import addonHandler
        version = None
        for addon in addonHandler.getAvailableAddons():
            if addon.name == "translate":
                version = addon.version
        if version is None:
            version = 'unknown'
        logHandler.log.info("Translate (%s) initialized, translating to %s" %
                            (version, self.language))

        _nvdaSpeak = speech._manager.speak
        _nvdaGetPropertiesSpeech = speech.getPropertiesSpeech
        speech._manager.speak = speak
        speech.getPropertiesSpeech = _nvdaGetPropertiesSpeech
        self.loadLocalCache()
def onInstall(postPathBug = False):
	#Add ourself to the path, so that commands when spoken can be queried to us.
	#Only if we are truely installing though.
	addons = []
	if not postPathBug:
		addons = addonHandler.getAvailableAddons()
	for addon in addons:
		if addon.name=="DictationBridge":
			#Hack to work around condition where
			#the uninstaller removes this addon from the path
			#After the installer for the updator ran.
			#We could use version specific directories, but wsr macros Does not
			#play nice with refreshing the path environment after path updates,
			# requiring a complete reboot of wsr, or commands spontaneously break cripticly.
			with open(os.path.join(config.getUserDefaultConfigPath(), ".dbInstall"), 
				"w") as fi:
				fi.write("dbInstall")
				return
	key = _winreg.OpenKeyEx(_winreg.HKEY_CURRENT_USER, "Environment", 0, _winreg.KEY_READ | _winreg.KEY_WRITE)
	try:
		value, typ = _winreg.QueryValueEx(key, "Path")
	except:
		value, typ = None, _winreg.REG_EXPAND_SZ
	if value is None:
		value = ""
	dir = os.path.dirname(__file__)
	if not isinstance(dir, unicode):
		dir = dir.decode(sys.getfilesystemencoding())
	dir = dir.replace(addonHandler.ADDON_PENDINGINSTALL_SUFFIX, "")
	log.info("addon directory: %r" % dir)
	log.info("current PATH: %r" % value)
	if value.lower().find(dir.lower()) == -1:
		if value != "":
			value += ";"
		value += dir
		log.info("new PATH: %r" % value)
		_winreg.SetValueEx(key, "Path", None, typ, value)
		sendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0, u"Environment")
Exemple #12
0
 def onTimer(self):
     if self.inTimer is True or self.hasBeenUpdated is True:
         return
     self.inTimer = True
     try:
         evt = self.updater.queue.get_nowait()
     except queue.Empty:
         evt = None
     if evt is not None:
         filepath = evt.get("download", None)
         if filepath is not None:
             import addonHandler
             for prev in addonHandler.getAvailableAddons():
                 if prev.name == updater.ADDON_NAME:
                     prev.requestRemove()
             bundle = addonHandler.AddonBundle(filepath)
             addonHandler.installAddonBundle(bundle)
             logHandler.log.info(
                 "Installed version %s, restart NVDA to make the changes permanent"
                 % (evt["version"]))
             self.hasBeenUpdated = True
     self.inTimer = False
     wx.CallLater(1000, self.onTimer)
Exemple #13
0
def checkForAddonUpdates():
	curAddons = {}
	addonSummaries = {}
	for addon in addonHandler.getAvailableAddons():
		# Sorry Nuance Vocalizer family, no update checks for you.
		if "vocalizer" in addon.name.lower(): continue
		manifest = addon.manifest
		name = addon.name
		if name in addonUtils.updateState["noUpdates"]: continue
		curVersion = manifest["version"]
		# Check different channels if appropriate.
		updateChannel = manifest.get("updateChannel")
		if updateChannel == "None": updateChannel = None
		if updateChannel != "dev" and name in addonUtils.updateState["devUpdates"]:
			updateChannel = "dev"
		elif updateChannel == "dev" and name not in addonUtils.updateState["devUpdates"]:
			updateChannel = None
		curAddons[name] = {"summary": manifest["summary"], "version": curVersion, "channel": updateChannel}
		addonSummaries[name] = manifest["summary"]
	try:
		info = checkForAddonUpdate(curAddons)
	except:
		info = {}
	#data = json.dumps(curAddons)
	# Pseudocode:
	"""try:
		res = urllib.open(someURL, data)
		# Check SSL and what not.
		res = json.loads(res)"""
	#res = json.loads(data)
	res = info
	for addon in res:
		res[addon]["summary"] = addonSummaries[addon]
		# In reality, it'll be a list of URL's to try.
		res[addon]["urls"] = res[addon]["path"]
	return res if len(res) else None
	def getAddonsList(self):
		from locale import strxfrm
		if py3:
			return sorted(addonHandler.getAvailableAddons(), key=lambda a: strxfrm(a.manifest['summary']))
		else:
			return sorted(addonHandler.getAvailableAddons(), key=lambda a: strxfrm(a.manifest['summary'].encode("mbcs")))
Exemple #15
0
def installAddon(parentWindow, addonPath):
	""" Installs the addon at path. Any error messages / warnings are presented to the user via a GUI message box.
	If attempting to install an addon that is pending removal, it will no longer be pending removal.
	:return True on success or False on failure.
	"""
	try:
		bundle = addonHandler.AddonBundle(addonPath)
	except:
		log.error("Error opening addon bundle from %s" % addonPath, exc_info=True)
		gui.messageBox(
			# Translators: The message displayed when an error occurs when opening an add-on package for adding.
			_("Failed to open add-on package file at %s - missing file or invalid file format") % addonPath,
			# Translators: The title of a dialog presented when an error occurs.
			_("Error"),
			wx.OK | wx.ICON_ERROR
		)
		return False  # Exit early, can't install an invalid bundle

	if not addonVersionCheck.hasAddonGotRequiredSupport(bundle):
		_showAddonRequiresNVDAUpdateDialog(parentWindow, bundle)
		return False  # Exit early, addon does not have required support
	elif not addonVersionCheck.isAddonTested(bundle):
		_showAddonTooOldDialog(parentWindow, bundle)
		return False  # Exit early, addon is not up to date with the latest API version.
	elif wx.YES != _showConfirmAddonInstallDialog(parentWindow, bundle):
		return False  # Exit early, User changed their mind about installation.

	prevAddon = None
	for addon in addonHandler.getAvailableAddons():
		if not addon.isPendingRemove and bundle.name==addon.manifest['name']:
			prevAddon=addon
			break
	if prevAddon:
		summary=bundle.manifest["summary"]
		curVersion=prevAddon.manifest["version"]
		newVersion=bundle.manifest["version"]

		# Translators: A title for the dialog asking if the user wishes to update a previously installed
		# add-on with this one.
		messageBoxTitle = _("Add-on Installation")

		# Translators: A message asking if the user wishes to update an add-on with the same version
		# currently installed according to the version number.
		overwriteExistingAddonInstallationMessage = _(
			"You are about to install version {newVersion} of {summary}, which appears to be already installed. "
			"Would you still like to update?"
		).format(summary=summary, newVersion=newVersion)

		# Translators: A message asking if the user wishes to update a previously installed add-on with this one.
		updateAddonInstallationMessage = _(
			"A version of this add-on is already installed. "
			"Would you like to update {summary} version {curVersion} to version {newVersion}?"
		).format(summary=summary, curVersion=curVersion, newVersion=newVersion)

		if gui.messageBox(
			overwriteExistingAddonInstallationMessage if curVersion == newVersion else updateAddonInstallationMessage,
			messageBoxTitle,
			wx.YES|wx.NO|wx.ICON_WARNING
		) != wx.YES:
				return False
		prevAddon.requestRemove()

	from contextlib import contextmanager

	@contextmanager
	def doneAndDestroy(window):
		try:
			yield window
		except:
			# pass on any exceptions
			raise
		finally:
			# but ensure that done and Destroy are called.
			window.done()
			window.Destroy()

	#  use a progress dialog so users know that something is happening.
	progressDialog = gui.IndeterminateProgressDialog(
		parentWindow,
		# Translators: The title of the dialog presented while an Addon is being installed.
		_("Installing Add-on"),
		# Translators: The message displayed while an addon is being installed.
		_("Please wait while the add-on is being installed.")
	)

	try:
		# Use context manager to ensure that `done` and `Destroy` are called on the progress dialog afterwards
		with doneAndDestroy(progressDialog):
			gui.ExecAndPump(addonHandler.installAddonBundle, bundle)
			return True
	except:
		log.error("Error installing  addon bundle from %s" % addonPath, exc_info=True)
		gui.messageBox(
			# Translators: The message displayed when an error occurs when installing an add-on package.
			_("Failed to install add-on from %s") % addonPath,
			# Translators: The title of a dialog presented when an error occurs.
			_("Error"),
			wx.OK | wx.ICON_ERROR
		)
	return False
def onInstall():
    for addon in addonHandler.getAvailableAddons():
        if addon.manifest['name'] == "remote" and addon.manifest[
                'version'].endswith("+"):
            askToRemove(addon)
            break
Exemple #17
0
def shouldNotUpdate():
	# Returns a list of descriptions for add-ons that should not update.
	return [addon.manifest["summary"] for addon in addonHandler.getAvailableAddons()
		if addon.name in addonUtils.updateState["noUpdates"]]
	def getAddonsList(self):
		from locale import strxfrm
		return sorted(addonHandler.getAvailableAddons(), key=lambda a: strxfrm(a.manifest['summary']))
Exemple #19
0
    def updateAddonDic(self, addonDic):
        """
		This method makes it possible to create a dictionary grouping all the add-ons that contain scripts associated or not with gestures.
		"""
        import addonHandler
        # We gather all the gestures available in a dictionary, thanks to inputCore.manager.getAllGestureMappings.
        allGest = inputCore.manager.getAllGestureMappings(
            obj=gui.mainFrame.prevFocus,
            ancestors=gui.mainFrame.prevFocusAncestors)
        # We store the list of installed add-ons in a variable named addonsList.
        addonsList = [addon for addon in addonHandler.getAvailableAddons()]
        # We Iterates through the dictionary containing all the available gestures.
        for category in allGest:
            # We create a local variable, storing the value of each of the main items in our dictionary.
            command = allGest[category]
            # These items represent the different categories available.
            # The values retrieved by allGest[category], in turn comprise another dictionary grouping the description of each of the scripts in each category.
            # We Iterates among the dictionary objects for each of the categories.
            for doc in command:
                # Each item of its sub-dictionaries represents the documentation of each of the scripts, which is why it was preferably named doc.
                # We now create a local variable script, which will retrieve each of the values of our sub-dictionary.
                script = command[doc]
                # each of its values is an instance of the inputCore.AllGesturesScriptInfo class for each of the scripts.
                # It's an object representing a script, which is why it was preferably named script.
                # We check if our script is that of an add-on, we will make further checks below.
                if script.moduleName.startswith(
                        "globalPlugins") or script.moduleName.startswith(
                            "appModules"):
                    # The moduleName property of each of these script objects returns the name of the module that contains the script.
                    # Now, it's going to be a bit complicated.
                    # We point to the script object directly in the appModule or globalPlugin, to check its path.
                    scriptMod = getattr(
                        script.cls, "script_{scriptName}".format(
                            scriptName=script.scriptName), None)
                    if scriptMod:
                        # Here is the path to the module, it will be interesting, because it's it that will reveal if it's an add-on or not.
                        modPath = scriptMod.im_func.func_code.co_filename
                        # This is the only way we have to retrieve the name of the add-on.
                        # We check the presence of the "addons" directory in the path.
                        if any(addon.path in modPath for addon in addonsList):
                            # There is no longer any doubt, it's an add-on.
                            # We get the summary of the add-on.
                            addonSum = [
                                addon.manifest["summary"]
                                for addon in addonsList
                                if addon.path in modPath
                            ][0]
                            # We check the gesture (s) of our script.
                            if len(script.gestures) > 0:
                                gestInfo = " | ".join([
                                    self.adjustGesture(x)
                                    for x in script.gestures
                                ])
                            else:
                                #. Translators: Message to inform there are no command assigned.
                                gestInfo = _(
                                    "Not assigned to gesture or part of layered commands"
                                )
                            # We try to update our dictionary addonDic, according to whether it has taken knowledge of each item or not.
                            try:
                                addonDic[addonSum][
                                    gestInfo] = script.displayName
                            except KeyError:
                                # It has not yet read it, so we create the very first sub-dictionary representing each of our scripts contained in each of our add-ons.
                                addonDic[addonSum] = {}
                                # We can now make our update.
                                addonDic[addonSum][
                                    gestInfo] = script.displayName
Exemple #20
0
if not versionInfo.updateVersionType:
    raise RuntimeError(
        "NVDA is running from source code, add-on update check is not supported"
    )
# NVDA 2018.1 and later.
import config
if config.isAppX:
    raise RuntimeError("This is NVDA Windows Store edition")
import addonHandler

addonHandler.initTranslation()
# Provided that NVDA issue 3208 is implemented.
if hasattr(addonHandler, "checkForAddonUpdate"):
    raise RuntimeError("NVDA itself will check for add-on updates")
# Temporary: check of Add-on Updater add-on is running.
for addon in addonHandler.getAvailableAddons():
    if (addon.name, addon.isDisabled) == ("addonUpdater", False):
        raise RuntimeError("Another add-on update provider exists")

import sys

py3 = sys.version.startswith("3")
import os  # Essentially, update download is no different than file downloads.
import time
if py3:
    import pickle
    from urllib.request import urlopen
else:
    import cPickle as pickle
    from urllib import urlopen
import threading
Exemple #21
0
 def _downloadSuccess(self):
     self._stopped()
     try:
         try:
             bundle = addonHandler.AddonBundle(self.destPath)
         except:
             log.error(f"Error opening addon bundle from {self.destPath}",
                       exc_info=True)
             gui.messageBox(
                 # Translators: The message displayed when an error occurs
                 # when trying to update an add-on package due to package problems.
                 _("Cannot update {name} - missing file or invalid file format"
                   ).format(name=self.addonName),
                 translate("Error"),
                 wx.OK | wx.ICON_ERROR)
             self.continueUpdatingAddons()
             return
         # Check compatibility with NVDA and/or Windows release.
         # NVDA itself will check add-on compatibility range.
         # As such, the below fragment was borrowed from NVDA Core (credit: NV Access).
         from addonHandler import addonVersionCheck
         from gui import addonGui
         # Check compatibility with NVDA and/or Windows release.
         if not addonVersionCheck.hasAddonGotRequiredSupport(bundle):
             addonGui._showAddonRequiresNVDAUpdateDialog(
                 gui.mainFrame, bundle)
             self.continueUpdatingAddons()
             return
         elif not addonVersionCheck.isAddonTested(bundle):
             addonGui._showAddonTooOldDialog(gui.mainFrame, bundle)
             self.continueUpdatingAddons()
             return
         # Some add-ons require a specific Windows release or later.
         # Prepare for winVersion.getWinVer function.
         import winVersion
         minimumWindowsVersion = bundle.manifest.get(
             "minimumWindowsVersion", None)
         if hasattr(winVersion, "getWinVer"):
             if minimumWindowsVersion is None:
                 minimumWindowsVersion = winVersion.getWinVer()
             else:
                 minimumWindowsVersion = winVersion.WinVersion.fromVersionText(
                     minimumWindowsVersion)
             winVersionUnsupported = winVersion.getWinVer(
             ) < minimumWindowsVersion
         else:
             if minimumWindowsVersion is None:
                 minimumWindowsVersion = winVersion.winVersion[:3]
             else:
                 minimumWindowsVersion = [
                     int(data) for data in minimumWindowsVersion.split(".")
                 ]
             minimumWinMajor, minimumWinMinor, minimumWinBuild = minimumWindowsVersion
             winMajor, winMinor, winBuild = winVersion.winVersion[:3]
             winVersionUnsupported = (winMajor, winMinor, winBuild) < (
                 minimumWinMajor, minimumWinMinor, minimumWinBuild)
         if winVersionUnsupported:
             gui.messageBox(
                 # Translators: The message displayed when the add-on requires a newer version of Windows.
                 _("{name} add-on is not compatible with this version of Windows."
                   ).format(name=self.addonName),
                 translate("Error"),
                 wx.OK | wx.ICON_ERROR)
             self.continueUpdatingAddons()
             return
         bundleName = bundle.manifest['name']
         isDisabled = False
         # Optimization (future): it is better to remove would-be add-ons all at once
         # instead of doing it each time a bundle is opened.
         for addon in addonHandler.getAvailableAddons():
             # Check for disabled state first.
             if bundleName == addon.manifest['name']:
                 if addon.isDisabled:
                     isDisabled = True
                 if not addon.isPendingRemove:
                     addon.requestRemove()
                 break
         progressDialog = gui.IndeterminateProgressDialog(
             gui.mainFrame,
             # Translators: The title of the dialog presented while an Addon is being updated.
             _("Updating {name}").format(name=self.addonName),
             # Translators: The message displayed while an addon is being updated.
             _("Please wait while the add-on is being updated."))
         try:
             gui.ExecAndPump(addonHandler.installAddonBundle, bundle)
         except:
             log.error(
                 f"Error installing  addon bundle from {self.destPath}",
                 exc_info=True)
             progressDialog.done()
             progressDialog.Hide()
             progressDialog.Destroy()
             gui.messageBox(
                 # Translators: The message displayed when an error occurs when installing an add-on package.
                 _("Failed to update {name} add-on").format(
                     name=self.addonName),
                 translate("Error"),
                 wx.OK | wx.ICON_ERROR)
             self.continueUpdatingAddons()
             return
         else:
             progressDialog.done()
             progressDialog.Hide()
             progressDialog.Destroy()
             _updatedAddons.append(bundleName)
             if isDisabled:
                 for addon in addonHandler.getAvailableAddons():
                     if bundleName == addon.manifest[
                             'name'] and addon.isPendingInstall:
                         addon.enable(False)
                         break
     finally:
         try:
             os.remove(self.destPath)
         except OSError:
             pass
     self.continueUpdatingAddons()
Exemple #22
0
 def _downloadSuccess(self):
     self._stopped()
     try:
         try:
             bundle = addonHandler.AddonBundle(self.destPath.decode("mbcs"))
         except AttributeError:
             bundle = addonHandler.AddonBundle(self.destPath)
         except:
             log.error("Error opening addon bundle from %s" % self.destPath,
                       exc_info=True)
             # Translators: The message displayed when an error occurs when trying to update an add-on package due to package problems.
             gui.messageBox(
                 _("Cannot update {name} - missing file or invalid file format"
                   ).format(name=self.addonName), translate("Error"),
                 wx.OK | wx.ICON_ERROR)
             self.continueUpdatingAddons()
             return
         # Check compatibility with NVDA and/or Windows release.
         import versionInfo
         minimumNVDAVersion = bundle.manifest.get("minimumNVDAVersion",
                                                  None)
         if minimumNVDAVersion is None:
             minimumNVDAVersion = [
                 versionInfo.version_year, versionInfo.version_major
             ]
         lastTestedNVDAVersion = bundle.manifest.get(
             "lastTestedNVDAVersion", None)
         if lastTestedNVDAVersion is None:
             lastTestedNVDAVersion = [
                 versionInfo.version_year, versionInfo.version_major
             ]
         # For NVDA version, only version_year.version_major will be checked.
         minimumYear, minimumMajor = minimumNVDAVersion[:2]
         lastTestedYear, lastTestedMajor = lastTestedNVDAVersion[:2]
         if not ((minimumYear, minimumMajor) <=
                 (versionInfo.version_year, versionInfo.version_major) <=
                 (lastTestedYear, lastTestedMajor)):
             # Translators: The message displayed when trying to update an add-on that is not going to be compatible with the current version of NVDA.
             gui.messageBox(
                 _("{name} add-on is not compatible with this version of NVDA. Minimum NVDA version: {minYear}.{minMajor}, last tested: {testedYear}.{testedMajor}."
                   ).format(name=self.addonName,
                            minYear=minimumYear,
                            minMajor=minimumMajor,
                            testedYear=lastTestedYear,
                            testedMajor=lastTestedMajor),
                 translate("Error"), wx.OK | wx.ICON_ERROR)
             self.continueUpdatingAddons()
             return
         # Some add-ons require a specific Windows release or later.
         import winVersion
         minimumWindowsVersion = bundle.manifest.get(
             "minimumWindowsVersion", None)
         if minimumWindowsVersion is None:
             minimumWindowsVersion = winVersion.winVersion[:3]
         else:
             minimumWindowsVersion = [
                 int(data) for data in minimumWindowsVersion.split(".")
             ]
         minimumWinMajor, minimumWinMinor, minimumWinBuild = minimumWindowsVersion
         winMajor, winMinor, winBuild = winVersion.winVersion[:3]
         if (winMajor, winMinor, winBuild) < (
                 minimumWinMajor, minimumWinMinor, minimumWinBuild):
             # Translators: The message displayed when the add-on requires a newer version of Windows.
             gui.messageBox(
                 _("{name} add-on is not compatible with this version of Windows."
                   ).format(name=self.addonName), translate("Error"),
                 wx.OK | wx.ICON_ERROR)
             self.continueUpdatingAddons()
             return
         bundleName = bundle.manifest['name']
         isDisabled = False
         # Optimization (future): it is better to remove would-be add-ons all at once instead of doing it each time a bundle is opened.
         for addon in addonHandler.getAvailableAddons():
             # Check for disabled state first.
             if bundleName == addon.manifest['name']:
                 if addon.isDisabled:
                     isDisabled = True
                 if not addon.isPendingRemove:
                     addon.requestRemove()
                 break
         progressDialog = gui.IndeterminateProgressDialog(
             gui.mainFrame,
             # Translators: The title of the dialog presented while an Addon is being updated.
             _("Updating {name}").format(name=self.addonName),
             # Translators: The message displayed while an addon is being updated.
             _("Please wait while the add-on is being updated."))
         try:
             gui.ExecAndPump(addonHandler.installAddonBundle, bundle)
         except:
             log.error("Error installing  addon bundle from %s" %
                       self.destPath,
                       exc_info=True)
             progressDialog.done()
             progressDialog.Hide()
             progressDialog.Destroy()
             # Translators: The message displayed when an error occurs when installing an add-on package.
             gui.messageBox(
                 _("Failed to update {name} add-on").format(
                     name=self.addonName), translate("Error"),
                 wx.OK | wx.ICON_ERROR)
             self.continueUpdatingAddons()
             return
         else:
             progressDialog.done()
             progressDialog.Hide()
             progressDialog.Destroy()
             _updatedAddons.append(bundleName)
             if isDisabled:
                 for addon in addonHandler.getAvailableAddons():
                     if bundleName == addon.manifest[
                             'name'] and addon.isPendingInstall:
                         addon.enable(False)
                         break
     finally:
         try:
             os.remove(self.destPath)
         except OSError:
             pass
     self.continueUpdatingAddons()
Exemple #23
0
def installAddon(storeClient, addon, closeAfter=False, silent=False):
    if silent == False:
        ui.message(_("Downloading %s") % (addon.name))
    data = storeClient.getAddonFile(addon.id, addon.versionId)

    if data is None:
        if silent == False:
            ui.message(_("Unable to download the add-on."))
        return False
    tmp = os.path.join(config.getUserDefaultConfigPath(),
                       "storeDownloadedAddon.nvda-addon")
    logHandler.log.info(u"Saving to %s" % (tmp))
    f = file(tmp, "wb")
    f.write(data)
    f.close()
    path = tmp
    if path is None:
        if silent == False:
            ui.message(_("Unable to download %s") % (addon.name))
        return False
    if silent == False:
        ui.message(_("Installing"))
    try:
        bundle = addonHandler.AddonBundle(path)
    except:
        logHandler.log.error("Error opening addon bundle from %s" % path,
                             exc_info=True)
        # Translators: The message displayed when an error occurs when opening an add-on package for adding.
        if silent == False:
            gui.messageBox(
                _("Failed to open add-on package file at %s - missing file or invalid file format"
                  ) % path,
                # Translators: The title of a dialog presented when an error occurs.
                _("Error"),
                wx.OK | wx.ICON_ERROR)
        return False
    bundleName = bundle.manifest['name']
    prevAddon = None
    for addon in addonHandler.getAvailableAddons():
        if not addon.isPendingRemove and bundleName == addon.manifest['name']:
            prevAddon = addon
            break
    if prevAddon:
        prevAddon.requestRemove()
    if silent is False:
        progressDialog = gui.IndeterminateProgressDialog(
            gui.mainFrame,
            # Translators: The title of the dialog presented while an Addon is being installed.
            _("Installing Add-on"),
            # Translators: The message displayed while an addon is being installed.
            _("Please wait while the add-on is being installed."))
        try:
            gui.ExecAndPump(addonHandler.installAddonBundle, bundle)
        except:
            logHandler.log.error("Error installing  addon bundle from %s" %
                                 addonPath,
                                 exc_info=True)
            progressDialog.done()
            del progressDialog
            # Translators: The message displayed when an error occurs when installing an add-on package.
            gui.messageBox(
                _("Failed to install add-on from %s") % (addon.name),
                # Translators: The title of a dialog presented when an error occurs.
                _("Error"),
                wx.OK | wx.ICON_ERROR)
            return False
        progressDialog.done()
        del progressDialog
    else:
        try:
            addonHandler.installAddonBundle(bundle)
        except:
            return False
    if closeAfter:
        wx.CallLater(1, core.restart)
    return True
Exemple #24
0
 def _downloadSuccess(self):
     self._stopped()
     try:
         try:
             bundle = addonHandler.AddonBundle(self.destPath)
         except:
             log.error(f"Error opening addon bundle from {self.destPath}",
                       exc_info=True)
             gui.messageBox(
                 # Translators: The message displayed when an error occurs
                 # when trying to update an add-on package due to package problems.
                 _("Cannot update {name} - missing file or invalid file format"
                   ).format(name=self.addonName),
                 translate("Error"),
                 wx.OK | wx.ICON_ERROR)
             self.continueUpdatingAddons()
             return
         # NVDA itself will check add-on compatibility range.
         # As such, the below fragment was borrowed from NVDA Core (credit: NV Access).
         from addonHandler import addonVersionCheck
         from gui import addonGui
         if not addonVersionCheck.hasAddonGotRequiredSupport(bundle):
             addonGui._showAddonRequiresNVDAUpdateDialog(
                 gui.mainFrame, bundle)
             self.continueUpdatingAddons()
             return
         elif not addonVersionCheck.isAddonTested(bundle):
             addonGui._showAddonTooOldDialog(gui.mainFrame, bundle)
             self.continueUpdatingAddons()
             return
         bundleName = bundle.manifest['name']
         isDisabled = False
         # Optimization (future): it is better to remove would-be add-ons all at once
         # instead of doing it each time a bundle is opened.
         for addon in addonHandler.getAvailableAddons():
             # Check for disabled state first.
             if bundleName == addon.manifest['name']:
                 if addon.isDisabled:
                     isDisabled = True
                 if not addon.isPendingRemove:
                     addon.requestRemove()
                 break
         progressDialog = gui.IndeterminateProgressDialog(
             gui.mainFrame,
             # Translators: The title of the dialog presented while an Addon is being updated.
             _("Updating {name}").format(name=self.addonName),
             # Translators: The message displayed while an addon is being updated.
             _("Please wait while the add-on is being updated."))
         try:
             gui.ExecAndPump(addonHandler.installAddonBundle, bundle)
         except:
             log.error(
                 f"Error installing  addon bundle from {self.destPath}",
                 exc_info=True)
             progressDialog.done()
             progressDialog.Hide()
             progressDialog.Destroy()
             gui.messageBox(
                 # Translators: The message displayed when an error occurs when installing an add-on package.
                 _("Failed to update {name} add-on").format(
                     name=self.addonName),
                 translate("Error"),
                 wx.OK | wx.ICON_ERROR)
             self.continueUpdatingAddons()
             return
         else:
             progressDialog.done()
             progressDialog.Hide()
             progressDialog.Destroy()
             _updatedAddons.append(bundleName)
             if isDisabled:
                 for addon in addonHandler.getAvailableAddons():
                     if bundleName == addon.manifest[
                             'name'] and addon.isPendingInstall:
                         addon.enable(False)
                         break
     finally:
         try:
             os.remove(self.destPath)
         except OSError:
             pass
     self.continueUpdatingAddons()
Exemple #25
0
def uninstallPreviousVersion():
	for addon in addonHandler.getAvailableAddons():
		if (
			addon.manifest["name"], addon.manifest["author"]) == previousNameAndAuthor:
			addon.requestRemove()
			break
Exemple #26
0
 def _downloadSuccess(self):
     self._stopped()
     # Emulate add-on update (don't prompt to install).
     from gui import addonGui
     closeAfter = addonGui.AddonsDialog._instance is None
     try:
         try:
             bundle = addonHandler.AddonBundle(self.destPath.decode("mbcs"))
         except:
             log.error("Error opening addon bundle from %s" % self.destPath,
                       exc_info=True)
             # Translators: The message displayed when an error occurs when opening an add-on package for adding.
             gui.messageBox(
                 _("Failed to open add-on package file at %s - missing file or invalid file format"
                   ) % self.destPath,
                 # Translators: The title of a dialog presented when an error occurs.
                 _("Error"),
                 wx.OK | wx.ICON_ERROR)
             return
         bundleName = bundle.manifest['name']
         for addon in addonHandler.getAvailableAddons():
             if not addon.isPendingRemove and bundleName == addon.manifest[
                     'name']:
                 addon.requestRemove()
                 break
         progressDialog = gui.IndeterminateProgressDialog(
             gui.mainFrame,
             # Translators: The title of the dialog presented while an Addon is being updated.
             _("Updating Add-on"),
             # Translators: The message displayed while an addon is being updated.
             _("Please wait while the add-on is being updated."))
         try:
             gui.ExecAndPump(addonHandler.installAddonBundle, bundle)
         except:
             log.error("Error installing  addon bundle from %s" %
                       self.destPath,
                       exc_info=True)
             if not closeAfter:
                 addonGui.AddonsDialog(gui.mainFrame).refreshAddonsList()
             progressDialog.done()
             del progressDialog
             # Translators: The message displayed when an error occurs when installing an add-on package.
             gui.messageBox(
                 _("Failed to update add-on  from %s") % self.destPath,
                 # Translators: The title of a dialog presented when an error occurs.
                 _("Error"),
                 wx.OK | wx.ICON_ERROR)
             return
         else:
             if not closeAfter:
                 addonGui.AddonsDialog(
                     gui.mainFrame).refreshAddonsList(activeIndex=-1)
             progressDialog.done()
             del progressDialog
     finally:
         try:
             os.remove(self.destPath)
         except OSError:
             pass
         if closeAfter:
             wx.CallLater(1, addonGui.AddonsDialog(gui.mainFrame).Close)
Exemple #27
0
 def getLocalAddon(self, storeAddon):
   for a in addonHandler.getAvailableAddons():
     if a.manifest['name'].upper() == storeAddon.name.upper():
       return a
   return None
Exemple #28
0
 def __getStores(self):
     for addon in addonHandler.getAvailableAddons():
         # Introduced in NVDA 2016.3
         if hasattr(addon, "isDisabled") and addon.isDisabled:
             continue
         yield self.addonStoreFactory(addon)
Exemple #29
0
def preferDevUpdates():
	# Returns a list of descriptions for add-ons that prefers development releases.
	return [addon.manifest["summary"] for addon in addonHandler.getAvailableAddons()
		if addon.name in addonUtils.updateState["devUpdates"]]
Exemple #30
0
# import the necessary modules.
import globalPluginHandler
import addonHandler
import gui
import globalVars
import wx
import shutil
import os
import pickle
from threading import Thread

# For translation
addonHandler.initTranslation()

# List containing all the add-ons
lista = list(addonHandler.getAvailableAddons())


# Creation of a GlobalPlugin class, derived from globalPluginHandler.GlobalPlugin.
class GlobalPlugin(globalPluginHandler.GlobalPlugin):
    # Creating the constructor of the newly created GlobalPlugin class.
    def __init__(self):
        # Call of the constructor of the parent class.
        super(GlobalPlugin, self).__init__()
        self._MainWindows = None

        if globalVars.appArgs.secure:
            return

        # Creation of our menu.
        self.toolsMenu = gui.mainFrame.sysTrayIcon.toolsMenu
    def _downloadSuccess(self):
        def getBundle():
            try:
                bundle = addonHandler.AddonBundle(self.destPath.decode("mbcs"))
            except AttributeError:
                bundle = addonHandler.AddonBundle(self.destPath)
            except Exception:
                log.error("Error opening addon bundle from %s" % self.destPath,
                          exc_info=True)
                # Translators: The message displayed when an error occurs
                # when trying to update an add-on package due to package problems.
                gui.messageBox(
                    # Translators: message to user
                    _("Cannot update {name} - missing file or invalid file format"
                      ).format(name=self.addonName),
                    makeAddonWindowTitle(NVDAString("Error")),
                    wx.OK | wx.ICON_ERROR)
                return None
            return bundle

        self._stopped()
        try:
            bundle = getBundle()
            if bundle is None:
                self.continueUpdatingAddons()
                return
            minimumNVDAVersion = bundle.manifest.get("minimumNVDAVersion",
                                                     None)
            lastTestedNVDAVersion = bundle.manifest.get(
                "lastTestedNVDAVersion", None)
            bundleName = bundle.manifest['name']
            if not checkCompatibility(bundleName, minimumNVDAVersion,
                                      lastTestedNVDAVersion):
                self.continueUpdatingAddons()
                return
            isDisabled = False
            # Optimization (future):
            # it is better to remove would-be add-ons all at once
            # instead of doing it each time a bundle is opened.
            for addon in addonHandler.getAvailableAddons():
                # Check for disabled state first.
                if bundleName == addon.manifest['name']:
                    if addon.isDisabled:
                        isDisabled = True
                    if not addon.isPendingRemove:
                        addon.requestRemove()
                    break
            progressDialog = gui.IndeterminateProgressDialog(
                gui.mainFrame,
                # Translators: The title of the dialog
                # presented while an Addon is being updated.
                makeAddonWindowTitle(_("Updating")),
                # Translators: The message displayed while an addon is being updated.
                _("Please wait while the add-on is being updated."))
            try:
                if self.autoUpdate:
                    extraAppArgs = globalVars.appArgsExtra if hasattr(
                        globalVars,
                        "appArgsExtra") else globalVars.unknownAppArgs
                    extraAppArgs.append("addon-auto-update")
                gui.ExecAndPump(addonHandler.installAddonBundle, bundle)
                if self.autoUpdate:
                    extraAppArgs.remove("addon-auto-update")
            except Exception:
                if self.autoUpdate:
                    extraAppArgs.remove("addon-auto-update")
                log.error("Error installing addon bundle from %s" %
                          self.destPath,
                          exc_info=True)
                progressDialog.done()
                gui.messageBox(
                    # Translators: The message displayed when an error occurs
                    # when installing an add-on package.
                    _("Failed to update {name} add-on").format(
                        name=self.addonName),
                    makeAddonWindowTitle(NVDAString("Error")),
                    wx.OK | wx.ICON_ERROR)
                self.continueUpdatingAddons()
                return
            else:
                progressDialog.done()
                self.addonHasBeenUpdated = True
                if isDisabled:
                    for addon in addonHandler.getAvailableAddons():
                        if bundleName == addon.manifest[
                                'name'] and addon.isPendingInstall:
                            addon.enable(False)
                            break
        finally:
            try:
                os.remove(self.destPath)
            except OSError:
                pass
            if self.addonHasBeenUpdated:
                if gui.messageBox(
                        NVDAString(
                            "Changes were made to add-ons. "
                            "You must restart NVDA for these changes to take effect. Would you like to restart now?"
                        ), NVDAString("Restart NVDA"),
                        wx.YES | wx.NO | wx.ICON_WARNING) == wx.YES:
                    wx.CallAfter(core.restart)
                return
        self.continueUpdatingAddons()
Exemple #32
0
def installAddon(parentWindow, addonPath):
    """ Installs the addon at path. Any error messages / warnings are presented to the user via a GUI message box.
	If attempting to install an addon that is pending removal, it will no longer be pending removal.
	:return True on success or False on failure.
	"""
    try:
        bundle = addonHandler.AddonBundle(addonPath)
    except:
        log.error("Error opening addon bundle from %s" % addonPath,
                  exc_info=True)
        gui.messageBox(
            # Translators: The message displayed when an error occurs when opening an add-on package for adding.
            _("Failed to open add-on package file at %s - missing file or invalid file format"
              ) % addonPath,
            # Translators: The title of a dialog presented when an error occurs.
            _("Error"),
            wx.OK | wx.ICON_ERROR)
        return False  # Exit early, can't install an invalid bundle

    if not addonVersionCheck.hasAddonGotRequiredSupport(bundle):
        _showAddonRequiresNVDAUpdateDialog(parentWindow, bundle)
        return False  # Exit early, addon does not have required support
    elif not addonVersionCheck.isAddonTested(bundle):
        _showAddonTooOldDialog(parentWindow, bundle)
        return False  # Exit early, addon is not up to date with the latest API version.
    elif wx.YES != _showConfirmAddonInstallDialog(parentWindow, bundle):
        return False  # Exit early, User changed their mind about installation.

    prevAddon = None
    for addon in addonHandler.getAvailableAddons():
        if not addon.isPendingRemove and bundle.name == addon.manifest['name']:
            prevAddon = addon
            break
    if prevAddon:
        summary = bundle.manifest["summary"]
        curVersion = prevAddon.manifest["version"]
        newVersion = bundle.manifest["version"]

        # Translators: A title for the dialog asking if the user wishes to update a previously installed
        # add-on with this one.
        messageBoxTitle = _("Add-on Installation")

        # Translators: A message asking if the user wishes to update an add-on with the same version
        # currently installed according to the version number.
        overwriteExistingAddonInstallationMessage = _(
            "You are about to install version {newVersion} of {summary}, which appears to be already installed. "
            "Would you still like to update?").format(summary=summary,
                                                      newVersion=newVersion)

        # Translators: A message asking if the user wishes to update a previously installed add-on with this one.
        updateAddonInstallationMessage = _(
            "A version of this add-on is already installed. "
            "Would you like to update {summary} version {curVersion} to version {newVersion}?"
        ).format(summary=summary, curVersion=curVersion, newVersion=newVersion)

        if gui.messageBox(
                overwriteExistingAddonInstallationMessage if curVersion
                == newVersion else updateAddonInstallationMessage,
                messageBoxTitle, wx.YES | wx.NO | wx.ICON_WARNING) != wx.YES:
            return False
        prevAddon.requestRemove()

    from contextlib import contextmanager

    @contextmanager
    def doneAndDestroy(window):
        try:
            yield window
        except:
            # pass on any exceptions
            raise
        finally:
            # but ensure that done and Destroy are called.
            window.done()
            window.Destroy()

    #  use a progress dialog so users know that something is happening.
    progressDialog = gui.IndeterminateProgressDialog(
        parentWindow,
        # Translators: The title of the dialog presented while an Addon is being installed.
        _("Installing Add-on"),
        # Translators: The message displayed while an addon is being installed.
        _("Please wait while the add-on is being installed."))

    try:
        # Use context manager to ensure that `done` and `Destroy` are called on the progress dialog afterwards
        with doneAndDestroy(progressDialog):
            gui.ExecAndPump(addonHandler.installAddonBundle, bundle)
            return True
    except:
        log.error("Error installing  addon bundle from %s" % addonPath,
                  exc_info=True)
        gui.messageBox(
            # Translators: The message displayed when an error occurs when installing an add-on package.
            _("Failed to install add-on from %s") % addonPath,
            # Translators: The title of a dialog presented when an error occurs.
            _("Error"),
            wx.OK | wx.ICON_ERROR)
    return False
Exemple #33
0
def onInstall():
    for addon in addonHandler.getAvailableAddons():
        if addon.manifest['name'] == "Unspoken Py3":
            askToRemove(addon)
            break