From cbdd2e87affa06910c64c1923da031277d2a30ec Mon Sep 17 00:00:00 2001 From: Thorsten Date: Wed, 23 Dec 2020 00:36:53 +0100 Subject: [PATCH 1/2] Improve get_lib_version, use as check --- lib/inputstreamhelper/__init__.py | 29 ++++++++-------------- lib/inputstreamhelper/widevine/widevine.py | 29 ++++++++++++++++++++-- 2 files changed, 37 insertions(+), 21 deletions(-) diff --git a/lib/inputstreamhelper/__init__.py b/lib/inputstreamhelper/__init__.py index fec532ae..3ce3bef5 100644 --- a/lib/inputstreamhelper/__init__.py +++ b/lib/inputstreamhelper/__init__.py @@ -11,7 +11,7 @@ set_setting, set_setting_bool, textviewer, translate_path, yesno_dialog) from .utils import arch, http_download, remove_tree, run_cmd, store, system_os, temp_path, unzip from .widevine.arm import install_widevine_arm, unmount -from .widevine.widevine import (backup_path, has_widevinecdm, ia_cdm_path, install_cdm_from_backup, latest_widevine_version, +from .widevine.widevine import (backup_path, has_widevinecdm, get_lib_version, ia_cdm_path, install_cdm_from_backup, latest_widevine_version, load_widevine_config, missing_widevine_libs, widevine_config_path, widevine_eula, widevinecdm_path) from .unicodes import compat_path @@ -96,18 +96,6 @@ def _inputstream_version(self): from .unicodes import to_unicode return to_unicode(addon.getAddonInfo('version')) - @staticmethod - def _get_lib_version(path): - if not path or not exists(path): - return '(Not found)' - import re - with open(compat_path(path), 'rb') as library: - match = re.search(br'[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+', library.read()) - if not match: - return '(Undetected)' - from .unicodes import to_unicode - return to_unicode(match.group(0)) - def _has_inputstream(self): """Checks if selected InputStream add-on is installed.""" data = jsonrpc(method='Addons.GetAddonDetails', params=dict(addonid=self.inputstream_addon)) @@ -195,7 +183,9 @@ def install_and_finish(self, progress, version): """Installs the cdm from backup and runs checks""" progress.update(97, message=localize(30049)) # Installing Widevine CDM - install_cdm_from_backup(version) + if not install_cdm_from_backup(version): + progress.close() + return False progress.update(98, message=localize(30050)) # Finishing if has_widevinecdm(): @@ -432,7 +422,7 @@ def info_dialog(self): wv_updated = strftime('%Y-%m-%d %H:%M', localtime(get_setting_float('last_modified', 0.0))) else: wv_updated = 'Never' - text += localize(30821, version=self._get_lib_version(widevinecdm_path()), date=wv_updated) + '\n' + text += localize(30821, version=get_lib_version(widevinecdm_path()), date=wv_updated) + '\n' if arch() in ('arm', 'arm64'): # Chrome OS version wv_cfg = load_widevine_config() if wv_cfg: @@ -451,7 +441,8 @@ def info_dialog(self): log(2, '\n{info}'.format(info=kodi_to_ascii(text))) textviewer(localize(30901), text) - def rollback_libwv(self): + @staticmethod + def rollback_libwv(): """Rollback lib to a version specified by the user""" bpath = backup_path() versions = listdir(bpath) @@ -470,7 +461,7 @@ def rollback_libwv(self): show_versions = [] for version in versions: - lib_version = self._get_lib_version(os.path.join(bpath, version, config.WIDEVINE_CDM_FILENAME[system_os()])) + lib_version = get_lib_version(os.path.join(bpath, version, config.WIDEVINE_CDM_FILENAME[system_os()])) show_versions.append('{} ({})'.format(lib_version, version)) if not show_versions: @@ -480,7 +471,7 @@ def rollback_libwv(self): version = select_dialog(localize(30057), show_versions) if version != -1: log(0, 'Rollback to version {version}', version=versions[version]) - install_cdm_from_backup(versions[version]) - notification(localize(30037), localize(30051)) # Success! Widevine successfully installed. + if install_cdm_from_backup(versions[version]): + notification(localize(30037), localize(30051)) # Success! Widevine successfully installed. return diff --git a/lib/inputstreamhelper/widevine/widevine.py b/lib/inputstreamhelper/widevine/widevine.py index 8f61bf5d..33318887 100644 --- a/lib/inputstreamhelper/widevine/widevine.py +++ b/lib/inputstreamhelper/widevine/widevine.py @@ -14,16 +14,23 @@ def install_cdm_from_backup(version): """Copies files from specified backup version to cdm dir""" - filenames = listdir(os.path.join(backup_path(), version)) + backup_dir = os.path.join(backup_path(), version) + + if not get_lib_version(os.path.join(backup_dir, config.WIDEVINE_CDM_FILENAME[system_os()])): + log(4, 'lib version check failed! Aborting installation.') + ok_dialog(localize(30004), localize(30005)) # Error during install, please report + return False + filenames = listdir(backup_dir) for filename in filenames: - backup_fpath = os.path.join(backup_path(), version, filename) + backup_fpath = os.path.join(backup_dir, filename) install_fpath = os.path.join(ia_cdm_path(), filename) hardlink(backup_fpath, install_fpath) log(0, 'Installed CDM version {version} from backup', version=version) set_setting('last_modified', time()) remove_old_backups(backup_path()) + return True def widevine_eula(): @@ -118,6 +125,24 @@ def ia_cdm_path(): return cdm_path +def get_lib_version(path): + """ + Determines version of the Widevine library. + Returns empty string if not possible, which might indicate a problematic file/arch mismatch, so this can be used as a check. + """ + from ctypes import CDLL, c_char_p + + lib_version = '' + try: + lib = CDLL(compat_path(path)) + lib.GetCdmVersion.restype = c_char_p + lib_version = to_unicode(lib.GetCdmVersion()) + except (OSError, AttributeError) as exc: + log(4, 'Failed to determine lib version: ' + str(exc)) + + return lib_version + + def missing_widevine_libs(): """Parses ldd output of libwidevinecdm.so and displays dialog if any depending libraries are missing.""" if system_os() != 'Linux': # this should only be needed for linux From bc92eba823f7abd73d06298b137bad22be50da8d Mon Sep 17 00:00:00 2001 From: mediaminister Date: Mon, 28 Dec 2020 20:08:02 +0100 Subject: [PATCH 2/2] Close lib to avoid segmentation fault --- lib/inputstreamhelper/widevine/widevine.py | 4 +++- tests/xbmcvfs.py | 8 ++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/inputstreamhelper/widevine/widevine.py b/lib/inputstreamhelper/widevine/widevine.py index 33318887..6819fc88 100644 --- a/lib/inputstreamhelper/widevine/widevine.py +++ b/lib/inputstreamhelper/widevine/widevine.py @@ -127,16 +127,18 @@ def ia_cdm_path(): def get_lib_version(path): """ - Determines version of the Widevine library. + Determines version of the Widevine library using the python ctypes module. Returns empty string if not possible, which might indicate a problematic file/arch mismatch, so this can be used as a check. """ from ctypes import CDLL, c_char_p + from _ctypes import dlclose lib_version = '' try: lib = CDLL(compat_path(path)) lib.GetCdmVersion.restype = c_char_p lib_version = to_unicode(lib.GetCdmVersion()) + dlclose(lib._handle) # pylint: disable=protected-access except (OSError, AttributeError) as exc: log(4, 'Failed to determine lib version: ' + str(exc)) diff --git a/tests/xbmcvfs.py b/tests/xbmcvfs.py index cbb65edd..7f2e7bbe 100644 --- a/tests/xbmcvfs.py +++ b/tests/xbmcvfs.py @@ -87,11 +87,11 @@ def rmdir(path): def translatePath(path): """A stub implementation of the xbmc translatePath() function""" if path.startswith('special://home'): - return path.replace('special://home', os.path.join(os.getcwd(), 'tests/')) + return path.replace('special://home', os.path.join(os.getcwd(), 'tests')) if path.startswith('special://masterprofile'): - return path.replace('special://masterprofile', os.path.join(os.getcwd(), 'tests/userdata/')) + return path.replace('special://masterprofile', os.path.join(os.getcwd(), 'tests/userdata')) if path.startswith('special://profile'): - return path.replace('special://profile', os.path.join(os.getcwd(), 'tests/userdata/')) + return path.replace('special://profile', os.path.join(os.getcwd(), 'tests/userdata')) if path.startswith('special://userdata'): - return path.replace('special://userdata', os.path.join(os.getcwd(), 'tests/userdata/')) + return path.replace('special://userdata', os.path.join(os.getcwd(), 'tests/userdata')) return path