[PAR2PARSER] Fix Par2Parser class
authorIra W. Snyder <devel@irasnyder.com>
Thu, 28 Dec 2006 05:09:36 +0000 (21:09 -0800)
committerIra W. Snyder <devel@irasnyder.com>
Thu, 28 Dec 2006 05:09:36 +0000 (21:09 -0800)
The original class was registering every PAR2 file as corrupt, even though
the old parser handled them fine. This reverts to the old parser, fixing
the problem.

Signed-off-by: Ira W. Snyder <devel@irasnyder.com>
Par2Parser.py
rarslave.py

index 804848f..c57d1e6 100644 (file)
@@ -7,10 +7,7 @@
 # This was stolen from cfv (see http://cfv.sourceforge.net/ for a copy)
 ################################################################################
 
 # This was stolen from cfv (see http://cfv.sourceforge.net/ for a copy)
 ################################################################################
 
-import struct, errno, os
-
-def get_full_filename (dir, file):
-       return os.path.abspath (os.path.expanduser (os.path.join (dir, file)))
+import struct, errno, os, md5
 
 def chompnulls(line):
        p = line.find('\0')
 
 def chompnulls(line):
        p = line.find('\0')
@@ -21,13 +18,19 @@ def get_protected_files (dir, filename):
        """Get all of the filenames that are protected by the par2
        file given as the filename"""
 
        """Get all of the filenames that are protected by the par2
        file given as the filename"""
 
-       full_filename = get_full_filename (dir, filename)
+       assert os.path.isdir (dir) # MUST be a valid directory
+       assert os.path.isfile (os.path.join (dir, filename))
+
+       full_filename = os.path.join (dir, filename)
 
        try:
                file = open(full_filename, 'rb')
        except:
                print 'Could not open %s' % (full_filename, )
 
        try:
                file = open(full_filename, 'rb')
        except:
                print 'Could not open %s' % (full_filename, )
-               raise EnvironmentError, (errno.EINVAL, 'can not open par2 file')
+               return []
+
+       # We always want to do crc checks
+       docrcchecks = True
 
        pkt_header_fmt = '< 8s Q 16s 16s 16s'
        pkt_header_size = struct.calcsize(pkt_header_fmt)
 
        pkt_header_fmt = '< 8s Q 16s 16s 16s'
        pkt_header_size = struct.calcsize(pkt_header_fmt)
@@ -41,16 +44,26 @@ def get_protected_files (dir, filename):
        filenames = []
 
        while 1:
        filenames = []
 
        while 1:
-               try:
-                       d = file.read(pkt_header_size)
-               except OverflowError:
-                       raise EnvironmentError, (errno.EINVAL, 'bad par2 file')
+               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 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)
+
+                       if control_md5.digest() != pkt_md5:
+                               raise EnvironmentError, (errno.EINVAL, \
+                                       "corrupt par2 file - bad packet hash")
+
                if pkt_type == 'PAR 2.0\0FileDesc':
                if pkt_type == 'PAR 2.0\0FileDesc':
+                       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])
 
                        file_id, file_md5, file_md5_16k, file_size = \
                                struct.unpack(file_pkt_fmt, d[:file_pkt_size])
 
@@ -60,10 +73,8 @@ def get_protected_files (dir, filename):
                                filenames.append(filename)
 
                elif pkt_type == "PAR 2.0\0Main\0\0\0\0":
                                filenames.append(filename)
 
                elif pkt_type == "PAR 2.0\0Main\0\0\0\0":
-                       try:
+                       if not docrcchecks:
                                d = file.read(pkt_len - pkt_header_size)
                                d = file.read(pkt_len - pkt_header_size)
-                       except OverflowError:
-                               raise EnvironmentError, (errno.EINVAL, 'corrupt par2 file')
 
                        if expected_file_ids is None:
                                expected_file_ids = []
 
                        if expected_file_ids is None:
                                expected_file_ids = []
@@ -74,10 +85,8 @@ def get_protected_files (dir, filename):
                                        expected_file_ids.append(d[i:i+16])
 
                else:
                                        expected_file_ids.append(d[i:i+16])
 
                else:
-                       try:
+                       if not docrcchecks:
                                file.seek(pkt_len - pkt_header_size, 1)
                                file.seek(pkt_len - pkt_header_size, 1)
-                       except OverflowError, IOError:
-                               raise EnvironmentError, (errno.EINVAL, 'corrupt par2 file')
 
        if expected_file_ids is None:
                raise EnvironmentError, (errno.EINVAL, \
 
        if expected_file_ids is None:
                raise EnvironmentError, (errno.EINVAL, \
index ce6e6ec..f02f356 100644 (file)
@@ -210,7 +210,7 @@ def find_likely_files (dir, p2file):
        name_matches = [f for f in os.listdir (dir) if regex.match (f)]
        try:
                parsed_matches = Par2Parser.get_protected_files (dir, p2file)
        name_matches = [f for f in os.listdir (dir) if regex.match (f)]
        try:
                parsed_matches = Par2Parser.get_protected_files (dir, p2file)
-       except EnvironmentError:
+       except EnvironmentError, OSError, OverflowError:
                parsed_matches = []
                logger.addMessage ('Bad par2 file: %s' % p2file, RarslaveLogger.MessageType.Fatal)
 
                parsed_matches = []
                logger.addMessage ('Bad par2 file: %s' % p2file, RarslaveLogger.MessageType.Fatal)
 
@@ -283,7 +283,7 @@ def find_extraction_heads (dir, files):
                        try:
                                prot_files = Par2Parser.get_protected_files (dir, f)
                                done = True
                        try:
                                prot_files = Par2Parser.get_protected_files (dir, f)
                                done = True
-                       except EnvironmentError:
+                       except EnvironmentError, OverflowError, OSError:
                                logger.addMessage ('Error parsing PAR2 file: %s', f)
                                continue
 
                                logger.addMessage ('Error parsing PAR2 file: %s', f)
                                continue