core.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. # -*- coding: utf8 -*-
  2. # libray - Libre Blu-Ray PS3 ISO Tool
  3. # Copyright (C) 2018 Nichlas Severinsen
  4. #
  5. # This file is part of libray.
  6. #
  7. # libray is free software: you can redistribute it and/or modify
  8. # it under the terms of the GNU General Public License as published by
  9. # the Free Software Foundation, either version 3 of the License, or
  10. # (at your option) any later version.
  11. #
  12. # libray is distributed in the hope that it will be useful,
  13. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. # GNU General Public License for more details.
  16. #
  17. # You should have received a copy of the GNU General Public License
  18. # along with libray. If not, see <https://www.gnu.org/licenses/>.
  19. import os
  20. import sys
  21. import shutil
  22. import requests
  23. from bs4 import BeautifulSoup
  24. try:
  25. from libray import iso
  26. except ImportError:
  27. import iso
  28. # Magic numbers / Constant variables
  29. SECTOR = 2048
  30. ALL_IRD_NET_LOC = 'http://jonnysp.bplaced.net/data.php'
  31. GET_IRD_NET_LOC = 'http://jonnysp.bplaced.net/ird/'
  32. # Utility functions
  33. def to_int(data, byteorder='big'):
  34. """Convert bytes to integer"""
  35. if isinstance(data, bytes):
  36. return int.from_bytes(data, byteorder)
  37. def to_bytes(data):
  38. """Convert a string of HEX to bytes"""
  39. if isinstance(data, str):
  40. return bytes(bytearray.fromhex(data))
  41. ISO_SECRET = to_bytes("380bcf0b53455b3c7817ab4fa3ba90ed")
  42. ISO_IV = to_bytes("69474772af6fdab342743aefaa186287")
  43. def filesize(filename):
  44. """Get size of a file in bytes from os.stat"""
  45. try:
  46. return open(filename, "rb").seek(0, 2)
  47. except:
  48. return os.stat(filename).st_size
  49. def read_seven_bit_encoded_int(fileobj, order):
  50. """Read an Int32, 7 bits at a time."""
  51. # The highest bit of the byte when on, means to continue reading more bytes.
  52. count = 0
  53. shift = 0
  54. byte = -1
  55. while (byte & 0x80) != 0 or byte == -1:
  56. # Check for a corrupted stream. Read a max of 5 bytes.
  57. if shift == (5 * 7):
  58. raise ValueError
  59. byte = to_int(fileobj.read(1), order)
  60. count |= (byte & 0x7F) << shift
  61. shift += 7
  62. return count
  63. def error(msg):
  64. """Print fatal error message and terminate"""
  65. print('ERROR: %s' % msg)
  66. sys.exit(1)
  67. def warning(msg):
  68. """Print a warning message"""
  69. print('WARNING: %s. Continuing regardless' % msg)
  70. def download_ird(ird_name):
  71. """Download an .ird from GET_IRD_NET_LOC"""
  72. ird_link = GET_IRD_NET_LOC + ird_name
  73. r = requests.get(ird_link, stream=True)
  74. with open(ird_name, 'wb') as ird_file:
  75. r.raw.decode_content = True
  76. shutil.copyfileobj(r.raw, ird_file)
  77. def ird_by_game_id(game_id):
  78. """Using a game_id, download the responding .ird from ALL_IRD_NET_LOC"""
  79. gameid = game_id.replace('-','')
  80. r = requests.get(ALL_IRD_NET_LOC, headers = {'User-Agent': 'Anonymous (You)' }, timeout=5)
  81. soup = BeautifulSoup(r.text, "html.parser")
  82. ird_name = False
  83. for elem in soup.find_all("a"):
  84. url = elem.get('href').split('/')[-1].replace('\\"','')
  85. if gameid in url:
  86. ird_name = url
  87. if not ird_name:
  88. error("Unable to download IRD, couldn't find link")
  89. download_ird(ird_name)
  90. return(ird_name)
  91. # Main functions
  92. def decrypt(args):
  93. """Try to decrypt a given .iso using relevant .ird using args from argparse
  94. If no .ird is given this will try to automatically download an .ird file with the encryption/decryption key for the given game .iso
  95. """
  96. input_iso = iso.ISO(args)
  97. input_iso.decrypt(args)