fix(core,security): safe update extraction and async bulk vk actions
This commit is contained in:
@@ -9,6 +9,18 @@ import zipfile
|
||||
|
||||
|
||||
class AutoUpdateService:
|
||||
@staticmethod
|
||||
def _safe_extract_zip(archive, destination_dir):
|
||||
destination_real = os.path.realpath(destination_dir)
|
||||
for member in archive.infolist():
|
||||
member_name = member.filename or ""
|
||||
if not member_name:
|
||||
continue
|
||||
target_path = os.path.realpath(os.path.join(destination_dir, member_name))
|
||||
if target_path != destination_real and not target_path.startswith(destination_real + os.sep):
|
||||
raise RuntimeError(f"Unsafe path in update archive: {member_name}")
|
||||
archive.extractall(destination_dir)
|
||||
|
||||
@staticmethod
|
||||
def download_update_archive(download_url, destination_path):
|
||||
request = urllib.request.Request(
|
||||
@@ -215,6 +227,6 @@ class AutoUpdateService:
|
||||
cls.verify_update_checksum(zip_path, checksum_url, download_name)
|
||||
os.makedirs(unpack_dir, exist_ok=True)
|
||||
with zipfile.ZipFile(zip_path, "r") as archive:
|
||||
archive.extractall(unpack_dir)
|
||||
cls._safe_extract_zip(archive, unpack_dir)
|
||||
source_dir = cls.locate_extracted_root(unpack_dir)
|
||||
return work_dir, source_dir
|
||||
|
||||
@@ -5,7 +5,42 @@ import urllib.error
|
||||
import urllib.request
|
||||
from urllib.parse import urlparse
|
||||
|
||||
from PySide6.QtCore import QObject, Signal
|
||||
try:
|
||||
from PySide6.QtCore import QObject, Signal
|
||||
except Exception:
|
||||
class _FallbackBoundSignal:
|
||||
def __init__(self):
|
||||
self._callbacks = []
|
||||
|
||||
def connect(self, callback):
|
||||
if callback is not None:
|
||||
self._callbacks.append(callback)
|
||||
|
||||
def emit(self, *args, **kwargs):
|
||||
for callback in list(self._callbacks):
|
||||
callback(*args, **kwargs)
|
||||
|
||||
class _FallbackSignalDescriptor:
|
||||
def __init__(self):
|
||||
self._storage_name = ""
|
||||
|
||||
def __set_name__(self, owner, name):
|
||||
self._storage_name = f"__fallback_signal_{name}"
|
||||
|
||||
def __get__(self, instance, owner):
|
||||
if instance is None:
|
||||
return self
|
||||
signal = instance.__dict__.get(self._storage_name)
|
||||
if signal is None:
|
||||
signal = _FallbackBoundSignal()
|
||||
instance.__dict__[self._storage_name] = signal
|
||||
return signal
|
||||
|
||||
class QObject:
|
||||
pass
|
||||
|
||||
def Signal(*_args, **_kwargs):
|
||||
return _FallbackSignalDescriptor()
|
||||
|
||||
|
||||
def _version_key(version_text):
|
||||
|
||||
Reference in New Issue
Block a user