LibRay/libray/core.py

154 lines
3.8 KiB
Python
Raw Normal View History

# -*- coding: utf8 -*-
# libray - Libre Blu-Ray PS3 ISO Tool
2019-08-01 08:42:14 +02:00
# Copyright © 2018 - 2019 Nichlas Severinsen
2019-05-16 10:37:28 +02:00
#
# This file is part of libray.
2019-05-16 10:37:28 +02:00
#
# libray is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
2019-05-16 10:37:28 +02:00
#
# libray is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
2019-05-16 10:37:28 +02:00
#
# You should have received a copy of the GNU General Public License
# along with libray. If not, see <https://www.gnu.org/licenses/>.
2019-06-07 09:00:03 +02:00
import os
import sys
import stat
2018-07-07 19:03:47 +02:00
import shutil
import requests
from bs4 import BeautifulSoup
2018-07-07 11:12:05 +02:00
try:
from libray import iso
except ImportError:
import iso
# Magic numbers / Constant variables
SECTOR = 2048
ALL_IRD_NET_LOC = 'http://jonnysp.bplaced.net/data.php'
GET_IRD_NET_LOC = 'http://jonnysp.bplaced.net/ird/'
# Utility functions
2019-06-07 09:00:03 +02:00
def to_int(data, byteorder='big'):
"""Convert bytes to integer"""
if isinstance(data, bytes):
2019-06-07 09:00:03 +02:00
return int.from_bytes(data, byteorder)
def to_bytes(data):
2019-06-07 09:00:03 +02:00
"""Convert a string of HEX to bytes"""
if isinstance(data, str):
return bytes(bytearray.fromhex(data))
ISO_SECRET = to_bytes("380bcf0b53455b3c7817ab4fa3ba90ed")
ISO_IV = to_bytes("69474772af6fdab342743aefaa186287")
def size(path):
"""Get size of a file or block device in bytes"""
pathstat = os.stat(path)
# Check if it's a block device
if stat.S_ISBLK(pathstat.st_mode):
return open(path, 'rb').seek(0, os.SEEK_END)
2019-11-03 14:49:24 +01:00
# Otherwise, it's hopefully a file
return pathstat.st_size
def read_seven_bit_encoded_int(fileobj, order):
2019-06-07 09:00:03 +02:00
"""Read an Int32, 7 bits at a time."""
2019-11-03 14:49:24 +01:00
# The highest bit of the byte, when on, means to continue reading more bytes.
count = 0
shift = 0
byte = -1
while (byte & 0x80) != 0 or byte == -1:
# Check for a corrupted stream. Read a max of 5 bytes.
if shift == (5 * 7):
raise ValueError
byte = to_int(fileobj.read(1), order)
count |= (byte & 0x7F) << shift
shift += 7
return count
def error(msg):
2019-06-07 09:00:03 +02:00
"""Print fatal error message and terminate"""
print('ERROR: %s' % msg)
sys.exit(1)
2018-07-07 19:03:47 +02:00
def warning(msg):
2019-06-07 09:00:03 +02:00
"""Print a warning message"""
2020-08-03 19:52:46 +02:00
print('WARNING: %s. Continuing regardless.' % msg)
2018-07-07 19:03:47 +02:00
def download_ird(ird_name):
2019-06-07 09:00:03 +02:00
"""Download an .ird from GET_IRD_NET_LOC"""
2020-08-03 19:52:46 +02:00
# Check if file already exists and skip if it does
if os.path.exists(ird_name):
return
ird_link = GET_IRD_NET_LOC + ird_name
r = requests.get(ird_link, stream=True)
with open(ird_name, 'wb') as ird_file:
r.raw.decode_content = True
shutil.copyfileobj(r.raw, ird_file)
def ird_by_game_id(game_id):
2019-06-07 09:00:03 +02:00
"""Using a game_id, download the responding .ird from ALL_IRD_NET_LOC"""
gameid = game_id.replace('-','')
2020-08-03 19:52:46 +02:00
try:
r = requests.get(ALL_IRD_NET_LOC, headers = {'User-Agent': 'Anonymous (You)' }, timeout=5)
except requests.exceptions.ReadTimeout:
core.error('Server timed out, fix your connection or manually specify a key/ird.')
soup = BeautifulSoup(r.text, "html.parser")
ird_name = False
for elem in soup.find_all("a"):
url = elem.get('href').split('/')[-1].replace('\\"','')
if gameid in url:
ird_name = url
if not ird_name:
2020-08-03 19:52:46 +02:00
error("Unable to download IRD, couldn't find link. You could specify the decryption key with -d if you have it.")
download_ird(ird_name)
return(ird_name)
2019-05-16 10:37:28 +02:00
# Main functions
2018-07-07 19:03:47 +02:00
def decrypt(args):
2019-06-07 09:00:03 +02:00
"""Try to decrypt a given .iso using relevant .ird using args from argparse
2019-06-07 09:00:03 +02:00
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)
input_iso.decrypt(args)
2019-05-16 10:37:28 +02:00