mirror of
https://github.com/NinjaCheetah/WiiPy.git
synced 2025-04-26 13:21:01 -04:00
Add checks to nus content subcommand, and improve error handling
This commit is contained in:
parent
8599c43c2d
commit
183498025a
@ -142,28 +142,52 @@ def handle_nus_content(args):
|
|||||||
tid = args.tid
|
tid = args.tid
|
||||||
cid = args.cid
|
cid = args.cid
|
||||||
version = args.version
|
version = args.version
|
||||||
|
out = args.output
|
||||||
if args.decrypt:
|
if args.decrypt:
|
||||||
decrypt_content = True
|
decrypt_content = True
|
||||||
else:
|
else:
|
||||||
decrypt_content = False
|
decrypt_content = False
|
||||||
|
|
||||||
content_id = int.from_bytes(binascii.unhexlify(cid))
|
# Only accepting the 000000xx format because it's the one that would be most commonly known, rather than using the
|
||||||
|
# actual integer that the hex Content ID translates to.
|
||||||
|
try:
|
||||||
|
content_id = int.from_bytes(binascii.unhexlify(cid))
|
||||||
|
except binascii.Error:
|
||||||
|
print("Invalid Content ID! Content ID must be in format \"000000xx\"!")
|
||||||
|
return
|
||||||
|
|
||||||
content_file_name = hex(content_id)[2:]
|
# Use the supplied output path if one was specified, otherwise generate one using the Content ID.
|
||||||
while len(content_file_name) < 8:
|
if out is None:
|
||||||
content_file_name = "0" + content_file_name
|
content_file_name = hex(content_id)[2:]
|
||||||
|
while len(content_file_name) < 8:
|
||||||
|
content_file_name = "0" + content_file_name
|
||||||
|
output_path = pathlib.Path(content_file_name)
|
||||||
|
else:
|
||||||
|
output_path = pathlib.Path(out)
|
||||||
|
|
||||||
content_data = libWiiPy.title.download_content(tid, content_id)
|
# Try to download the content, and catch the ValueError libWiiPy will throw if it can't be found.
|
||||||
|
print("Downloading content with Content ID " + cid + "...")
|
||||||
|
try:
|
||||||
|
content_data = libWiiPy.title.download_content(tid, content_id)
|
||||||
|
except ValueError:
|
||||||
|
print("The Title ID or Content ID you specified could not be found!")
|
||||||
|
return
|
||||||
|
|
||||||
if decrypt_content is True:
|
if decrypt_content is True:
|
||||||
content_file_name = content_file_name + ".app"
|
# Ensure that a version was supplied, because we need the matching TMD for decryption to work.
|
||||||
|
if version is None:
|
||||||
|
print("You must specify the version that the requested content belongs to for decryption!")
|
||||||
|
return
|
||||||
|
|
||||||
|
output_path = output_path.with_suffix(".app")
|
||||||
tmd = libWiiPy.title.TMD()
|
tmd = libWiiPy.title.TMD()
|
||||||
tmd.load(libWiiPy.title.download_tmd(tid, version))
|
tmd.load(libWiiPy.title.download_tmd(tid, version))
|
||||||
|
# Try to get a Ticket for the title, if a common one is available.
|
||||||
try:
|
try:
|
||||||
ticket = libWiiPy.title.Ticket()
|
ticket = libWiiPy.title.Ticket()
|
||||||
ticket.load(libWiiPy.title.download_ticket(tid))
|
ticket.load(libWiiPy.title.download_ticket(tid, wiiu_endpoint=True))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
print(" - No Ticket is available!")
|
print("No Ticket is available! Content cannot be decrypted!")
|
||||||
return
|
return
|
||||||
|
|
||||||
content_hash = 'gggggggggggggggggggggggggggggggggggggggg'
|
content_hash = 'gggggggggggggggggggggggggggggggggggggggg'
|
||||||
@ -175,17 +199,25 @@ def handle_nus_content(args):
|
|||||||
content_size = record.content_size
|
content_size = record.content_size
|
||||||
content_index = record.index
|
content_index = record.index
|
||||||
|
|
||||||
|
# If the default hash never changed, then a content record matching the downloaded content couldn't be found,
|
||||||
|
# which most likely means that the wrong version was specified.
|
||||||
|
if content_hash == 'gggggggggggggggggggggggggggggggggggggggg':
|
||||||
|
print("Content was not found in the TMD from the specified version! Content cannot be decrypted!")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Manually decrypt the content and verify its hash, which is what libWiiPy's get_content() methods do. We just
|
||||||
|
# can't really use that here because that require setting up a lot more of the title than is necessary.
|
||||||
content_dec = libWiiPy.title.decrypt_content(content_data, ticket.get_title_key(), content_index, content_size)
|
content_dec = libWiiPy.title.decrypt_content(content_data, ticket.get_title_key(), content_index, content_size)
|
||||||
content_dec_hash = hashlib.sha1(content_dec).hexdigest()
|
content_dec_hash = hashlib.sha1(content_dec).hexdigest()
|
||||||
if content_hash != content_dec_hash:
|
if content_hash != content_dec_hash:
|
||||||
raise ValueError("The decrypted content provided does not match the record at the provided index. \n"
|
raise ValueError("The decrypted content provided does not match the record at the provided index. \n"
|
||||||
"Expected hash is: {}\n".format(content_hash) +
|
"Expected hash is: {}\n".format(content_hash) +
|
||||||
"Actual hash is: {}".format(content_dec_hash))
|
"Actual hash is: {}".format(content_dec_hash))
|
||||||
file = open(content_file_name, "wb")
|
file = open(output_path, "wb")
|
||||||
file.write(content_dec)
|
file.write(content_dec)
|
||||||
file.close()
|
file.close()
|
||||||
else:
|
else:
|
||||||
file = open(content_file_name, "wb")
|
file = open(output_path, "wb")
|
||||||
file.write(content_data)
|
file.write(content_data)
|
||||||
file.close()
|
file.close()
|
||||||
|
|
||||||
|
2
wiipy.py
2
wiipy.py
@ -57,6 +57,8 @@ if __name__ == "__main__":
|
|||||||
help="Content ID to download (in \"000000xx\" format)")
|
help="Content ID to download (in \"000000xx\" format)")
|
||||||
nus_content_parser.add_argument("-v", "--version", metavar="VERSION", type=int,
|
nus_content_parser.add_argument("-v", "--version", metavar="VERSION", type=int,
|
||||||
help="version this content belongs to (required for decryption)")
|
help="version this content belongs to (required for decryption)")
|
||||||
|
nus_content_parser.add_argument("-o", "--output", metavar="OUT", type=str,
|
||||||
|
help="path to download the content to (optional)")
|
||||||
nus_content_parser.add_argument("-d", "--decrypt", action="store_true", help="decrypt this content")
|
nus_content_parser.add_argument("-d", "--decrypt", action="store_true", help="decrypt this content")
|
||||||
|
|
||||||
# Argument parser for the U8 subcommand.
|
# Argument parser for the U8 subcommand.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user