Exemplo n.º 1
0
    def analyze_data_chunk(self, chunk_size, wave_file, num_bytes, display):
        print_with_condition(
            display, "Reading data chunk (size: {}).".format(chunk_size))

        # TODO: static 44 does not work with JUNK chunk
        expected_data_subchunk_size = num_bytes - wave_file.tell() + 8
        if chunk_size != expected_data_subchunk_size:
            warning_with_condition(
                display,
                "Data subchunk size does not match file size. Should be {}, but is: {} (difference: {})"
                .format(expected_data_subchunk_size, chunk_size,
                        abs(expected_data_subchunk_size - chunk_size)))

        wave_file.seek(chunk_size - 8, 1)  # skip audio data

        return False
Exemplo n.º 2
0
    def analyze_aiff_header(self, path, display=True):

        found_error = False

        file_name = os.path.basename(path)
        num_bytes = os.path.getsize(path)

        print_with_condition(
            display,
            "Displaying AIFF File Header Data for File {}".format(file_name))
        print_with_condition(display, "Number of Bytes: {}".format(num_bytes))

        if num_bytes < 12:
            print_with_condition(
                display,
                "File is only {} bytes long and therefore can not contain an AIFF header."
                .format(num_bytes))
            found_error = True

        print_with_condition(display, "Reading AIFF Header...")
        with open(path, "rb") as aiff_file:
            form_chunk_bytes = aiff_file.read(12)

            #print_with_condition(display, "Header contains the following bytes (hexadecimal): {}".format(byte_string_to_hex(form_chunk_bytes)))

            if form_chunk_bytes[:4] != b"FORM":
                error_with_condition(
                    display,
                    "File does not start with 'FORM' and therefore does not contain a correct AIFF file header."
                    .format(file_name))
                found_error = True

            chunk_size_bytes = form_chunk_bytes[4:8]
            chunk_size = struct.unpack(">I", chunk_size_bytes)[0]

            print_with_condition(display, "Chunk Size: {}".format(chunk_size))

            expected_chunk_size = num_bytes - 8
            if chunk_size != expected_chunk_size:
                warning_with_condition(
                    display,
                    "Chunk size does not match file size. Should be equal to total number of bytes - 8 = {}, but was: {} (difference: {})"
                    .format(expected_chunk_size, chunk_size,
                            abs(expected_chunk_size - chunk_size)))

            format_name_bytes = form_chunk_bytes[8:12]
            if self.is_decodable(format_name_bytes):
                print_with_condition(
                    display,
                    "Format: {}".format(self.decode_bytes(format_name_bytes)))
            else:
                error_with_condition(
                    display,
                    "Invalid (non-printable) format name encountered (byte sequence {})."
                    .format(format_name_bytes))
                found_error = True

            is_aiff = format_name_bytes == b"AIFF"
            is_aifc = format_name_bytes == b"AIFC"
            if not (is_aifc or is_aiff):
                error_with_condition(
                    display, "Bytes 8-12 do neither contain 'AIFF' nor 'AIFC'")
                found_error = True

            while aiff_file.tell() < num_bytes:
                chunk_header = aiff_file.read(8)
                chunk_name_bytes = chunk_header[:4]

                if not self.is_decodable(chunk_name_bytes):
                    found_error = True
                    error_with_condition(
                        display,
                        "Invalid (non-printable) chunk name encountered (byte sequence {}). Aborting analysis."
                        .format(chunk_name_bytes))
                    break

                chunk_size_bytes = chunk_header[4:8]
                chunk_size = struct.unpack(">I", chunk_size_bytes)[0]

                current_position = aiff_file.tell()

                if self.analyze_aiff_chunk(chunk_name_bytes, chunk_size,
                                           aiff_file, display, is_aifc):
                    found_error = True

                if aiff_file.tell() == current_position:
                    print_error(
                        "No bytes consumed while processing '{}' chunk.".
                        format(self.decode_bytes(chunk_name_bytes)))
                    break

        return found_error
Exemplo n.º 3
0
    def analyze_wave_header(self, path, display=True):

        file_name = os.path.basename(path)
        num_bytes = os.path.getsize(path)

        print_with_condition(
            display,
            "Displaying WAVE File Header Data for File {}".format(file_name))
        print_with_condition(display, "Number of Bytes: {}".format(num_bytes))

        if num_bytes < 12:
            print_with_condition(
                display,
                "File is only {} bytes long and therefore can not contain a WAVE file header."
                .format(num_bytes))
            return True

        print_with_condition(display, "Reading WAVE Header...")

        with open(path, "rb") as wave_file:
            header_bytes = wave_file.read(12)

            if header_bytes[:4] != b"RIFF":
                error_with_condition(
                    display,
                    "File does not start with 'RIFF' and therefore does not contain a correct wave file header."
                    .format(file_name))
                return True

            chunk_size_bytes = header_bytes[4:8]
            chunk_size = struct.unpack("<I", chunk_size_bytes)[0]

            print_with_condition(display, "Chunk Size: {}".format(chunk_size))

            expected_chunk_size = num_bytes - 8
            if chunk_size != expected_chunk_size:
                warning_with_condition(
                    display,
                    "Chunk size does not match file size. Should be equal to total number of bytes - 8 = {}, but was: {} (difference: {})"
                    .format(expected_chunk_size, chunk_size,
                            abs(expected_chunk_size - chunk_size)))

            if header_bytes[8:12] != b"WAVE":
                error_with_condition(display,
                                     "Bytes 8-12 do not contain 'WAVE'")
                return True

            while wave_file.tell() < num_bytes:
                chunk_header = wave_file.read(8)
                chunk_name_bytes = chunk_header[:4]

                if not self.is_decodable(chunk_name_bytes):
                    error_with_condition(
                        display,
                        "Invalid (non-printable) chunk name encountered (byte sequence {}). Aborting analysis."
                        .format(chunk_name_bytes))
                    return True

                chunk_size_bytes = chunk_header[4:8]
                chunk_size = struct.unpack("<I", chunk_size_bytes)[0]

                current_position = wave_file.tell()

                if self.analyze_wave_chunk(chunk_name_bytes, chunk_size,
                                           wave_file, num_bytes, display):
                    return True

                if wave_file.tell() == current_position:
                    raise RuntimeError(
                        "No bytes consumed while processing '{}' chunk.".
                        format(self.decode_bytes(chunk_name_bytes)))

                if chunk_name_bytes == b'data':
                    # skip remaining parts of the file in case the data chunk is not correct
                    # otherwise this may lead to follow-up errors
                    break

        return False