mirror of
https://github.com/leminlimez/Nugget.git
synced 2025-04-08 04:23:05 +08:00
read individual files rather than all at once
This commit is contained in:
@@ -23,19 +23,35 @@ class BackupFile:
|
|||||||
@dataclass
|
@dataclass
|
||||||
class ConcreteFile(BackupFile):
|
class ConcreteFile(BackupFile):
|
||||||
contents: bytes
|
contents: bytes
|
||||||
|
src_path: Optional[str] = None
|
||||||
owner: int = 0
|
owner: int = 0
|
||||||
group: int = 0
|
group: int = 0
|
||||||
inode: Optional[int] = None
|
inode: Optional[int] = None
|
||||||
mode: _FileMode = DEFAULT
|
mode: _FileMode = DEFAULT
|
||||||
|
|
||||||
|
hash: bytes = None
|
||||||
|
size: int = None
|
||||||
|
|
||||||
|
def read_contents(self) -> bytes:
|
||||||
|
contents = self.contents
|
||||||
|
if self.contents == None:
|
||||||
|
with open(self.src_path, "rb") as in_file:
|
||||||
|
contents = in_file.read()
|
||||||
|
# prepopulate hash and size
|
||||||
|
self.hash = sha1(contents).digest()
|
||||||
|
self.size = len(contents)
|
||||||
|
return contents
|
||||||
|
|
||||||
def to_record(self) -> mbdb.MbdbRecord:
|
def to_record(self) -> mbdb.MbdbRecord:
|
||||||
if self.inode is None:
|
if self.inode is None:
|
||||||
self.inode = int.from_bytes(randbytes(8), "big")
|
self.inode = int.from_bytes(randbytes(8), "big")
|
||||||
|
if self.hash == None or self.size == None:
|
||||||
|
self.read_contents()
|
||||||
return mbdb.MbdbRecord(
|
return mbdb.MbdbRecord(
|
||||||
domain=self.domain,
|
domain=self.domain,
|
||||||
filename=self.path,
|
filename=self.path,
|
||||||
link="",
|
link="",
|
||||||
hash=sha1(self.contents).digest(),
|
hash=self.hash,
|
||||||
key=b"",
|
key=b"",
|
||||||
mode=self.mode | _FileMode.S_IFREG,
|
mode=self.mode | _FileMode.S_IFREG,
|
||||||
#unknown2=0,
|
#unknown2=0,
|
||||||
@@ -46,7 +62,7 @@ class ConcreteFile(BackupFile):
|
|||||||
mtime=int(datetime.now().timestamp()),
|
mtime=int(datetime.now().timestamp()),
|
||||||
atime=int(datetime.now().timestamp()),
|
atime=int(datetime.now().timestamp()),
|
||||||
ctime=int(datetime.now().timestamp()),
|
ctime=int(datetime.now().timestamp()),
|
||||||
size=len(self.contents),
|
size=self.size,
|
||||||
flags=4,
|
flags=4,
|
||||||
properties=[]
|
properties=[]
|
||||||
)
|
)
|
||||||
@@ -126,7 +142,7 @@ class Backup:
|
|||||||
if isinstance(file, ConcreteFile):
|
if isinstance(file, ConcreteFile):
|
||||||
#print("Writing", file.path, "to", directory / sha1((file.domain + "-" + file.path).encode()).digest().hex())
|
#print("Writing", file.path, "to", directory / sha1((file.domain + "-" + file.path).encode()).digest().hex())
|
||||||
with open(directory / sha1((file.domain + "-" + file.path).encode()).digest().hex(), "wb") as f:
|
with open(directory / sha1((file.domain + "-" + file.path).encode()).digest().hex(), "wb") as f:
|
||||||
f.write(file.contents)
|
f.write(file.read_contents())
|
||||||
|
|
||||||
with open(directory / "Manifest.mbdb", "wb") as f:
|
with open(directory / "Manifest.mbdb", "wb") as f:
|
||||||
f.write(self.generate_manifest_db().to_bytes())
|
f.write(self.generate_manifest_db().to_bytes())
|
||||||
|
|||||||
@@ -4,8 +4,9 @@ from pymobiledevice3.services.installation_proxy import InstallationProxyService
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
class FileToRestore:
|
class FileToRestore:
|
||||||
def __init__(self, contents: str, restore_path: str, domain: str = None, owner: int = 501, group: int = 501):
|
def __init__(self, contents: str, restore_path: str, contents_path: str = None, domain: str = None, owner: int = 501, group: int = 501):
|
||||||
self.contents = contents
|
self.contents = contents
|
||||||
|
self.contents_path = contents_path
|
||||||
self.restore_path = restore_path
|
self.restore_path = restore_path
|
||||||
self.domain = domain
|
self.domain = domain
|
||||||
self.owner = owner
|
self.owner = owner
|
||||||
@@ -75,7 +76,8 @@ def concat_regular_file(file: FileToRestore, files_list: list[FileToRestore], la
|
|||||||
file.domain,
|
file.domain,
|
||||||
owner=file.owner,
|
owner=file.owner,
|
||||||
group=file.group,
|
group=file.group,
|
||||||
contents=file.contents
|
contents=file.contents,
|
||||||
|
src_path=file.contents_path
|
||||||
))
|
))
|
||||||
return new_last_domain, full_path
|
return new_last_domain, full_path
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import traceback
|
import traceback
|
||||||
import plistlib
|
import plistlib
|
||||||
from pathlib import Path
|
from tempfile import TemporaryDirectory
|
||||||
|
|
||||||
from PySide6.QtWidgets import QMessageBox
|
from PySide6.QtWidgets import QMessageBox
|
||||||
from PySide6.QtCore import QSettings
|
from PySide6.QtCore import QSettings
|
||||||
@@ -304,6 +304,7 @@ class DeviceManager:
|
|||||||
# create the restore file list
|
# create the restore file list
|
||||||
files_to_restore: dict[FileToRestore] = [
|
files_to_restore: dict[FileToRestore] = [
|
||||||
]
|
]
|
||||||
|
tmp_pb_dir = None # temporary directory for unzipping pb files
|
||||||
|
|
||||||
# set the plist keys
|
# set the plist keys
|
||||||
if not resetting:
|
if not resetting:
|
||||||
@@ -325,7 +326,8 @@ class DeviceManager:
|
|||||||
if tweak.enabled and tweak.file_location.value.startswith("/var/mobile/"):
|
if tweak.enabled and tweak.file_location.value.startswith("/var/mobile/"):
|
||||||
uses_domains = True
|
uses_domains = True
|
||||||
elif isinstance(tweak, PosterboardTweak):
|
elif isinstance(tweak, PosterboardTweak):
|
||||||
tweak.apply_tweak(files_to_restore=files_to_restore)
|
tmp_pb_dir = TemporaryDirectory()
|
||||||
|
tweak.apply_tweak(files_to_restore=files_to_restore, output_dir=tmp_pb_dir.name)
|
||||||
else:
|
else:
|
||||||
if gestalt_plist != None:
|
if gestalt_plist != None:
|
||||||
gestalt_plist = tweak.apply_tweak(gestalt_plist)
|
gestalt_plist = tweak.apply_tweak(gestalt_plist)
|
||||||
@@ -413,12 +415,16 @@ class DeviceManager:
|
|||||||
update_label("Restoring to device...")
|
update_label("Restoring to device...")
|
||||||
try:
|
try:
|
||||||
restore_files(files=files_to_restore, reboot=self.auto_reboot, lockdown_client=self.data_singleton.current_device.ld)
|
restore_files(files=files_to_restore, reboot=self.auto_reboot, lockdown_client=self.data_singleton.current_device.ld)
|
||||||
|
if tmp_pb_dir != None:
|
||||||
|
tmp_pb_dir.cleanup()
|
||||||
msg = "Your device will now restart."
|
msg = "Your device will now restart."
|
||||||
if not self.auto_reboot:
|
if not self.auto_reboot:
|
||||||
msg = "Please restart your device to see changes."
|
msg = "Please restart your device to see changes."
|
||||||
QMessageBox.information(None, "Success!", "All done! " + msg)
|
QMessageBox.information(None, "Success!", "All done! " + msg)
|
||||||
update_label("Success!")
|
update_label("Success!")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
if tmp_pb_dir != None:
|
||||||
|
tmp_pb_dir.cleanup()
|
||||||
show_apply_error(e, update_label)
|
show_apply_error(e, update_label)
|
||||||
|
|
||||||
## RESETTING MOBILE GESTALT
|
## RESETTING MOBILE GESTALT
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ from tweaks.custom_gestalt_tweaks import CustomGestaltTweaks, ValueTypeStrings
|
|||||||
from tweaks.daemons_tweak import Daemon
|
from tweaks.daemons_tweak import Daemon
|
||||||
|
|
||||||
App_Version = "5.0"
|
App_Version = "5.0"
|
||||||
App_Build = 1
|
App_Build = 2
|
||||||
|
|
||||||
class Page(Enum):
|
class Page(Enum):
|
||||||
Home = 0
|
Home = 0
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ from .tweak_classes import Tweak
|
|||||||
from Sparserestore.restore import FileToRestore
|
from Sparserestore.restore import FileToRestore
|
||||||
import os
|
import os
|
||||||
import zipfile
|
import zipfile
|
||||||
from tempfile import TemporaryDirectory
|
|
||||||
|
|
||||||
class PosterboardTweak(Tweak):
|
class PosterboardTweak(Tweak):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@@ -13,19 +12,18 @@ class PosterboardTweak(Tweak):
|
|||||||
|
|
||||||
def recursive_add(self, files_to_restore: list[FileToRestore], curr_path: str, restore_path: str = "", isAdding: bool = False):
|
def recursive_add(self, files_to_restore: list[FileToRestore], curr_path: str, restore_path: str = "", isAdding: bool = False):
|
||||||
for folder in sorted(os.listdir(curr_path)):
|
for folder in sorted(os.listdir(curr_path)):
|
||||||
if folder == ".DS_Store" or folder == "__MACOSX":
|
if folder.startswith('.') or folder == "__MACOSX":
|
||||||
continue
|
continue
|
||||||
if isAdding:
|
if isAdding:
|
||||||
# if file then add it, otherwise recursively call again
|
# if file then add it, otherwise recursively call again
|
||||||
if os.path.isfile(os.path.join(curr_path, folder)):
|
if os.path.isfile(os.path.join(curr_path, folder)):
|
||||||
try:
|
try:
|
||||||
with open(os.path.join(curr_path, folder), "rb") as in_file:
|
files_to_restore.append(FileToRestore(
|
||||||
contents = in_file.read()
|
contents=None,
|
||||||
files_to_restore.append(FileToRestore(
|
contents_path=os.path.join(curr_path, folder),
|
||||||
contents=contents,
|
restore_path=f"{restore_path}/{folder}",
|
||||||
restore_path=f"{restore_path}/{folder}",
|
domain=f"AppDomain-{self.bundle_id}"
|
||||||
domain=f"AppDomain-{self.bundle_id}"
|
))
|
||||||
))
|
|
||||||
except IOError:
|
except IOError:
|
||||||
print(f"Failed to open file: {folder}") # TODO: Add QDebug equivalent
|
print(f"Failed to open file: {folder}") # TODO: Add QDebug equivalent
|
||||||
else:
|
else:
|
||||||
@@ -38,7 +36,7 @@ class PosterboardTweak(Tweak):
|
|||||||
else:
|
else:
|
||||||
self.recursive_add(files_to_restore, os.path.join(curr_path, folder), isAdding=False)
|
self.recursive_add(files_to_restore, os.path.join(curr_path, folder), isAdding=False)
|
||||||
|
|
||||||
def apply_tweak(self, files_to_restore: list[FileToRestore]):
|
def apply_tweak(self, files_to_restore: list[FileToRestore], output_dir: str):
|
||||||
# unzip the file
|
# unzip the file
|
||||||
if not self.enabled:
|
if not self.enabled:
|
||||||
return
|
return
|
||||||
@@ -52,8 +50,7 @@ class PosterboardTweak(Tweak):
|
|||||||
return
|
return
|
||||||
elif self.zip_path == None:
|
elif self.zip_path == None:
|
||||||
return
|
return
|
||||||
with TemporaryDirectory() as output_dir:
|
with zipfile.ZipFile(self.zip_path, 'r') as zip_ref:
|
||||||
with zipfile.ZipFile(self.zip_path, 'r') as zip_ref:
|
zip_ref.extractall(output_dir)
|
||||||
zip_ref.extractall(output_dir)
|
# add the files
|
||||||
# add the files
|
self.recursive_add(files_to_restore, curr_path=output_dir)
|
||||||
self.recursive_add(files_to_restore, curr_path=output_dir)
|
|
||||||
Reference in New Issue
Block a user