diff --git a/CHANGELOG.md b/CHANGELOG.md index 36fa5d6..a829944 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,11 +3,15 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). +## [0.0.2] - 2019-07-07 +### Added/Fixed +- Decrypting block devices directly (eg. cd/dvd/bd drive) instead of .iso files. For example `-i /dev/sg0` or `-i /dev/sr0`. + ## [0.0.1] - 2019-05-16 ### Added - Manually loading .ird files with `-k` (for 'key') - Automatic downloading of .ird files when not given (currently only from jonnysp.bplaced.net) -- Successful decryption of a PS3 .iso with .ird when path to encrypted .iso is given with `-i` +- Successful decryption of a PS3 .iso with .ird when path to encrypted .iso is given with `-i` - Manually specify output .iso file with `-o` (default is 'output.iso') - Verbosity with `-v` - Helptext with `-h` (automatically generated by argparse) diff --git a/README.md b/README.md index 70ec3ac..71cc9c8 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ LibRay: A portmanteau of Libre and Blu-Ray -LibRay aims to be a Libre (FLOSS) Python application for unencrypting, +LibRay aims to be a Libre (FLOSS) Python application for unencrypting, extracting, repackaging, and encrypting PS3 ISOs. A hackable, crossplatform, alternative to ISOTools and ISO-Rebuilder. @@ -29,7 +29,7 @@ Note: You will need Python 3, so you might want to use `python3` and `pip3` inst For Arch or Arch-based GNU/Linux distributions there's an option to [install libray from the AUR](https://aur.archlinux.org/packages/libray-git/) (Arch User Repository). -You will need an [AUR helper](https://wiki.archlinux.org/index.php/AUR_helpers) (of which there are many). +You will need an [AUR helper](https://wiki.archlinux.org/index.php/AUR_helpers) (of which there are many). Then you will need to run the appropriate install command for that AUR helper using `libray-git` as package name. @@ -78,7 +78,9 @@ Then, if you want to feed it into RPCS3 just extract the contents of the .ISO: 7z x nfs_ps3_decrypted.iso ``` -And move the resulting folders into the appropriate folder for RPCS3. +And move the resulting folders into the appropriate folder for RPCS3: + +- Linux: /home/username/.config/rpcs3/dev_hdd0/disc/ ## License @@ -86,7 +88,7 @@ This project is Free and Open Source Software; FOSS, licensed under the GNU Gene ## Error! -Help! I get +Help! I get > ImportError: No module named Crypto.Cipher @@ -104,7 +106,7 @@ sudo pip install pycrypto ## Development -[see also](http://www.psdevwiki.com/ps3/Bluray_disc#Encryption) ([archive.fo](https://archive.fo/hN1E6)) +[see also](http://www.psdevwiki.com/ps3/Bluray_disc#Encryption) ([archive.fo](https://archive.fo/hN1E6)) [7bit encoded int / RLE / CLP](https://github.com/Microsoft/referencesource/blob/master/mscorlib/system/io/binaryreader.cs#L582-L600) @@ -112,9 +114,9 @@ clp = compressed length prefix ## Todo -- Docstrings - Extract ISO (currently doable with `7z x output.iso` - Repackage (unextract) and reencrypt iso? - Test .irds with version < 9 - Custom command to backup all irds available -- pypi +- Unit tests + diff --git a/libray/core.py b/libray/core.py index 703ff5f..8536f29 100644 --- a/libray/core.py +++ b/libray/core.py @@ -21,6 +21,7 @@ import os import sys +import stat import shutil import requests from bs4 import BeautifulSoup @@ -56,12 +57,18 @@ ISO_SECRET = to_bytes("380bcf0b53455b3c7817ab4fa3ba90ed") ISO_IV = to_bytes("69474772af6fdab342743aefaa186287") -def filesize(filename): - """Get size of a file in bytes from os.stat""" - try: - return open(filename, "rb").seek(0, 2) - except: - return os.stat(filename).st_size +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) + + # Otherwise, it's hopefully file + + return pathstat.st_size def read_seven_bit_encoded_int(fileobj, order): @@ -126,7 +133,7 @@ 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 """ diff --git a/libray/ird.py b/libray/ird.py index c14226d..f7d07bd 100644 --- a/libray/ird.py +++ b/libray/ird.py @@ -48,7 +48,7 @@ class IRD: ORDER = 'little' TEMP_FILE = 'ird' - MAGIC_STRING = b"3IRD" + MAGIC_STRING = b'3IRD' def __init__(self, args): @@ -56,10 +56,14 @@ class IRD: self.uncompress(args.ird) # TODO: Try/Except? - self.size = core.filesize(self.TEMP_FILE) + self.size = core.size(self.TEMP_FILE) + + if not self.size: + core.error('IRD file is empty!') + with open(self.TEMP_FILE, 'rb') as input_ird: if input_ird.read(4) != self.MAGIC_STRING: - core.error("Either not an IRD file, corruped IRD file, or unknown IRD format") + core.error('Either not an IRD file, corruped IRD file, or unknown IRD format') self.version = core.to_int(input_ird.read(1), self.ORDER) self.game_id = input_ird.read(9) diff --git a/libray/iso.py b/libray/iso.py index 630aab4..d899a63 100644 --- a/libray/iso.py +++ b/libray/iso.py @@ -34,7 +34,7 @@ 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 @@ -50,8 +50,12 @@ class ISO: def __init__(self, args): """ISO constructor using args from argparse""" + self.size = core.size(args.iso) + + if not self.size: + core.error('looks like ISO file/mount is empty?') + 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)) unused_bytes = input_iso.read(self.NUM_INFO_BYTES) # Yeah, I don't know either. @@ -97,7 +101,7 @@ class ISO: while input_iso.tell() < region['end']: data = input_iso.read(core.SECTOR) if not data: - core.warning("Trying to read past the end of the file") + core.warning('Trying to read past the end of the file') break pbar.update(1) output_iso.write(data) @@ -112,7 +116,7 @@ class ISO: data = input_iso.read(core.SECTOR) if not data: - core.warning("Trying to read past the end of the file") + core.warning('Trying to read past the end of the file') break pbar.update(1) diff --git a/libray/libray.py b/libray/libray.py index bf4ecf8..08d62d0 100755 --- a/libray/libray.py +++ b/libray/libray.py @@ -33,11 +33,11 @@ if __name__ == '__main__': # Parse command line arguments with argpase parser = argparse.ArgumentParser(description='A Libre (FLOSS) Python application for unencrypting, extracting, repackaging, and encrypting PS3 ISOs') - parser.add_argument('-v', '--verbose', help="Increase verbosity", action='count') - parser.add_argument('-o', '--output', dest='output', type=str, help="Output filename", default='output.iso') - parser.add_argument('-k', '--ird', dest='ird', type=str, help="Path to .ird file", default="") + parser.add_argument('-v', '--verbose', help='Increase verbosity', action='count') + parser.add_argument('-o', '--output', dest='output', type=str, help='Output filename', default='output.iso') + parser.add_argument('-k', '--ird', dest='ird', type=str, help='Path to .ird file', default='') required = parser.add_argument_group('required arguments') - required.add_argument('-i', '--iso', dest='iso', type=str, help="Path to .iso file", required=True) + required.add_argument('-i', '--iso', dest='iso', type=str, help='Path to .iso file', required=True) args = parser.parse_args() core.decrypt(args) diff --git a/requirements.txt b/requirements.txt index 7e7c1c6..827414e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -tqdm==4.23.4 +tqdm==4.32.2 pycrypto==2.6.1 -requests==2.19.1 -beautifulsoup4==4.6.0 +requests==2.22.0 +beautifulsoup4==4.7.1 diff --git a/setup.py b/setup.py index ceca187..3cf453e 100755 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ from setuptools import setup setup( name="libray", - version="0.0.1", + version="0.0.2", description='A Libre (FLOSS) Python application for unencrypting, extracting, repackaging, and encrypting PS3 ISOs', author="Nichlas Severinsen", author_email="ns@nsz.no", @@ -13,9 +13,9 @@ setup( packages=['libray'], scripts=['libray/libray'], install_requires=[ - 'tqdm==4.23.4', + 'tqdm==4.32.2', 'pycrypto==2.6.1', - 'requests==2.19.1', - 'beautifulsoup4==4.6.0', + 'requests==2.22.0', + 'beautifulsoup4==4.7.1', ], -) \ No newline at end of file +)