Skip to content

Instantly share code, notes, and snippets.

@Subtixx
Created September 5, 2024 11:13
Show Gist options
  • Save Subtixx/c02c359f7fbbcacb071a33b7e1bbd8da to your computer and use it in GitHub Desktop.
Save Subtixx/c02c359f7fbbcacb071a33b7e1bbd8da to your computer and use it in GitHub Desktop.
Simple Jailbroken PS4 FTP Savegame Backup utility
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