def test_cffolder_add_data(self): reserve = {'cbCFHeader': 0, 'cbCFFolder': 0, 'cbCFData': 0} cfheader = CFHEADER(flags=0, reserve=reserve) cffolder = CFFOLDER(cfheader=cfheader) cfdata = CFDATA(data="testdata1") cffolder.add_data(cfdata) cfdata = CFDATA(data="testdata2") cffolder.add_data(cfdata) self.assertEquals(2, cffolder.cCFData)
def test_cfdata_normal_creation(self): data = "this is the data" cfdata = CFDATA(data=data) self.assertEquals(data, cfdata.ab) self.assertEquals(len(data), cfdata.cbData) self.assertEquals(len(data), cfdata.cbUncomp) self.assertEquals(len(cfdata), len(repr(cfdata)))
def test_cfdata_with_reserve(self): data = "this is the data" reserve = {'cbCFHeader': 0, 'cbCFFolder': 0, 'cbCFData': 20} cfheader = CFHEADER(flags=CFHEADER.cfhdrRESERVE_PRESENT, reserve=reserve) cffolder = CFFOLDER(cfheader=cfheader) cfdata = CFDATA(cffolder=cffolder, data=data) self.assertEquals(20, len(cfdata.abReserve)) self.assertEquals(len(cfdata), len(repr(cfdata)))
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 _read_data_primitive(self, current_cab, cffile): file_data = "" file_data_len = self.file_data_len while file_data_len < cffile.cbFile and self.curr_index_data < len(current_cab.cfdata_list): current_cfdata = current_cab.cfdata_list[self.curr_index_data] file_data_len += current_cfdata.cbUncomp file_data += current_cfdata.ab self.curr_index_data += 1 self.file_data_len = file_data_len if self.file_data_len > cffile.cbFile: # The CAB compressor of windows does a nasty thing... # It allows to share a CFDATA between TWO CFFILES # We need to adjust the data if this is the case difference = self.file_data_len - cffile.cbFile real_file_data = file_data[0:(self.file_data_len-difference)] # We will create an anonymous CFDATA and add it to the list .. # This way the remaining bytes that belongs to the next CFFILE will be read transparently new_cfdata = CFDATA() new_cfdata.ab = file_data[(self.file_data_len-difference):self.file_data_len] new_cfdata.cbUncomp = len(new_cfdata.ab) new_cfdata.cbData = len(new_cfdata.ab) current_cab.cfdata_list.insert(self.curr_index_data, new_cfdata) return real_file_data return file_data
def read_data(self, handle): result = [] data_count = sum([cffolder.cCFData for cffolder in self.cffolder_list]) for i in range(data_count): parameters = {} parameters["csum"] = self._read_dword(handle) parameters["cbData"] = self._read_word(handle) parameters["cbUncomp"] = self._read_word(handle) if self.cfheader.flags & CFHEADER.cfhdrRESERVE_PRESENT: parameters["abReserve"] = handle.read(self.cfheader.cbCFData) else: parameters["abReserve"] = "" parameters["ab"] = handle.read(parameters["cbData"]) result.append(CFDATA.create_from_parameters(parameters=parameters)) return result