Пример #1
0
 def test_cffolder_add_file(self):
     reserve = {'cbCFHeader': 0, 'cbCFFolder': 0, 'cbCFData': 0}
     cfheader = CFHEADER(flags=0, reserve=reserve)
     cffolder = CFFOLDER(cfheader=cfheader)
     cffile = CFFILE(cffolder=cffolder, filename="trav.txt")
     cffolder.add_file(cffile)
     self.assertEquals(1, cfheader.cFiles)
Пример #2
0
    def _update_prev_cabfile(self, filename):
        # Only execute if there is more than one cab in the set
        if len(self.cab_files) < 2:
            return

        # Get the previous cab and the current cab
        prev_cab = self.cab_files[-2]
        current_cab = self.cab_files[-1]

        if prev_cab.cfheader.flags & CFHEADER.cfhdrNEXT_CABINET != CFHEADER.cfhdrNEXT_CABINET:
            # We only need to update the szCabinetNext, szDiskNext and Flags once!

            # Set the NEXT_CABINET flag in the cfheader
            prev_cab.cfheader.flags |= CFHEADER.cfhdrNEXT_CABINET
            # Update strings in the cfheader indicating there is a next cab
            prev_cab.cfheader.szCabinetNext = CABFile.get_null_ended_string(
                current_cab.cab_filename)
            prev_cab.cfheader.szDiskNext = CABFile.get_null_ended_string(
                "continued")

            # Set IFolder on CFFILE to ifoldCONTINUED_TO_NEXT
            folder_list = prev_cab.cfheader.cffolder_list
            for folder in folder_list:
                for _cffile in folder.cffile_list:
                    if _cffile.szName == CABFile.get_null_ended_string(
                            filename):
                        if _cffile.iFolder in CFFILE.get_iFolder_options():
                            _cffile.iFolder |= CFFILE.ifoldCONTINUED_TO_NEXT
                        else:
                            _cffile.iFolder = CFFILE.ifoldCONTINUED_TO_NEXT

        # Update offsets - We need to do this every time
        # because we've just added some strings into the structure
        prev_cab.update_fields()
Пример #3
0
    def _update_prev_cabfile(self, filename):
        # Only execute if there is more than one cab in the set
        if len(self.cab_files) < 2:
            return

        # Get the previous cab and the current cab
        prev_cab = self.cab_files[-2]
        current_cab = self.cab_files[-1]

        if prev_cab.cfheader.flags & CFHEADER.cfhdrNEXT_CABINET != CFHEADER.cfhdrNEXT_CABINET:
        # We only need to update the szCabinetNext, szDiskNext and Flags once!

            # Set the NEXT_CABINET flag in the cfheader
            prev_cab.cfheader.flags |= CFHEADER.cfhdrNEXT_CABINET
            # Update strings in the cfheader indicating there is a next cab
            prev_cab.cfheader.szCabinetNext = CABFile.get_null_ended_string(current_cab.cab_filename)
            prev_cab.cfheader.szDiskNext = CABFile.get_null_ended_string("continued")

            # Set IFolder on CFFILE to ifoldCONTINUED_TO_NEXT
            folder_list = prev_cab.cfheader.cffolder_list
            for folder in folder_list:
                for _cffile in folder.cffile_list:
                    if _cffile.szName == CABFile.get_null_ended_string(filename):
                        if _cffile.iFolder in CFFILE.get_iFolder_options():
                            _cffile.iFolder |= CFFILE.ifoldCONTINUED_TO_NEXT
                        else:
                            _cffile.iFolder = CFFILE.ifoldCONTINUED_TO_NEXT

        # Update offsets - We need to do this every time
        # because we've just added some strings into the structure
        prev_cab.update_fields()
