X-Git-Url: https://www.irasnyder.com/gitweb/?p=rarslave2.git;a=blobdiff_plain;f=Par2Parser.py;h=69401012ae83253da61a18528b2cb2324e3d0d51;hp=c57d1e6d5b5f552ca566457dc82c64228d7c88e2;hb=390d46a48947106283cf21883a28e7cddc665c12;hpb=25c6aa2221fa7294e253ca540aa1eb58f447459d diff --git a/Par2Parser.py b/Par2Parser.py index c57d1e6..6940101 100644 --- a/Par2Parser.py +++ b/Par2Parser.py @@ -43,60 +43,67 @@ def get_protected_files (dir, filename): expected_file_ids = None filenames = [] - while 1: - d = file.read(pkt_header_size) - if not d: - break - - magic, pkt_len, pkt_md5, set_id, pkt_type = struct.unpack(pkt_header_fmt, d) - - if docrcchecks: - control_md5 = md5.new() - control_md5.update(d[0x20:]) - d = file.read(pkt_len - pkt_header_size) - control_md5.update(d) + # This try is here to ensure that we close the open file before + # returning. Since this code was (pretty much) borrowed verbatim + # from the cfv project, I didn't want to refactor it to make file + # closing more sane, so I just used a try / finally clause. + try: + while 1: + d = file.read(pkt_header_size) + if not d: + break - if control_md5.digest() != pkt_md5: - raise EnvironmentError, (errno.EINVAL, \ - "corrupt par2 file - bad packet hash") + magic, pkt_len, pkt_md5, set_id, pkt_type = struct.unpack(pkt_header_fmt, d) - if pkt_type == 'PAR 2.0\0FileDesc': - if not docrcchecks: + if docrcchecks: + control_md5 = md5.new() + control_md5.update(d[0x20:]) d = file.read(pkt_len - pkt_header_size) + control_md5.update(d) - file_id, file_md5, file_md5_16k, file_size = \ - struct.unpack(file_pkt_fmt, d[:file_pkt_size]) + if control_md5.digest() != pkt_md5: + raise EnvironmentError, (errno.EINVAL, \ + "corrupt par2 file - bad packet hash") - if seen_file_ids.get(file_id) is None: - seen_file_ids[file_id] = 1 - filename = chompnulls(d[file_pkt_size:]) - filenames.append(filename) + if pkt_type == 'PAR 2.0\0FileDesc': + if not docrcchecks: + d = file.read(pkt_len - pkt_header_size) - elif pkt_type == "PAR 2.0\0Main\0\0\0\0": - if not docrcchecks: - d = file.read(pkt_len - pkt_header_size) + file_id, file_md5, file_md5_16k, file_size = \ + struct.unpack(file_pkt_fmt, d[:file_pkt_size]) + + if seen_file_ids.get(file_id) is None: + seen_file_ids[file_id] = 1 + filename = chompnulls(d[file_pkt_size:]) + filenames.append(filename) - if expected_file_ids is None: - expected_file_ids = [] - slice_size, num_files = struct.unpack(main_pkt_fmt, d[:main_pkt_size]) - num_nonrecovery = (len(d)-main_pkt_size)/16 - num_files + elif pkt_type == "PAR 2.0\0Main\0\0\0\0": + if not docrcchecks: + d = file.read(pkt_len - pkt_header_size) - for i in range(main_pkt_size,main_pkt_size+(num_files+num_nonrecovery)*16,16): - expected_file_ids.append(d[i:i+16]) + if expected_file_ids is None: + expected_file_ids = [] + slice_size, num_files = struct.unpack(main_pkt_fmt, d[:main_pkt_size]) + num_nonrecovery = (len(d)-main_pkt_size)/16 - num_files - else: - if not docrcchecks: - file.seek(pkt_len - pkt_header_size, 1) + for i in range(main_pkt_size,main_pkt_size+(num_files+num_nonrecovery)*16,16): + expected_file_ids.append(d[i:i+16]) - if expected_file_ids is None: - raise EnvironmentError, (errno.EINVAL, \ - "corrupt or unsupported par2 file - no main packet found") + else: + if not docrcchecks: + file.seek(pkt_len - pkt_header_size, 1) - for id in expected_file_ids: - if not seen_file_ids.has_key(id): + if expected_file_ids is None: raise EnvironmentError, (errno.EINVAL, \ - "corrupt or unsupported par2 file - " \ - "expected file description packet not found") + "corrupt or unsupported par2 file - no main packet found") + + for id in expected_file_ids: + if not seen_file_ids.has_key(id): + raise EnvironmentError, (errno.EINVAL, \ + "corrupt or unsupported par2 file - " \ + "expected file description packet not found") + finally: + file.close () return filenames