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)
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()
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()
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)))
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)))
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
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()
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 ")
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()
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)))