Пример #4
0
 def test_cffile_create_from_parameters(self):
     now = datetime.datetime.now()
     params = {
         "cbFile": 0x1000,
         "uoffFolderStart": 0x20202020,
         "iFolder": 0x01,
         "date": ((now.year-1980)<<9)+(now.month<<5)+(now.day),
         "time": (now.hour<<11)+(now.minute<<5)+(now.second/2),
         "attribs": CFFILE._A_EXEC,
         "szName": "trav.txt"
     }
     cffile = CFFILE.create_from_parameters(parameters=params)
     self.assertEquals("trav.txt", cffile.szName)
     self.assertEquals(0x20202020, cffile.uoffFolderStart)
     self.assertEquals(len(cffile), len(repr(cffile)))
Пример #5
0
 def test_cffile_create_from_parameters(self):
     now = datetime.datetime.now()
     params = {
         "cbFile": 0x1000,
         "uoffFolderStart": 0x20202020,
         "iFolder": 0x01,
         "date": ((now.year - 1980) << 9) + (now.month << 5) + (now.day),
         "time": (now.hour << 11) + (now.minute << 5) + (now.second / 2),
         "attribs": CFFILE._A_EXEC,
         "szName": "trav.txt"
     }
     cffile = CFFILE.create_from_parameters(parameters=params)
     self.assertEquals("trav.txt", cffile.szName)
     self.assertEquals(0x20202020, cffile.uoffFolderStart)
     self.assertEquals(len(cffile), len(repr(cffile)))
Пример #6
0
 def read_files(self, handle):
     result = []
     for i in range(self.cfheader.cFiles):
         parameters = {}
         parameters["cbFile"] = self._read_dword(handle)
         parameters["uoffFolderStart"] = self._read_dword(handle)
         parameters["iFolder"] = self._read_word(handle)
         parameters["date"] = self._read_word(handle)
         parameters["time"] = self._read_word(handle)
         parameters["attribs"] = self._read_word(handle)
         szName = handle.read(1)
         while szName[-1] != "\x00":
             szName += handle.read(1)
         parameters["szName"] = szName
         result.append(CFFILE.create_from_parameters(parameters=parameters))
     return result
Пример #7
0
    def _update_current_cabfile(self, filename, folder_name):

        # Only execute if there was more than one cab before inserting the current
        if len(self.cab_files) < 2:
            return

        # The last added cab is the current
        cab_file = self.cab_files[-1]

        if cab_file.cfheader.flags & CFHEADER.cfhdrPREV_CABINET != CFHEADER.cfhdrPREV_CABINET:
            # We only need to update the szCabinetPrev, szDiskPrev and Flags once!

            # Set PREVIOUS CABINET on the actual
            cab_file.cfheader.flags |= CFHEADER.cfhdrPREV_CABINET

            # MSDN - szCabinetPrev:
            # Note that this gives the name of the most-recently-preceding cabinet file that contains
            #  the initial instance of a file entry. This might not be the immediately previous cabinet file,
            #  when the most recent file spans multiple cabinet files. If searching in reverse for a specific file entry,
            #  or trying to extract a file that is reported to begin in the "previous cabinet",
            #  szCabinetPrev would give the name of the cabinet to examine.

            # We need to search for the first cabinet that holds part of the file
            prev_cab = self._find_first_cab_of_file(filename, folder_name)
            if prev_cab == None:
                # This is a border case where the last cabfile had the exact space requiered for the last file.
                prev_cab = self.cab_files[-2]
            cab_file.cfheader.szCabinetPrev = CABFile.get_null_ended_string(
                prev_cab.cab_filename)
            cab_file.cfheader.szDiskPrev = CABFile.get_null_ended_string(
                "previous")

            folder_list = cab_file.cfheader.cffolder_list
            for folder in folder_list:
                for _cffile in folder.cffile_list:
                    if _cffile.szName == CABFile.get_null_ended_string(
                            filename):
                        if _cffile.iFolder in CFFILE.get_iFolder_options():
                            _cffile.iFolder |= CFFILE.ifoldCONTINUED_FROM_PREV
                        else:
                            _cffile.iFolder = CFFILE.ifoldCONTINUED_FROM_PREV

        # Update offsets - We need to do this every time
        # because we've just added some strings into the structure
        cab_file.update_fields()
