Some cleaning up, changelog

This commit is contained in:
Nichlas Severinsen 2019-06-07 09:00:03 +02:00
parent cee1c05820
commit 81a43952a8
6 changed files with 77 additions and 25 deletions

View file

@ -18,6 +18,7 @@
# You should have received a copy of the GNU General Public License
# along with libray. If not, see <https://www.gnu.org/licenses/>.
import os
import sys
import shutil
@ -38,12 +39,15 @@ GET_IRD_NET_LOC = 'http://jonnysp.bplaced.net/ird/'
# Utility functions
def to_int(data, order='big'):
def to_int(data, byteorder='big'):
"""Convert bytes to integer"""
if isinstance(data, bytes):
return int.from_bytes(data, order)
return int.from_bytes(data, byteorder)
def to_bytes(data):
"""Convert a string of HEX to bytes"""
if isinstance(data, str):
return bytes(bytearray.fromhex(data))
@ -53,12 +57,13 @@ ISO_IV = to_bytes("69474772af6fdab342743aefaa186287")
def filesize(filename):
"""Get size of a file in bytes from os.stat"""
return os.stat(filename).st_size
def read_seven_bit_encoded_int(fileobj, order):
# Read out an Int32 7 bits at a time. The high bit
# of the byte when on means to continue reading more bytes
"""Read an Int32, 7 bits at a time."""
# The highest bit of the byte when on, means to continue reading more bytes.
count = 0
shift = 0
byte = -1
@ -73,15 +78,18 @@ def read_seven_bit_encoded_int(fileobj, order):
def error(msg):
"""Print fatal error message and terminate"""
print('ERROR: %s' % msg)
sys.exit(1)
def warning(msg):
"""Print a warning message"""
print('WARNING: %s. Continuing regardless' % msg)
def download_ird(ird_name):
"""Download an .ird from GET_IRD_NET_LOC"""
ird_link = GET_IRD_NET_LOC + ird_name
r = requests.get(ird_link, stream=True)
@ -91,6 +99,7 @@ def download_ird(ird_name):
def ird_by_game_id(game_id):
"""Using a game_id, download the responding .ird from ALL_IRD_NET_LOC"""
gameid = game_id.replace('-','')
r = requests.get(ALL_IRD_NET_LOC, headers = {'User-Agent': 'Anonymous (You)' }, timeout=5)
soup = BeautifulSoup(r.text, "html.parser")
@ -113,6 +122,10 @@ def ird_by_game_id(game_id):
def decrypt(args):
"""Try to decrypt a given .iso using relevant .ird using args from argparse
If no .ird is given this will try to automatically download an .ird file with the encryption/decryption key for the given game .iso
"""
input_iso = iso.ISO(args)

View file

@ -24,6 +24,7 @@ import sys
import zlib
import shutil
try:
from libray import core
except ImportError:
@ -31,7 +32,19 @@ except ImportError:
class IRD:
"""Class for handling .ird files
Attributes:
version: IRD version number
game_id: PS3 game identifier
game_name: Name of PS3 game
update_version: PS3 firmware update version
game_version: PS3 game version
app_version: PS3 app version
region_count: How many encrypted regions are in the .iso
file_count: How many files are supposed to be in the .iso
data1: Encryption key
"""
ORDER = 'little'
TEMP_FILE = 'ird'
@ -39,8 +52,9 @@ class IRD:
def __init__(self, args):
"""IRD constructor using args from argparse"""
self.uncompress(args.ird) # TODO: Try/Except
self.uncompress(args.ird) # TODO: Try/Except?
self.size = core.filesize(self.TEMP_FILE)
with open(self.TEMP_FILE, 'rb') as input_ird:
@ -95,18 +109,9 @@ class IRD:
os.remove(self.TEMP_FILE)
def get_if_exists(self, input_ird):
starting_address = input_ird.tell()
length = core.read_seven_bit_encoded_int(input_ird, self.ORDER)
print(length)
if length:
return input_ird.read(length)
input_ird.seek(starting_address)
return None
def uncompress(self, filename):
"""Uncompress IRD. Assumes given .ird file is not compressed, but then tries to decompress it with zlib/gzfile if it was not uncompressed"""
uncompress = False
with open(filename, 'rb') as input_ird:
if input_ird.read(4) != self.MAGIC_STRING:
@ -120,8 +125,10 @@ class IRD:
shutil.copyfile(filename, self.TEMP_FILE)
def print_info(self):
# TODO: This could probably have been a __str__? Who cares?
"""Print some info about the IRD"""
print('Info from IRD:')
print('Version: %s' % self.version)
print('Game ID: %s' % self.game_id)

View file

@ -23,6 +23,7 @@ import sys
from tqdm import tqdm
from Crypto.Cipher import AES
try:
from libray import core
from libray import ird
@ -32,12 +33,23 @@ except ImportError:
class ISO:
"""Class for handling PS3 .iso files
Attributes:
size: Size of .iso in bytes
number_of_regions: Number of regions in the .iso
regions: List with info of every region
game_id: PS3 game id
ird: IRD object (see ird.py)
disc_key: data1 from .ird, encrypted
"""
NUM_INFO_BYTES = 4
def __init__(self, args):
"""ISO constructor using args from argparse"""
with open(args.iso, 'rb') as input_iso:
self.size = core.filesize(args.iso)
self.number_of_regions = core.to_int(input_iso.read(self.NUM_INFO_BYTES))
@ -69,6 +81,7 @@ class ISO:
def decrypt(self, args):
"""Decrypt self using args from argparse"""
print('Decrypting with disc key: %s' % self.disc_key.hex())
@ -110,7 +123,9 @@ class ISO:
pbar.close()
def read_regions(self, input_iso, filename):
"""List with information (start, end, whether it's encrypted) for every region"""
regions = []
encrypted = False
@ -128,6 +143,9 @@ class ISO:
def print_info(self):
# TODO: This could probably have been a __str__? Who cares?
"""Print some info about the ISO"""
print('Info from ISO:')
print('Regions: %s (%s)' % (self.number_of_regions, self.number_of_regions*2) )
for i, region in enumerate(self.regions):

View file

@ -22,6 +22,7 @@
import argparse
try:
from libray import core
except ImportError: