def file_tree_ana(self, treeC): # key uint32 # namesize uint32 # name string # file_size uint32 # crc uint32 # offset uint32 # alignSize uint32 file_dict = {} for file in range(self.file_nums): key = treeC[:4] name_size = toInt(treeC[4: 8]) name = treeC[8: 8 + name_size] file_size = toInt(treeC[8 + name_size: 12 + name_size]) crc = toInt(treeC[12 + name_size: 16 + name_size]) offset = toInt(treeC[16 + name_size: 20 + name_size]) alignSize = (file_size + 3) & 0xFFFFFFFC treeC = treeC[28 + name_size:] file_encode_C = self.all_C[offset: offset+file_size] fileC = decrypt_file(file_encode_C, alignSize, crc) file_dict[str(name, encoding='utf-8')] = [key, file_size, crc, offset, alignSize, fileC] break return file_dict
def password_(paName, codeType): code = encode_(paName, codeType) passW = [] for i in range(32): a = toInt(code[i * 4:4 + i * 4]) + 2020 b = toInt(code[::-1][i * 4:4 + i * 4]) + 2020 passW += [toByte(a), toByte(b)] return passW
def insertImg(self, newImgContent, imgName, index=-1, insertMode=False): """ 插入IMG :param newImgContent: 插入的IMG文件流 :param imgName: 插入的IMG文件名称 :param index: 插入序号 :param insertMode: 正序倒序标识符 :return: """ header, imgCount, dictA, dictB, imgContentSplits = self.getSplitData() # -------从末尾插入且是顺序时,或者NPK为空时,直接使用add方法 if (index == -1 and insertMode is False) or imgCount == 0: self.addImg(newImgContent, imgName) return True imgCount += 1 size = toByte(len(newImgContent)) name = toByte(imgName) # 倒序插入 if insertMode: address = toByte(dictA[index][0] + 264) newDictB = {index: [address, size, name]} for key, value in dictB.items(): if key < index: dictB[key][0] = toByte(dictA[key][0] + 264) newDictB[key] = dictB[key] if key >= index: dictB[key][0] = toByte(dictA[key][0] + 264 + toInt(size)) newDictB[key + 1] = dictB[key] dictB = dictSort(newDictB) imgContentSplits.insert(index + 1, newImgContent) self.allContent = self.updateSplitData(header, imgCount, dictB, imgContentSplits) return True # 默认顺序插入 # -----确定新插入img的indexContent # -----位置偏移为插入目标 + 264 + 插入目标imgContent的长度 address = toByte(dictA[index][0] + 264 + dictA[index][1]) newDictB = {index + 1: [address, size, name]} for key, value in dictB.items(): if key <= index: dictB[key][0] = toByte(dictA[key][0] + 264) newDictB[key] = dictB[key] elif key > index: # ----------插入位置之后的imgIndex偏移后延 264 + 新插入imgContent的size dictB[key][0] = toByte(dictA[key][0] + 264 + toInt(size)) newDictB[key + 1] = dictB[key] dictB = dictSort(newDictB) imgContentSplits.insert(index + 1, newImgContent) self.allContent = self.updateSplitData(header, imgCount, dictB, imgContentSplits) return True
def addDictImg(self, imgNameContentDict): """ 从IMG字典流内容中添加,可对应 extractImg方法使用 :param imgNameContentDict: IMG字典流词典,[IMG名称, IMG文件流] :return: 新NPK文件流 """ header, imgCount, dictA, dictB, imgContentSplits = self.getSplitData() lenOfMotoNpk = len(self.allContent) addCount = len(imgNameContentDict.keys()) addCountFlag = 0 lenOfAddIndexC = 264 * addCount for key, value in dictB.items(): dictB[key][0] = toByte(dictA[key][0] + lenOfAddIndexC) for value in imgNameContentDict.values(): addContentLength = 0 if addCountFlag > 0: for i in range(addCountFlag): addContentLength += len(imgNameContentDict[i][-1]) # print(addContentLength) dictB[imgCount + addCountFlag] = [ toByte(lenOfMotoNpk + lenOfAddIndexC + addContentLength), value[0], value[2] ] if imgCount == 0: dictB[imgCount + addCountFlag][0] = toByte( toInt(dictB[imgCount + addCountFlag][0]) + 32) imgContentSplits.append(value[-1]) addCountFlag += 1 imgCount += addCount self.allContent = self.updateSplitData(header, imgCount, dictB, imgContentSplits) return self.allContent
def password_(paName, codeType): code = encode_(paName, codeType) passW = [] # tLine = "2448992054080" for i in range(32): a = toInt(code[i * 4:4 + i * 4]) + 2020 b = toInt(code[::-1][i * 4:4 + i * 4]) + 2020 # if len(a) < len(tLine): # a += " " * (len(tLine) - len(a)) # if len(b) < len(tLine): # b += " " * (len(tLine) - len(b)) passW += [toByte(a), toByte(b)] return passW
def v2Ana(self): # V2版本 分析索引 if self.edition != 2: return False # print(self.edition) indexContent = self.allContent[32:32 + self.indexSize] pngContent = self.allContent[32 + self.indexSize:] # 索引分析字典 indexAnaDict = {} loopIndexDict = {} for index_ in range(self.indexCount): indexType = indexContent[:4] if colorSystem[self.edition][indexType]: # 图片压缩状态 宽 高 png大小 X坐标 Y坐标 帧域款 帧域高 index_ana_list = [ "zipStat", "width", "height", "png_size", "xPos", "yPos", "frameW", "frameH" ] # 对索引信息分割 for ana_index in range(8): index_ana_list[ana_index] = toInt( indexContent[4 * (ana_index + 1):4 * (ana_index + 2)]) # 对图片数据进行分割 png_size = index_ana_list[3] if index_ana_list[0] == 0x06: index_ana_list.append( zlib.decompress(pngContent[0:png_size])) elif index_ana_list[0] == 0x05: index_ana_list.append(pngContent[0:png_size]) indexAnaDict[index_] = (indexType, index_ana_list) pngContent = pngContent[png_size:] indexContent = indexContent[36:] else: loopIndexDict[index_] = toInt(indexContent[4:8]) indexContent = indexContent[8:] indexAnaDict = loopIndexReplace(indexAnaDict, loopIndexDict) return indexAnaDict
def __init__(self, bytes_stream): # 标识符大小 self.guid_size = toInt(bytes_stream[:4]) flag = self.guid_size # 标识符 self.guid = bytes_stream[4: 4 + flag] # 版本 self.version = bytes_stream[4 + flag: 8 + flag] # 目录树索引长度 self.indexes_length = toInt(bytes_stream[8 + flag: 12 + flag]) # crc32码? self.crc32 = toInt(bytes_stream[12 + flag: 16 + flag]) # 文件总数 self.file_nums = toInt(bytes_stream[16 + flag:])
def login(password, codeType): disk_ = get_disk_ID() enCodeA = b'' enCodeB = b'' for i in range(32): a = toByte(toInt(password[i * 2]) - 2020) b = toByte(toInt(password[i * 2 + 1]) - 2020)[::-1] enCodeA += a enCodeB = b + enCodeB trueCode = toString(enCodeA + enCodeB).replace(' ', '') if disk_ + passwordData[codeType] == trueCode: return True else: print("硬盘码为:\t" + disk_) print("密码不正确已退出") return False
def indexContentAna(imgIndexContent): imgIndexAnaDictA = {} imgIndexAnaDictB = {} imgIndexAnaDictC = [] for element in imgIndexContent: address = element[:4] size = element[4:8] name = element[8:] index = imgIndexContent.index(element) imgIndexAnaDictA[index] = [toInt(address), toInt(size), toString(name)] imgIndexAnaDictB[index] = [address, size, name] if index == 0: imgIndexAnaDictC.append(toInt(size)) if index > 0: if imgIndexAnaDictA[index][0] != imgIndexAnaDictA[index - 1][0]: imgIndexAnaDictC.append(toInt(size)) else: imgIndexAnaDictC.append(0) return imgIndexAnaDictA, imgIndexAnaDictB, imgIndexAnaDictC
def updateSplitData(self, header, imgCount, dictB, imgContentSplits): """ 更新NPK分割内容 :param header: 文件头 :param imgCount: IMG数量 :param dictB: 二进制流IMG词典 :param imgContentSplits: IMG内容分割 :return: NPK文件流 """ self.allContent = reCombination(header, imgCount, dictB, imgContentSplits) self.imgContents = imgContentSplits self.contentSplit = self.splitNpkContent() if len(dictB.keys()) > 0: dictA = dictB for key in dictB.keys(): dictA[key][0] = toInt(dictB[key][0]) dictA[key][1] = toInt(dictB[key][1]) dictA[key][2] = toString(dictB[key][2]) self.dictAna = dictA if len(dictB.keys()) == 0: self.dictAna = {} return self.allContent
def npkContentSplit(npkContent): header = npkContent[:16] imgCount = toInt(npkContent[16:20]) imgIndexContent = [] sHA = b'' imgContents = [] if imgCount > 0: for index in range(imgCount): imgIndexContent.append(npkContent[20 + index * 264:20 + (index + 1) * 264]) sHA = npkContent[20 + imgCount * 264:20 + 32 + imgCount * 264] imgContents = npkContent[20 + 32 + imgCount * 264:] return [header, imgCount, imgIndexContent, sHA, imgContents]
def delRepeatImg(repeatImgNpkDict, img2Dir): if len(repeatImgNpkDict.keys()) <= 0: return False for npkPath, imgIndexes in repeatImgNpkDict.items(): truePath = img2Dir + '\\\\' + npkPath obj = NPK() try: obj.open(truePath) obj.delImg(imgIndexes) except: print(truePath + "{}\t处理失败".format(imgIndexes)) continue imgCount = toInt(obj.allContent[16:20]) obj.save(mode=False) if imgCount == 0: remove(truePath) print("已删除空NPK文件:\t" + npkPath.split("\\")[-1])
def nameAna(filePath): """ 仅获取NPK和内部IMG名称的词典 :param filePath: NPK文件路径 :return: False为目标文件不为标准NPK文件。npkName, imgNameList = [imgName1, imgName2] """ with open(filePath, 'rb') as npk: npkContent = npk.read() # self.allContent = npkContent if isNPK(npkContent): imgCount = abs(toInt(npkContent[16:20])) # 获取名称 npkName = filePath.split("\\")[-1] indexContent = npkContent[20:20 + imgCount * 264] imgNameList = [ toString(indexContent[264 * imgIndex:264 * (imgIndex + 1)][8:]) for imgIndex in range(imgCount) ] return npkName, imgNameList else: return False
def edition(self): return toInt(self.allContent[24:28])
def delImg(self, index=None, delAll=False): """ 删除IMG :param index: 删除编号或列表 :param delAll: 全删除标识符 :return: 删除成功/失败 """ # 全删除模式,则将NPK更新为空NPK if delAll: self.allContent = empty_NPK return True header, imgCount, dictA, dictB, imgContentSplits = self.getSplitData() if index is None: return False if isinstance(index, int): index = [index] if isinstance(index, list): index = list(set(index)) index = [ i_ if i_ > 0 else i_ + self.imgCount for i_ in list(set(index)) if ((0 <= i_ < self.imgCount) or ( i_ < 0 and i_ + self.imgCount >= 0)) ] if len(index) >= imgCount: self.allContent = empty_NPK return True addressIndex = [] for key in dictA.keys(): addressIndex.append(dictA[key][0]) addressIndexBak = addressIndex[:] for element in index: if element < 0: element = imgCount + element addressIndex.remove(dictA[element][0]) for key, value in dictB.items(): if key > element and dictA[element][0] not in addressIndex: dictB[key][0] = toByte( toInt(dictB[key][0]) - dictA[element][1]) if key > element and dictA[element][0] in addressIndex: continue newImgContents = [] newDictB = {} newFlag = 0 for lasTelement in addressIndex: lastIndex = addressIndexBak.index(lasTelement) newImgContents.append(imgContentSplits[lastIndex]) newDictB[newFlag] = dictB[lastIndex] newFlag += 1 imgCount -= len(index) for key, value in newDictB.items(): newDictB[key][0] = toByte( toInt(newDictB[key][0]) - 264 * len(index)) self.allContent = self.updateSplitData(header, imgCount, newDictB, newImgContents) return True return False
def imgCount(self): return toInt(self.allContent[16:20])
def indexCount(self): return toInt(self.allContent[28:32])
def indexSize(self): return toInt(self.allContent[16:20])