Пример #8
0
    def add_file(self, folder_name, filename, total_len, data):

        if self.size == self.max_data:
            raise CABException("This cab is full")

        if (self.size + len(data)) <= self.max_data:

            try:
                cffolder = next(_ for _ in self.cffolder_list
                                if _.name == folder_name)
                # We need to check if the cffolder has a cffile scattered that continues from a PREV
                # If this is the case, we need to provide a new cffolder anyways.. this is how it works
                cffolder = self._check_for_scattered_prev_cffile(cffolder)
            except StopIteration:
                cffolder = self._create_cffolder(folder_name)
                self.cffolder_list.append(cffolder)

            cffile = CFFILE(cffolder=cffolder,
                            total_len=total_len,
                            filename=filename)
            self.cffile_list.append(cffile)

            # Max data per CFDATA is 0x8000 -> This is an empirical result
            if len(data) > 0x8000:
                data_chunks = [
                    data[i:i + 0x8000] for i in range(0, len(data), 0x8000)
                ]
                for data_chunk in data_chunks:
                    cfdata = CFDATA(cffolder=cffolder, data=data_chunk)
                    self.cfdata_list.append(cfdata)
                    cffolder.add_data(cfdata)
            else:
                cfdata = CFDATA(cffolder=cffolder, data=data)
                self.cfdata_list.append(cfdata)
                # Update cCFData
                cffolder.add_data(cfdata)

            cffolder.add_file(cffile)

            self.update_fields()
            self.size += len(data)

        else:
            raise CABException("The cab hasn't enough space for the data ")
Пример #9
0
    def _update_current_cabfile(self, filename, folder_name):

        # Only execute if there was more than one cab before inserting the current
        if len(self.cab_files) < 2:
            return

        # The last added cab is the current
        cab_file = self.cab_files[-1]

        if cab_file.cfheader.flags & CFHEADER.cfhdrPREV_CABINET != CFHEADER.cfhdrPREV_CABINET:
        # We only need to update the szCabinetPrev, szDiskPrev and Flags once!

            # Set PREVIOUS CABINET on the actual
            cab_file.cfheader.flags |= CFHEADER.cfhdrPREV_CABINET

            # MSDN - szCabinetPrev:
            # Note that this gives the name of the most-recently-preceding cabinet file that contains
            #  the initial instance of a file entry. This might not be the immediately previous cabinet file,
            #  when the most recent file spans multiple cabinet files. If searching in reverse for a specific file entry,
            #  or trying to extract a file that is reported to begin in the "previous cabinet",
            #  szCabinetPrev would give the name of the cabinet to examine.

            # We need to search for the first cabinet that holds part of the file
            prev_cab = self._find_first_cab_of_file(filename, folder_name)
            if prev_cab == None:
                # This is a border case where the last cabfile had the exact space requiered for the last file.
                prev_cab = self.cab_files[-2]
            cab_file.cfheader.szCabinetPrev = CABFile.get_null_ended_string(prev_cab.cab_filename)
            cab_file.cfheader.szDiskPrev = CABFile.get_null_ended_string("previous")

            folder_list = cab_file.cfheader.cffolder_list
            for folder in folder_list:
                for _cffile in folder.cffile_list:
                    if _cffile.szName == CABFile.get_null_ended_string(filename):
                        if _cffile.iFolder in CFFILE.get_iFolder_options():
                             _cffile.iFolder |= CFFILE.ifoldCONTINUED_FROM_PREV
                        else:
                            _cffile.iFolder = CFFILE.ifoldCONTINUED_FROM_PREV

        # Update offsets - We need to do this every time
        # because we've just added some strings into the structure
        cab_file.update_fields()
Пример #10
0
 def test_cffile_normal_creation(self):
     cffile = CFFILE(total_len=0x1000, filename="trav.txt")
     self.assertEquals(0x1000, cffile.cbFile)
     self.assertEquals("trav.txt", cffile.szName)
     self.assertEquals(len(cffile), len(repr(cffile)))