Created
September 5, 2024 11:13
-
-
Save Subtixx/c02c359f7fbbcacb071a33b7e1bbd8da to your computer and use it in GitHub Desktop.
Simple Jailbroken PS4 FTP Savegame Backup utility
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os | |
import ftputil | |
import ftplib | |
import hashlib | |
save_dir = '/user/home/USERID/savedata/' | |
ftp_host = '192.168.1.200' | |
ftp_port = 2121 | |
ftp_user = 'username' | |
ftp_password = 'password' | |
class Playstation4(ftplib.FTP): | |
def __init__(self, host, userid, password, port): | |
"""Act like ftplib.FTP's constructor but connect to another port.""" | |
ftplib.FTP.__init__(self) | |
self.connect(host, port) | |
self.login(userid, password) | |
self.use_list_a_option = True | |
class Playstation4BackupUtility: | |
ftp_host = None | |
crcs = {} | |
def __init__(self): | |
self.ftp_host = ftputil.FTPHost(ftp_host, ftp_user, ftp_password, port=ftp_port, session_factory=Playstation4) | |
self.load_crcs() | |
os.makedirs('backup', exist_ok=True) | |
def __del__(self): | |
self.ftp_host.close() | |
def start(self): | |
self.recurse_download(save_dir, 'backup') | |
self.save_crcs() | |
def load_crcs(self): | |
if not os.path.exists('crcs.txt'): | |
self.save_crcs() | |
with open('crcs.txt') as f: | |
for line in f: | |
self.crc, path = line.strip().split('\t') | |
self.crcs[path] = crc | |
def save_crcs(self): | |
with open('crcs.txt', 'w') as f: | |
for path, crc in self.crcs.items(): | |
f.write(f'{crc}\t{path}\n') | |
def recurse_download(self, remote_dir, local_dir): | |
for name in self.ftp_host.listdir(remote_dir): | |
remote_path = self.ftp_host.path.join(remote_dir, name) | |
local_path = os.path.join(local_dir, name) | |
if self.ftp_host.path.isdir(remote_path): | |
os.makedirs(local_path, exist_ok=True) | |
self.recurse_download(remote_path, local_path) | |
else: | |
if os.path.exists(local_path): | |
local_crc = self.calculate_local_crc(local_path) | |
remote_crc = self.calculate_remote_crc(remote_path) | |
if local_crc == remote_crc: | |
print(f'Skipping {remote_path} because it is up to date') | |
continue | |
print(f'Downloading {remote_path} to {local_path}') | |
self.ftp_host.download(remote_path, local_path) | |
def calculate_local_crc(self, path): | |
with open(path, 'rb') as f: | |
self.crcs[path] = hashlib.md5(f.read()).hexdigest() | |
return self.crcs[path] | |
def calculate_remote_crc(self, path): | |
with self.ftp_host.open(path, 'rb') as f: | |
return hashlib.md5(f.read()).hexdigest() | |
if __name__ == '__main__': | |
backup = Playstation4BackupUtility() | |
backup.start() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment