From 60eeb7bb87f7d6abef7d5c9c98afaece5820fa37 Mon Sep 17 00:00:00 2001 From: wangzeyu Date: Sat, 2 Dec 2023 19:36:01 +0800 Subject: [PATCH 01/37] try to load zip data Signed-off-by: wangzeyu --- .../ohos/hapsigntool/error/ZipException.java | 17 + .../hap/entity/zip/CentralDirectory.java | 354 ++++++++++++++++++ .../hap/entity/zip/DataDescriptor.java | 70 ++++ .../hap/entity/zip/EndOfCentralDirectory.java | 177 +++++++++ .../ohos/hapsigntool/hap/entity/zip/Zip.java | 227 +++++++++++ .../hapsigntool/hap/entity/zip/ZipEntry.java | 58 +++ .../hap/entity/zip/ZipEntryHeader.java | 257 +++++++++++++ .../hap/provider/SignProvider.java | 2 + .../com/ohos/hapsigntool/utils/FileUtils.java | 51 ++- 9 files changed, 1211 insertions(+), 2 deletions(-) create mode 100644 hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/error/ZipException.java create mode 100644 hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/CentralDirectory.java create mode 100644 hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/DataDescriptor.java create mode 100644 hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/EndOfCentralDirectory.java create mode 100644 hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/Zip.java create mode 100644 hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntry.java create mode 100644 hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntryHeader.java diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/error/ZipException.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/error/ZipException.java new file mode 100644 index 00000000..fc525d97 --- /dev/null +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/error/ZipException.java @@ -0,0 +1,17 @@ +package com.ohos.hapsigntool.error; + +import java.io.IOException; + +public class ZipException extends IOException { + public ZipException() { + + } + + public ZipException(String message) { + super(message); + } + + public ZipException(String message, Exception e) { + super(message, e); + } +} diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/CentralDirectory.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/CentralDirectory.java new file mode 100644 index 00000000..c29a899c --- /dev/null +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/CentralDirectory.java @@ -0,0 +1,354 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.ohos.hapsigntool.hap.entity.zip; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.charset.StandardCharsets; + +class CentralDirectory { + public static final int cdLength = 46; + + /** + * 4 bytes + */ + public static final int signature = 0x02014b50; + + /** + * 2 bytes + */ + private short version; + + /** + * 2 bytes + */ + private short versionExtra; + + + /** + * 2 bytes + */ + private short flag; + + /** + * 2 bytes + */ + private short method; + + /** + * 2 bytes + */ + private short lastTime; + + /** + * 2 bytes + */ + private short lastDate; + + /** + * 4 bytes + */ + private int crc32; + + /** + * 4 bytes + */ + private int compressedSize; + + /** + * 4 bytes + */ + private int unCompressedSize; + + /** + * 2 bytes + */ + private short fileNameLength; + + /** + * 2 bytes + */ + private short extraLength; + + /** + * 2 bytes + */ + private short commentLength; + + /** + * 2 bytes + */ + private short diskNumStart; + + + /** + * 2 bytes + */ + private short internalFile; + + + /** + * 4 bytes + */ + private int externalFile; + + + /** + * 4 bytes + */ + private int offset; + + /** + * n bytes + */ + private String fileName; + + /** + * n bytes + */ + private byte[] extraData; + + /** + * n bytes + */ + private String comment; + + public static CentralDirectory initCentralDirectory(byte[] bytes, int offset) { + if (bytes.length < offset) { + return null; + } + CentralDirectory cd = new CentralDirectory(); + ByteBuffer bf = ByteBuffer.allocate(bytes.length); + bf.put(bytes, offset, bytes.length - offset); + bf.order(ByteOrder.LITTLE_ENDIAN); + bf.flip(); + if (bf.getInt() != signature) { + return null; + } + cd.setVersion(bf.getShort()); + cd.setVersionExtra(bf.getShort()); + cd.setFlag(bf.getShort()); + cd.setMethod(bf.getShort()); + cd.setLastTime(bf.getShort()); + cd.setLastDate(bf.getShort()); + cd.setCrc32(bf.getInt()); + cd.setCompressedSize(bf.getInt()); + cd.setUnCompressedSize(bf.getInt()); + cd.setFileNameLength(bf.getShort()); + cd.setExtraLength(bf.getShort()); + cd.setCommentLength(bf.getShort()); + cd.setDiskNumStart(bf.getShort()); + cd.setInternalFile(bf.getShort()); + cd.setExternalFile(bf.getInt()); + cd.setOffset(bf.getInt()); + if (cd.getFileNameLength() > 0) { + cd.setFileName(new String(bf.array(), StandardCharsets.UTF_8)); + } + if (cd.getExtraLength() > 0) { + byte[] extra = new byte[cd.getExtraLength()]; + bf.get(extra); + cd.setExtraData(extra); + } + if (cd.getCommentLength() > 0) { + cd.setComment(new String(bf.array(), StandardCharsets.UTF_8)); + } + return cd; + } + + public byte[] toBytes() { + int length = cdLength + fileNameLength + extraLength + commentLength; + ByteBuffer bf = ByteBuffer.allocate(length).order(ByteOrder.LITTLE_ENDIAN); + bf.putInt(signature); + bf.putShort(version); + bf.putShort(versionExtra); + bf.putShort(flag); + bf.putShort(method); + bf.putShort(lastTime); + bf.putShort(lastDate); + bf.putInt(crc32); + bf.putInt(compressedSize); + bf.putInt(unCompressedSize); + bf.putShort(fileNameLength); + bf.putShort(extraLength); + bf.putShort(commentLength); + bf.putShort(diskNumStart); + bf.putShort(internalFile); + bf.putInt(externalFile); + bf.putInt(offset); + if (fileNameLength > 0) { + bf.put(fileName.getBytes(StandardCharsets.UTF_8)); + } + if (extraLength > 0) { + bf.put(extraData); + } + if (commentLength > 0) { + bf.put(comment.getBytes(StandardCharsets.UTF_8)); + } + return bf.array(); + } + + public short getVersion() { + return version; + } + + public void setVersion(short version) { + this.version = version; + } + + public short getVersionExtra() { + return versionExtra; + } + + public void setVersionExtra(short versionExtra) { + this.versionExtra = versionExtra; + } + + public short getFlag() { + return flag; + } + + public void setFlag(short flag) { + this.flag = flag; + } + + public short getMethod() { + return method; + } + + public void setMethod(short method) { + this.method = method; + } + + public short getLastTime() { + return lastTime; + } + + public void setLastTime(short lastTime) { + this.lastTime = lastTime; + } + + public short getLastDate() { + return lastDate; + } + + public void setLastDate(short lastDate) { + this.lastDate = lastDate; + } + + public int getCrc32() { + return crc32; + } + + public void setCrc32(int crc32) { + this.crc32 = crc32; + } + + public int getCompressedSize() { + return compressedSize; + } + + public void setCompressedSize(int compressedSize) { + this.compressedSize = compressedSize; + } + + public int getUnCompressedSize() { + return unCompressedSize; + } + + public void setUnCompressedSize(int unCompressedSize) { + this.unCompressedSize = unCompressedSize; + } + + public short getFileNameLength() { + return fileNameLength; + } + + public void setFileNameLength(short fileNameLength) { + this.fileNameLength = fileNameLength; + } + + public short getExtraLength() { + return extraLength; + } + + public void setExtraLength(short extraLength) { + this.extraLength = extraLength; + } + + public short getCommentLength() { + return commentLength; + } + + public void setCommentLength(short commentLength) { + this.commentLength = commentLength; + } + + public short getDiskNumStart() { + return diskNumStart; + } + + public void setDiskNumStart(short diskNumStart) { + this.diskNumStart = diskNumStart; + } + + public short getInternalFile() { + return internalFile; + } + + public void setInternalFile(short internalFile) { + this.internalFile = internalFile; + } + + public int getExternalFile() { + return externalFile; + } + + public void setExternalFile(int externalFile) { + this.externalFile = externalFile; + } + + public int getOffset() { + return offset; + } + + public void setOffset(int offset) { + this.offset = offset; + } + + public String getFileName() { + return fileName; + } + + public void setFileName(String fileName) { + this.fileName = fileName; + } + + public byte[] getExtraData() { + return extraData; + } + + public void setExtraData(byte[] extraData) { + this.extraData = extraData; + } + + public String getComment() { + return comment; + } + + public void setComment(String comment) { + this.comment = comment; + } +} \ No newline at end of file diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/DataDescriptor.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/DataDescriptor.java new file mode 100644 index 00000000..436d6fe8 --- /dev/null +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/DataDescriptor.java @@ -0,0 +1,70 @@ +package com.ohos.hapsigntool.hap.entity.zip; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +public class DataDescriptor { + public static final int desLength = 12; + + /** + * 4 bytes + */ + int crc32; + + /** + * 4 bytes + */ + int compressedSize; + + /** + * 4 bytes + */ + int unCompressedSize; + + public static DataDescriptor initDataDescriptor(byte[] bytes) { + if (bytes.length != 12) { + return null; + } + ByteBuffer bf = ByteBuffer.allocate(bytes.length); + bf.put(bytes); + bf.order(ByteOrder.LITTLE_ENDIAN); + bf.flip(); + DataDescriptor data = new DataDescriptor(); + data.setCrc32(bf.getInt()); + data.setCompressedSize(bf.getInt()); + data.setUnCompressedSize(bf.getInt()); + return data; + } + + public byte[] toBytes() { + ByteBuffer bf = ByteBuffer.allocate(desLength).order(ByteOrder.LITTLE_ENDIAN); + bf.putInt(crc32); + bf.putInt(compressedSize); + bf.putInt(unCompressedSize); + return bf.array(); + } + + public int getCrc32() { + return crc32; + } + + public void setCrc32(int crc32) { + this.crc32 = crc32; + } + + public int getCompressedSize() { + return compressedSize; + } + + public void setCompressedSize(int compressedSize) { + this.compressedSize = compressedSize; + } + + public int getUnCompressedSize() { + return unCompressedSize; + } + + public void setUnCompressedSize(int unCompressedSize) { + this.unCompressedSize = unCompressedSize; + } +} diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/EndOfCentralDirectory.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/EndOfCentralDirectory.java new file mode 100644 index 00000000..5d75de47 --- /dev/null +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/EndOfCentralDirectory.java @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.ohos.hapsigntool.hap.entity.zip; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.charset.StandardCharsets; + +class EndOfCentralDirectory { + public static final int eocdLength = 22; + + /** + * 4 bytes + */ + public static final int signature = 0x06054b50; + + /** + * 2 bytes + */ + private short diskNum; + + + /** + * 2 bytes + */ + private short CDStartDiskNum; + + /** + * 2 bytes + */ + private short thisDiskCDNum; + + /** + * 2 bytes + */ + private short CDTotal; + + /** + * 4 bytes + */ + private int CDSize; + + /** + * 4 bytes + */ + private int offset; + + /** + * 2 bytes + */ + private short commentLength; + + /** + * n bytes + */ + private String comment; + + public static EndOfCentralDirectory initEOCDByBytes(byte[] bytes) { + EndOfCentralDirectory eocd = new EndOfCentralDirectory(); + ByteBuffer bf = ByteBuffer.allocate(bytes.length); + bf.put(bytes); + bf.order(ByteOrder.LITTLE_ENDIAN); + bf.flip(); + if (bf.getInt() != signature) { + return null; + } + eocd.setDiskNum(bf.getShort()); + eocd.setCDStartDiskNum(bf.getShort()); + eocd.setThisDiskCDNum(bf.getShort()); + eocd.setCDTotal(bf.getShort()); + eocd.setCDSize(bf.getInt()); + eocd.setOffset(bf.getInt()); + eocd.setCommentLength(bf.getShort()); + if (eocd.getCommentLength() > 0) { + byte[] comment = new byte[eocd.getCommentLength()]; + bf.get(comment); + eocd.setComment(new String(comment, StandardCharsets.UTF_8)); + } + if (bf.remaining() != 0) { + return null; + } + return eocd; + } + + public byte[] toBytes() { + ByteBuffer bf = ByteBuffer.allocate(eocdLength + commentLength).order(ByteOrder.LITTLE_ENDIAN); + bf.putInt(signature); + bf.putShort(diskNum); + bf.putShort(CDStartDiskNum); + bf.putShort(thisDiskCDNum); + bf.putShort(CDTotal); + bf.putInt(CDSize); + bf.putInt(offset); + bf.putShort(commentLength); + if (commentLength > 0) { + bf.put(comment.getBytes(StandardCharsets.UTF_8)); + } + return bf.array(); + } + + public short getDiskNum() { + return diskNum; + } + + public void setDiskNum(short diskNum) { + this.diskNum = diskNum; + } + + public short getCDStartDiskNum() { + return CDStartDiskNum; + } + + public void setCDStartDiskNum(short CDStartDiskNum) { + this.CDStartDiskNum = CDStartDiskNum; + } + + public short getThisDiskCDNum() { + return thisDiskCDNum; + } + + public void setThisDiskCDNum(short thisDiskCDNum) { + this.thisDiskCDNum = thisDiskCDNum; + } + + public short getCDTotal() { + return CDTotal; + } + + public void setCDTotal(short CDTotal) { + this.CDTotal = CDTotal; + } + + public int getCDSize() { + return CDSize; + } + + public void setCDSize(int CDSize) { + this.CDSize = CDSize; + } + + public int getOffset() { + return offset; + } + + public void setOffset(int offset) { + this.offset = offset; + } + + public short getCommentLength() { + return commentLength; + } + + public void setCommentLength(short commentLength) { + this.commentLength = commentLength; + } + + public String getComment() { + return comment; + } + + public void setComment(String comment) { + this.comment = comment; + } +} \ No newline at end of file diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/Zip.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/Zip.java new file mode 100644 index 00000000..5642da42 --- /dev/null +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/Zip.java @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.ohos.hapsigntool.hap.entity.zip; + + +import com.ohos.hapsigntool.error.ZipException; +import com.ohos.hapsigntool.utils.FileUtils; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +public class Zip { + private List zipEntries; + + private long signingOffset; + + private byte[] signingBlock; + + private long CDOffset; + + private List centralDirectories; + + private long EOCDOffset; + + private EndOfCentralDirectory endOfCentralDirectory; + + private String file; + + public Zip(File file) throws IOException { + this.file = file.getPath(); + // 1. get eocd data + endOfCentralDirectory = getZipEndOfCentralDirectory(file); + // 2. use eocd's cd offset, get cd data + centralDirectories = getZipCentralDirectory(file); + // 3. use cd's entry offset and file size, get entry data + zipEntries = getZipEntries(file); + // 4. file data - eocd - cd - entry = sign block + signingBlock = getSigningBlock(file); + } + + private EndOfCentralDirectory getZipEndOfCentralDirectory(File file) throws IOException { + EndOfCentralDirectory eocd; + if (file.length() < EndOfCentralDirectory.eocdLength) { + throw new ZipException("find zip eocd failed"); + } + + // try to read EOCD without comment + int eocdMaxLength = EndOfCentralDirectory.eocdLength; + EOCDOffset = file.length() - eocdMaxLength; + byte[] bytes = FileUtils.readFileByOffsetAndLength(file, EOCDOffset, eocdMaxLength); + eocd = EndOfCentralDirectory.initEOCDByBytes(bytes); + if (eocd != null) { + return eocd; + } + + //try to search EOCD with comment + int maxCommentLength = 65535; + eocdMaxLength = EndOfCentralDirectory.eocdLength + maxCommentLength; + EOCDOffset = file.length() - eocdMaxLength; + bytes = FileUtils.readFileByOffsetAndLength(file, EOCDOffset, eocdMaxLength); + for (int start = 0; start < eocdMaxLength; start++) { + eocd = EndOfCentralDirectory.initEOCDByBytes(bytes); + if (eocd != null) { + EOCDOffset += start; + return eocd; + } + } + throw new ZipException("read zip failed: can not find eocd in file"); + } + + private List getZipCentralDirectory(File file) throws IOException { + List cdList = new ArrayList<>(endOfCentralDirectory.getCDTotal()); + CDOffset = endOfCentralDirectory.getOffset(); + byte[] cdBytes = FileUtils.readFileByOffsetAndLength(file, CDOffset, endOfCentralDirectory.getCDSize()); + if (cdBytes.length < CentralDirectory.cdLength) { + throw new ZipException("find zip cd failed"); + } + int offset = 0; + while (offset < cdBytes.length) { + CentralDirectory cd = CentralDirectory.initCentralDirectory(cdBytes, offset); + if (cd == null) { + throw new ZipException("find zip cd failed"); + } + cdList.add(cd); + offset += CentralDirectory.cdLength + cd.getFileNameLength() + cd.getExtraLength() + cd.getCommentLength(); + } + return cdList; + } + + private byte[] getSigningBlock(File file) throws IOException { + return FileUtils.readFileByOffsetAndLength(file, signingOffset, CDOffset - signingOffset); + } + + private List getZipEntries(File file) throws IOException { + List entryList = new ArrayList<>(); + for (CentralDirectory cd : centralDirectories) { + long offset = cd.getOffset(); + long fileSize = cd.getCompressedSize(); + entryList.add(initZipEntry(file, offset, fileSize)); + } + return entryList; + } + + private ZipEntry initZipEntry(File file, long entryOffset, long fileSize) throws IOException { + ZipEntry entry = new ZipEntry(); + long offset = entryOffset; + byte[] headBytes = FileUtils.readFileByOffsetAndLength(file, offset, ZipEntryHeader.headerLength); + ZipEntryHeader zipEntryHeader = ZipEntryHeader.initZipEntryHeader(headBytes); + if (zipEntryHeader == null) { + throw new ZipException("find zip entry head failed"); + } + offset += ZipEntryHeader.headerLength; + byte[] nameExtra = FileUtils.readFileByOffsetAndLength(file, offset, zipEntryHeader.getFileNameLength() + zipEntryHeader.getExtraLength()); + zipEntryHeader.setNameAndExtra(nameExtra); + + offset += zipEntryHeader.getFileNameLength() + zipEntryHeader.getExtraLength(); + entry.setFileOffset(offset); + entry.setFileSize(fileSize); + + offset += fileSize; + byte[] desBytes = FileUtils.readFileByOffsetAndLength(file, offset, DataDescriptor.desLength); + DataDescriptor dataDescriptor = DataDescriptor.initDataDescriptor(desBytes); + if (dataDescriptor == null) { + throw new ZipException("find zip entry desc failed"); + } + + entry.setDataDescriptor(dataDescriptor); + entry.setZipEntryHeader(zipEntryHeader); + return entry; + } + + public void toFile(String file) { + for (ZipEntry zipEntry : zipEntries) { + FileUtils.writeByteToOutFile(zipEntry.getZipEntryHeader().toBytes(), file); + // TODO 需要根据源文件,按照offset写入压缩后数据 +// FileUtils.wri(zipEntry.getZipEntryData(), file); + FileUtils.writeByteToOutFile(zipEntry.getDataDescriptor().toBytes(), file); + } + FileUtils.writeByteToOutFile(signingBlock, file); + for (CentralDirectory cd : centralDirectories) { + FileUtils.writeByteToOutFile(cd.toBytes(), file); + } + FileUtils.writeByteToOutFile(endOfCentralDirectory.toBytes(), file); + } + + public void alignment() { + // TODO 字节对齐逻辑 + } + public List getZipEntries() { + return zipEntries; + } + + public void setZipEntries(List zipEntries) { + this.zipEntries = zipEntries; + } + + public long getSigningOffset() { + return signingOffset; + } + + public void setSigningOffset(long signingOffset) { + this.signingOffset = signingOffset; + } + + public byte[] getSigningBlock() { + return signingBlock; + } + + public void setSigningBlock(byte[] signingBlock) { + this.signingBlock = signingBlock; + } + + public long getCDOffset() { + return CDOffset; + } + + public void setCDOffset(long CDOffset) { + this.CDOffset = CDOffset; + } + + public List getCentralDirectories() { + return centralDirectories; + } + + public void setCentralDirectories(List centralDirectories) { + this.centralDirectories = centralDirectories; + } + + public long getEOCDOffset() { + return EOCDOffset; + } + + public void setEOCDOffset(long EOCDOffset) { + this.EOCDOffset = EOCDOffset; + } + + public EndOfCentralDirectory getEndOfCentralDirectory() { + return endOfCentralDirectory; + } + + public void setEndOfCentralDirectory(EndOfCentralDirectory endOfCentralDirectory) { + this.endOfCentralDirectory = endOfCentralDirectory; + } + + public String getFile() { + return file; + } + + public void setFile(String file) { + this.file = file; + } +} \ No newline at end of file diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntry.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntry.java new file mode 100644 index 00000000..080cfb70 --- /dev/null +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntry.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.ohos.hapsigntool.hap.entity.zip; + +class ZipEntry { + private ZipEntryHeader zipEntryHeader; + + private long fileOffset; + + private long fileSize; + + private DataDescriptor dataDescriptor; + + public ZipEntryHeader getZipEntryHeader() { + return zipEntryHeader; + } + + public void setZipEntryHeader(ZipEntryHeader zipEntryHeader) { + this.zipEntryHeader = zipEntryHeader; + } + + public DataDescriptor getDataDescriptor() { + return dataDescriptor; + } + + public void setDataDescriptor(DataDescriptor dataDescriptor) { + this.dataDescriptor = dataDescriptor; + } + + public long getFileOffset() { + return fileOffset; + } + + public void setFileOffset(long fileOffset) { + this.fileOffset = fileOffset; + } + + public long getFileSize() { + return fileSize; + } + + public void setFileSize(long fileSize) { + this.fileSize = fileSize; + } +} \ No newline at end of file diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntryHeader.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntryHeader.java new file mode 100644 index 00000000..477f9ca1 --- /dev/null +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntryHeader.java @@ -0,0 +1,257 @@ +/* + * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.ohos.hapsigntool.hap.entity.zip; + + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.charset.StandardCharsets; + +class ZipEntryHeader { + + public static int headerLength = 30; + /** + * 4 bytes + */ + public static final int signature = 0x04034b50; + + /** + * 2 bytes + */ + private short version; + + /** + * 2 bytes + */ + private short flag; + + /** + * 2 bytes + */ + private short method; + + /** + * 2 bytes + */ + private short lastTime; + + /** + * 2 bytes + */ + private short lastDate; + + /** + * 4 bytes + */ + private int crc32; + + /** + * 4 bytes + */ + private int compressedSize; + + /** + * 4 bytes + */ + private int unCompressedSize; + + /** + * 2 bytes + */ + private short fileNameLength; + + /** + * 2 bytes + */ + private short extraLength; + + /** + * n bytes + */ + private String fileName; + + /** + * n bytes + */ + private byte[] extraData; + + public static ZipEntryHeader initZipEntryHeader(byte[] bytes) { + ZipEntryHeader entryHeader = new ZipEntryHeader(); + ByteBuffer bf = ByteBuffer.allocate(bytes.length); + bf.put(bytes); + bf.order(ByteOrder.LITTLE_ENDIAN); + bf.flip(); + if (bf.getInt() != ZipEntryHeader.signature) { + return null; + } + entryHeader.setVersion(bf.getShort()); + entryHeader.setFlag(bf.getShort()); + entryHeader.setMethod(bf.getShort()); + entryHeader.setLastTime(bf.getShort()); + entryHeader.setLastDate(bf.getShort()); + entryHeader.setCrc32(bf.getInt()); + entryHeader.setCompressedSize(bf.getInt()); + entryHeader.setUnCompressedSize(bf.getInt()); + entryHeader.setFileNameLength(bf.getShort()); + entryHeader.setExtraLength(bf.getShort()); + + return entryHeader; + } + + public void setNameAndExtra(byte[] bytes) { + ByteBuffer bf = ByteBuffer.allocate(bytes.length); + bf.put(bytes); + bf.order(ByteOrder.LITTLE_ENDIAN); + bf.flip(); + if (fileNameLength > 0) { + byte[] nameBytes = new byte[fileNameLength]; + bf.get(nameBytes); + this.fileName = new String(nameBytes, StandardCharsets.UTF_8); + } + if (extraLength > 0) { + byte[] extra = new byte[extraLength]; + bf.get(extra); + this.extraData = extra; + } + } + + public byte[] toBytes() { + int length = headerLength + fileNameLength + extraLength; + ByteBuffer bf = ByteBuffer.allocate(length).order(ByteOrder.LITTLE_ENDIAN); + bf.putInt(signature); + bf.putShort(version); + bf.putShort(flag); + bf.putShort(method); + bf.putShort(lastTime); + bf.putShort(lastDate); + bf.putInt(crc32); + bf.putInt(compressedSize); + bf.putInt(unCompressedSize); + bf.putShort(fileNameLength); + bf.putShort(extraLength); + if (fileNameLength > 0) { + bf.put(fileName.getBytes(StandardCharsets.UTF_8)); + } + if (extraLength > 0) { + bf.put(extraData); + } + return bf.array(); + } + + public static int getHeaderLength() { + return headerLength; + } + + public static void setHeaderLength(int headerLength) { + ZipEntryHeader.headerLength = headerLength; + } + + public short getVersion() { + return version; + } + + public void setVersion(short version) { + this.version = version; + } + + public short getFlag() { + return flag; + } + + public void setFlag(short flag) { + this.flag = flag; + } + + public short getMethod() { + return method; + } + + public void setMethod(short method) { + this.method = method; + } + + public short getLastTime() { + return lastTime; + } + + public void setLastTime(short lastTime) { + this.lastTime = lastTime; + } + + public short getLastDate() { + return lastDate; + } + + public void setLastDate(short lastDate) { + this.lastDate = lastDate; + } + + public int getCrc32() { + return crc32; + } + + public void setCrc32(int crc32) { + this.crc32 = crc32; + } + + public int getCompressedSize() { + return compressedSize; + } + + public void setCompressedSize(int compressedSize) { + this.compressedSize = compressedSize; + } + + public int getUnCompressedSize() { + return unCompressedSize; + } + + public void setUnCompressedSize(int unCompressedSize) { + this.unCompressedSize = unCompressedSize; + } + + public short getFileNameLength() { + return fileNameLength; + } + + public void setFileNameLength(short fileNameLength) { + this.fileNameLength = fileNameLength; + } + + public short getExtraLength() { + return extraLength; + } + + public void setExtraLength(short extraLength) { + this.extraLength = extraLength; + } + + public String getFileName() { + return fileName; + } + + public void setFileName(String fileName) { + this.fileName = fileName; + } + + public byte[] getExtraData() { + return extraData; + } + + public void setExtraData(byte[] extraData) { + this.extraData = extraData; + } +} \ No newline at end of file diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/provider/SignProvider.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/provider/SignProvider.java index c181bdaf..44b5ac94 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/provider/SignProvider.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/provider/SignProvider.java @@ -29,6 +29,7 @@ import com.ohos.hapsigntool.codesigning.sign.CodeSigning; import com.ohos.hapsigntool.error.CustomException; import com.ohos.hapsigntool.hap.config.SignerConfig; import com.ohos.hapsigntool.hap.entity.SigningBlock; +import com.ohos.hapsigntool.hap.entity.zip.Zip; import com.ohos.hapsigntool.hap.exception.HapFormatException; import com.ohos.hapsigntool.hap.exception.InvalidParamsException; import com.ohos.hapsigntool.hap.exception.MissingParamsException; @@ -504,6 +505,7 @@ public abstract class SignProvider { */ private void copyFileAndAlignment(File input, File tmpOutput, int alignment) throws IOException, HapFormatException { + Zip zip = new Zip(input); try (JarFile inputJar = new JarFile(input, false); FileOutputStream outputFile = new FileOutputStream(tmpOutput); JarOutputStream outputJar = new JarOutputStream(outputFile)) { diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/utils/FileUtils.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/utils/FileUtils.java index fdb240af..2fd4947d 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/utils/FileUtils.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/utils/FileUtils.java @@ -58,7 +58,7 @@ public final class FileUtils { /** * File reader block size */ - public static final int FILE_BUFFER_BLOCK = 4096; + public static final int FILE_BUFFER_BLOCK = 16 * 1024; /** * File end */ @@ -96,7 +96,25 @@ public final class FileUtils { * @throws IOException Read failed */ public static byte[] readFile(File file) throws IOException { - return read(new FileInputStream(file)); + return read(Files.newInputStream(file.toPath()), 0L, file.length()); + } + + /** + * Read byte from input file. + * + * @param file Which file to read + * @return byte content + * @throws IOException Read failed + */ + public static byte[] readFileByOffsetAndLength(File file, long offset, long length) throws IOException { + if (offset > file.length()) { + throw new IOException("read file failed: offset " + offset + "is too large"); + } + + if (length + offset > file.length()) { + throw new IOException("read file failed"); + } + return read(Files.newInputStream(file.toPath()), offset, length); } /** @@ -119,6 +137,35 @@ public final class FileUtils { } } + /** + * Read byte from input stream. + * + * @param input Input stream + * @return File content + * @throws IOException Read failed + */ + public static byte[] read(InputStream input, long offset, long length) throws IOException { + try (ByteArrayOutputStream output = new ByteArrayOutputStream()) { + byte[] buffer = new byte[FILE_BUFFER_BLOCK]; + int read; + long readSum = 0; + input.skip(offset); + while ((read = input.read(buffer)) != FILE_END) { + readSum += read; + if (readSum <= length) { + output.write(buffer, 0, read); + } else { + long outputLength = length % FILE_BUFFER_BLOCK; + output.write(buffer, 0, (int) outputLength); + break; + } + } + return output.toByteArray(); + } finally { + close(input); + } + } + /** * Out put content to file. * -- Gitee From 8ad39c497ed9d1b9f0e8a22b58e34ad13ebafdb7 Mon Sep 17 00:00:00 2001 From: wangzeyu Date: Mon, 4 Dec 2023 17:22:20 +0800 Subject: [PATCH 02/37] try to alignment zip data Signed-off-by: wangzeyu --- .../hap/entity/zip/CentralDirectory.java | 27 ++- .../hap/entity/zip/DataDescriptor.java | 20 ++ .../hap/entity/zip/EndOfCentralDirectory.java | 20 +- .../ohos/hapsigntool/hap/entity/zip/Zip.java | 202 ++++++++++++------ .../hapsigntool/hap/entity/zip/ZipEntry.java | 47 ++-- .../hap/entity/zip/ZipEntryData.java | 130 +++++++++++ .../hap/entity/zip/ZipEntryHeader.java | 28 ++- .../hap/provider/SignProvider.java | 3 + .../com/ohos/hapsigntool/utils/FileUtils.java | 48 ++++- 9 files changed, 410 insertions(+), 115 deletions(-) create mode 100644 hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntryData.java diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/CentralDirectory.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/CentralDirectory.java index c29a899c..453850a0 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/CentralDirectory.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/CentralDirectory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Copyright (c) 2023-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -19,6 +19,11 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.charset.StandardCharsets; +/** + * resolve zip CentralDirectory data + * + * @since 2023/12/02 + */ class CentralDirectory { public static final int cdLength = 46; @@ -126,6 +131,8 @@ class CentralDirectory { */ private String comment; + private int length; + public static CentralDirectory initCentralDirectory(byte[] bytes, int offset) { if (bytes.length < offset) { return null; @@ -155,7 +162,9 @@ class CentralDirectory { cd.setExternalFile(bf.getInt()); cd.setOffset(bf.getInt()); if (cd.getFileNameLength() > 0) { - cd.setFileName(new String(bf.array(), StandardCharsets.UTF_8)); + byte[] fileName = new byte[cd.getFileNameLength()]; + bf.get(fileName); + cd.setFileName(new String(fileName, StandardCharsets.UTF_8)); } if (cd.getExtraLength() > 0) { byte[] extra = new byte[cd.getExtraLength()]; @@ -163,13 +172,15 @@ class CentralDirectory { cd.setExtraData(extra); } if (cd.getCommentLength() > 0) { - cd.setComment(new String(bf.array(), StandardCharsets.UTF_8)); + byte[] comment = new byte[cd.getCommentLength()]; + bf.get(comment); + cd.setComment(new String(comment, StandardCharsets.UTF_8)); } + cd.setLength(cdLength + cd.getFileNameLength() + cd.getExtraLength() + cd.getCommentLength()); return cd; } public byte[] toBytes() { - int length = cdLength + fileNameLength + extraLength + commentLength; ByteBuffer bf = ByteBuffer.allocate(length).order(ByteOrder.LITTLE_ENDIAN); bf.putInt(signature); bf.putShort(version); @@ -351,4 +362,12 @@ class CentralDirectory { public void setComment(String comment) { this.comment = comment; } + + public int getLength() { + return length; + } + + public void setLength(int length) { + this.length = length; + } } \ No newline at end of file diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/DataDescriptor.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/DataDescriptor.java index 436d6fe8..83a543f3 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/DataDescriptor.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/DataDescriptor.java @@ -1,8 +1,28 @@ +/* + * Copyright (c) 2023-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package com.ohos.hapsigntool.hap.entity.zip; import java.nio.ByteBuffer; import java.nio.ByteOrder; +/** + * resolve zip DataDescriptor data + * + * @since 2023/12/02 + */ public class DataDescriptor { public static final int desLength = 12; diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/EndOfCentralDirectory.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/EndOfCentralDirectory.java index 5d75de47..51eead07 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/EndOfCentralDirectory.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/EndOfCentralDirectory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Copyright (c) 2023-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -19,6 +19,11 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.charset.StandardCharsets; +/** + * resolve zip EndOfCentralDirectory data + * + * @since 2023/12/04 + */ class EndOfCentralDirectory { public static final int eocdLength = 22; @@ -68,6 +73,8 @@ class EndOfCentralDirectory { */ private String comment; + private int length; + public static EndOfCentralDirectory initEOCDByBytes(byte[] bytes) { EndOfCentralDirectory eocd = new EndOfCentralDirectory(); ByteBuffer bf = ByteBuffer.allocate(bytes.length); @@ -89,6 +96,7 @@ class EndOfCentralDirectory { bf.get(comment); eocd.setComment(new String(comment, StandardCharsets.UTF_8)); } + eocd.setLength(eocdLength + eocd.getCommentLength()); if (bf.remaining() != 0) { return null; } @@ -96,7 +104,7 @@ class EndOfCentralDirectory { } public byte[] toBytes() { - ByteBuffer bf = ByteBuffer.allocate(eocdLength + commentLength).order(ByteOrder.LITTLE_ENDIAN); + ByteBuffer bf = ByteBuffer.allocate(length).order(ByteOrder.LITTLE_ENDIAN); bf.putInt(signature); bf.putShort(diskNum); bf.putShort(CDStartDiskNum); @@ -174,4 +182,12 @@ class EndOfCentralDirectory { public void setComment(String comment) { this.comment = comment; } + + public int getLength() { + return length; + } + + public void setLength(int length) { + this.length = length; + } } \ No newline at end of file diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/Zip.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/Zip.java index 5642da42..093d51ce 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/Zip.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/Zip.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Copyright (c) 2023-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -18,13 +18,22 @@ package com.ohos.hapsigntool.hap.entity.zip; import com.ohos.hapsigntool.error.ZipException; import com.ohos.hapsigntool.utils.FileUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; +/** + * resolve zip data + * + * @since 2023/12/02 + */ public class Zip { + private static final Logger LOGGER = LogManager.getLogger(Zip.class); + private List zipEntries; private long signingOffset; @@ -33,24 +42,38 @@ public class Zip { private long CDOffset; - private List centralDirectories; - private long EOCDOffset; private EndOfCentralDirectory endOfCentralDirectory; private String file; + private final List suffix4K = new ArrayList() {{ + add(".so"); + add(".abc"); + }}; + + private final short unCompressMethod = 0; + public Zip(File file) throws IOException { + long start = System.currentTimeMillis(); this.file = file.getPath(); // 1. get eocd data endOfCentralDirectory = getZipEndOfCentralDirectory(file); + long EOCD = System.currentTimeMillis(); + LOGGER.info("read EOCD use " + (EOCD - start) + "ms"); // 2. use eocd's cd offset, get cd data - centralDirectories = getZipCentralDirectory(file); + getZipCentralDirectory(file); + long CD = System.currentTimeMillis(); + LOGGER.info("read CD use " + (CD - EOCD) + "ms"); // 3. use cd's entry offset and file size, get entry data - zipEntries = getZipEntries(file); - // 4. file data - eocd - cd - entry = sign block + getZipEntries(file); + long entry = System.currentTimeMillis(); + LOGGER.info("read entry use " + (entry - CD) + "ms"); + // 4. file all data - eocd - cd - entry = sign block signingBlock = getSigningBlock(file); + long signBlock = System.currentTimeMillis(); + LOGGER.info("read signBlock use " + (signBlock - entry) + "ms"); } private EndOfCentralDirectory getZipEndOfCentralDirectory(File file) throws IOException { @@ -83,8 +106,8 @@ public class Zip { throw new ZipException("read zip failed: can not find eocd in file"); } - private List getZipCentralDirectory(File file) throws IOException { - List cdList = new ArrayList<>(endOfCentralDirectory.getCDTotal()); + private void getZipCentralDirectory(File file) throws IOException { + zipEntries = new ArrayList<>(endOfCentralDirectory.getCDTotal()); CDOffset = endOfCentralDirectory.getOffset(); byte[] cdBytes = FileUtils.readFileByOffsetAndLength(file, CDOffset, endOfCentralDirectory.getCDSize()); if (cdBytes.length < CentralDirectory.cdLength) { @@ -96,77 +119,130 @@ public class Zip { if (cd == null) { throw new ZipException("find zip cd failed"); } - cdList.add(cd); + ZipEntry entry = new ZipEntry(); + entry.setCentralDirectory(cd); + zipEntries.add(entry); offset += CentralDirectory.cdLength + cd.getFileNameLength() + cd.getExtraLength() + cd.getCommentLength(); } - return cdList; } private byte[] getSigningBlock(File file) throws IOException { return FileUtils.readFileByOffsetAndLength(file, signingOffset, CDOffset - signingOffset); } - private List getZipEntries(File file) throws IOException { - List entryList = new ArrayList<>(); - for (CentralDirectory cd : centralDirectories) { + private void getZipEntries(File file) throws IOException { + for (ZipEntry entry : zipEntries) { + CentralDirectory cd = entry.getCentralDirectory(); long offset = cd.getOffset(); long fileSize = cd.getCompressedSize(); - entryList.add(initZipEntry(file, offset, fileSize)); + short flag = cd.getFlag(); + short i = 0x08; + // set desc null flag + boolean descFlag = (flag & i) != 0; + entry.setZipEntryData(ZipEntryData.initZipEntry(file, offset, fileSize, descFlag)); } - return entryList; + ZipEntry endEntry = zipEntries.get(zipEntries.size() - 1); + CentralDirectory endCD = endEntry.getCentralDirectory(); + ZipEntryData endEntryData = endEntry.getZipEntryData(); + signingOffset = endCD.getOffset() + endEntryData.getLength(); } - private ZipEntry initZipEntry(File file, long entryOffset, long fileSize) throws IOException { - ZipEntry entry = new ZipEntry(); - long offset = entryOffset; - byte[] headBytes = FileUtils.readFileByOffsetAndLength(file, offset, ZipEntryHeader.headerLength); - ZipEntryHeader zipEntryHeader = ZipEntryHeader.initZipEntryHeader(headBytes); - if (zipEntryHeader == null) { - throw new ZipException("find zip entry head failed"); - } - offset += ZipEntryHeader.headerLength; - byte[] nameExtra = FileUtils.readFileByOffsetAndLength(file, offset, zipEntryHeader.getFileNameLength() + zipEntryHeader.getExtraLength()); - zipEntryHeader.setNameAndExtra(nameExtra); - - offset += zipEntryHeader.getFileNameLength() + zipEntryHeader.getExtraLength(); - entry.setFileOffset(offset); - entry.setFileSize(fileSize); - - offset += fileSize; - byte[] desBytes = FileUtils.readFileByOffsetAndLength(file, offset, DataDescriptor.desLength); - DataDescriptor dataDescriptor = DataDescriptor.initDataDescriptor(desBytes); - if (dataDescriptor == null) { - throw new ZipException("find zip entry desc failed"); + public void toFile(String file) throws IOException { + File f = new File(file); + if (!f.exists()) { + f.createNewFile(); } - - entry.setDataDescriptor(dataDescriptor); - entry.setZipEntryHeader(zipEntryHeader); - return entry; - } - - public void toFile(String file) { - for (ZipEntry zipEntry : zipEntries) { - FileUtils.writeByteToOutFile(zipEntry.getZipEntryHeader().toBytes(), file); - // TODO 需要根据源文件,按照offset写入压缩后数据 -// FileUtils.wri(zipEntry.getZipEntryData(), file); - FileUtils.writeByteToOutFile(zipEntry.getDataDescriptor().toBytes(), file); + FileUtils.write(new byte[]{}, f); + long start = System.currentTimeMillis(); + + for (ZipEntry entry : zipEntries) { + ZipEntryData zipEntryData = entry.getZipEntryData(); + FileUtils.writeByteToOutFile(zipEntryData.getZipEntryHeader().toBytes(), file); + FileUtils.writeFileByOffsetToFile(this.file, file, zipEntryData.getFileOffset(), zipEntryData.getFileSize()); + if (zipEntryData.getDataDescriptor() != null) { + FileUtils.writeByteToOutFile(zipEntryData.getDataDescriptor().toBytes(), file); + } } FileUtils.writeByteToOutFile(signingBlock, file); - for (CentralDirectory cd : centralDirectories) { + for (ZipEntry entry : zipEntries) { + CentralDirectory cd = entry.getCentralDirectory(); FileUtils.writeByteToOutFile(cd.toBytes(), file); } FileUtils.writeByteToOutFile(endOfCentralDirectory.toBytes(), file); + long end = System.currentTimeMillis(); + LOGGER.info("write file use " + (end - start) + "ms"); } - public void alignment() { - // TODO 字节对齐逻辑 + public void alignment() throws ZipException { + for (ZipEntry entry : zipEntries) { + ZipEntryData zipEntryData = entry.getZipEntryData(); + short method = zipEntryData.getZipEntryHeader().getMethod(); + // only align uncompressed entry. + if (method != unCompressMethod) { + continue; + } + // some file align 4096 byte. + if (is4kAlignSuffix(zipEntryData.getZipEntryHeader().getFileName())) { + short align4kBytes = 4096; + short alignment = zipEntryData.alignment(align4kBytes); + if (alignment > 0) { + int offset = entry.getCentralDirectory().getOffset() + alignment; + entry.getCentralDirectory().setOffset(offset); + endOfCentralDirectory.setOffset(endOfCentralDirectory.getOffset() + alignment); + } + } else { + // other file align 4 byte. + short align4Bytes = 4; + short alignment = zipEntryData.alignment(align4Bytes); + if (alignment > 0) { + int offset = entry.getCentralDirectory().getOffset() + alignment; + entry.getCentralDirectory().setOffset(offset); + endOfCentralDirectory.setOffset(endOfCentralDirectory.getOffset() + alignment); + } + } + } } - public List getZipEntries() { - return zipEntries; + + public void sort() { + int unCompressOffset = 0; + int CompressOffset = zipEntries.size() - 1; + int pointer = 0; + // sort uncompress file (so, abc) - other uncompress file - compress file + while (pointer <= CompressOffset) { + ZipEntry entry = zipEntries.get(pointer); + if (is4kAlignSuffix(entry.getZipEntryData().getZipEntryHeader().getFileName()) + && entry.getZipEntryData().getZipEntryHeader().getMethod() == unCompressMethod) { + ZipEntry temp = zipEntries.get(unCompressOffset); + zipEntries.set(unCompressOffset, zipEntries.get(pointer)); + zipEntries.set(pointer, temp); + unCompressOffset++; + pointer++; + continue; + } + if (entry.getZipEntryData().getZipEntryHeader().getMethod() != unCompressMethod) { + ZipEntry temp = zipEntries.get(CompressOffset); + zipEntries.set(CompressOffset, zipEntries.get(pointer)); + zipEntries.set(pointer, temp); + CompressOffset--; + continue; + } + pointer++; + } + // reset offset + int offset = 0; + for (ZipEntry entry : zipEntries) { + entry.getCentralDirectory().setOffset(offset); + offset += entry.getZipEntryData().getLength(); + } } - public void setZipEntries(List zipEntries) { - this.zipEntries = zipEntries; + private boolean is4kAlignSuffix(String name) { + for (String suffix : suffix4K) { + if (name.endsWith(suffix)) { + return true; + } + } + return false; } public long getSigningOffset() { @@ -193,14 +269,6 @@ public class Zip { this.CDOffset = CDOffset; } - public List getCentralDirectories() { - return centralDirectories; - } - - public void setCentralDirectories(List centralDirectories) { - this.centralDirectories = centralDirectories; - } - public long getEOCDOffset() { return EOCDOffset; } @@ -224,4 +292,12 @@ public class Zip { public void setFile(String file) { this.file = file; } + + public List getZipEntries() { + return zipEntries; + } + + public void setZipEntries(List zipEntries) { + this.zipEntries = zipEntries; + } } \ No newline at end of file diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntry.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntry.java index 080cfb70..59fe7c0b 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntry.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Copyright (c) 2023-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -15,44 +15,29 @@ package com.ohos.hapsigntool.hap.entity.zip; +/** + * ZipEntry and CentralDirectory data + * + * @since 2023/12/02 + */ class ZipEntry { - private ZipEntryHeader zipEntryHeader; - - private long fileOffset; - - private long fileSize; - - private DataDescriptor dataDescriptor; - - public ZipEntryHeader getZipEntryHeader() { - return zipEntryHeader; - } - - public void setZipEntryHeader(ZipEntryHeader zipEntryHeader) { - this.zipEntryHeader = zipEntryHeader; - } + private ZipEntryData zipEntryData; - public DataDescriptor getDataDescriptor() { - return dataDescriptor; - } - - public void setDataDescriptor(DataDescriptor dataDescriptor) { - this.dataDescriptor = dataDescriptor; - } + private CentralDirectory centralDirectory; - public long getFileOffset() { - return fileOffset; + public ZipEntryData getZipEntryData() { + return zipEntryData; } - public void setFileOffset(long fileOffset) { - this.fileOffset = fileOffset; + public void setZipEntryData(ZipEntryData zipEntryData) { + this.zipEntryData = zipEntryData; } - public long getFileSize() { - return fileSize; + public CentralDirectory getCentralDirectory() { + return centralDirectory; } - public void setFileSize(long fileSize) { - this.fileSize = fileSize; + public void setCentralDirectory(CentralDirectory centralDirectory) { + this.centralDirectory = centralDirectory; } } \ No newline at end of file diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntryData.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntryData.java new file mode 100644 index 00000000..5bdd1575 --- /dev/null +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntryData.java @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2023-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.ohos.hapsigntool.hap.entity.zip; + +import com.ohos.hapsigntool.error.ZipException; +import com.ohos.hapsigntool.utils.FileUtils; + +import java.io.File; +import java.io.IOException; + +/** + * resolve zip ZipEntry data + * + * @since 2023/12/04 + */ +class ZipEntryData { + private ZipEntryHeader zipEntryHeader; + + private long fileOffset; + + private long fileSize; + + private DataDescriptor dataDescriptor; + + private long length; + + public ZipEntryHeader getZipEntryHeader() { + return zipEntryHeader; + } + + public static ZipEntryData initZipEntry(File file, long entryOffset, long fileSize, boolean descFlag) throws IOException { + ZipEntryData entry = new ZipEntryData(); + long offset = entryOffset; + byte[] headBytes = FileUtils.readFileByOffsetAndLength(file, offset, ZipEntryHeader.headerLength); + ZipEntryHeader zipEntryHeader = ZipEntryHeader.initZipEntryHeader(headBytes); + if (zipEntryHeader == null) { + throw new ZipException("find zip entry head failed"); + } + offset += ZipEntryHeader.headerLength; + byte[] nameAndExtra = FileUtils.readFileByOffsetAndLength(file, offset, + zipEntryHeader.getFileNameLength() + zipEntryHeader.getExtraLength()); + zipEntryHeader.setNameAndExtra(nameAndExtra); + + offset += zipEntryHeader.getFileNameLength() + zipEntryHeader.getExtraLength(); + entry.setFileOffset(offset); + entry.setFileSize(fileSize); + + offset += fileSize; + long length = zipEntryHeader.getLength() + fileSize; + + if (descFlag) { + byte[] desBytes = FileUtils.readFileByOffsetAndLength(file, offset, DataDescriptor.desLength); + DataDescriptor dataDescriptor = DataDescriptor.initDataDescriptor(desBytes); + if (dataDescriptor == null) { + throw new ZipException("find zip entry desc failed"); + } + length += DataDescriptor.desLength; + entry.setDataDescriptor(dataDescriptor); + } + + entry.setZipEntryHeader(zipEntryHeader); + entry.setLength(length); + return entry; + } + + public short alignment(short alignNum) throws ZipException { + long add = alignNum - length % alignNum; + if (add > Short.MAX_VALUE) { + throw new ZipException("can not align " + zipEntryHeader.getFileName()); + } + int newExtraLength = zipEntryHeader.getExtraLength() + (short) add; + if (newExtraLength > Short.MAX_VALUE) { + throw new ZipException("can not align " + zipEntryHeader.getFileName()); + } + short length = (short) newExtraLength; + zipEntryHeader.setExtraLength(length); + byte[] extra = new byte[length]; + zipEntryHeader.setExtraData(extra); + return (short) add; + } + + public void setZipEntryHeader(ZipEntryHeader zipEntryHeader) { + this.zipEntryHeader = zipEntryHeader; + } + + public DataDescriptor getDataDescriptor() { + return dataDescriptor; + } + + public void setDataDescriptor(DataDescriptor dataDescriptor) { + this.dataDescriptor = dataDescriptor; + } + + public long getFileOffset() { + return fileOffset; + } + + public void setFileOffset(long fileOffset) { + this.fileOffset = fileOffset; + } + + public long getFileSize() { + return fileSize; + } + + public void setFileSize(long fileSize) { + this.fileSize = fileSize; + } + + public long getLength() { + return length; + } + + public void setLength(long length) { + this.length = length; + } +} \ No newline at end of file diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntryHeader.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntryHeader.java index 477f9ca1..d005cd38 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntryHeader.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntryHeader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022-2023 Huawei Device Co., Ltd. + * Copyright (c) 2023-2023 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -20,6 +20,11 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.charset.StandardCharsets; +/** + * resolve zip ZipEntryHeader data + * + * @since 2023/12/02 + */ class ZipEntryHeader { public static int headerLength = 30; @@ -88,6 +93,8 @@ class ZipEntryHeader { */ private byte[] extraData; + private int length; + public static ZipEntryHeader initZipEntryHeader(byte[] bytes) { ZipEntryHeader entryHeader = new ZipEntryHeader(); ByteBuffer bf = ByteBuffer.allocate(bytes.length); @@ -107,7 +114,7 @@ class ZipEntryHeader { entryHeader.setUnCompressedSize(bf.getInt()); entryHeader.setFileNameLength(bf.getShort()); entryHeader.setExtraLength(bf.getShort()); - + entryHeader.setLength(headerLength + entryHeader.getFileNameLength() + entryHeader.getExtraLength()); return entryHeader; } @@ -129,7 +136,6 @@ class ZipEntryHeader { } public byte[] toBytes() { - int length = headerLength + fileNameLength + extraLength; ByteBuffer bf = ByteBuffer.allocate(length).order(ByteOrder.LITTLE_ENDIAN); bf.putInt(signature); bf.putShort(version); @@ -151,14 +157,6 @@ class ZipEntryHeader { return bf.array(); } - public static int getHeaderLength() { - return headerLength; - } - - public static void setHeaderLength(int headerLength) { - ZipEntryHeader.headerLength = headerLength; - } - public short getVersion() { return version; } @@ -254,4 +252,12 @@ class ZipEntryHeader { public void setExtraData(byte[] extraData) { this.extraData = extraData; } + + public int getLength() { + return length; + } + + public void setLength(int length) { + this.length = length; + } } \ No newline at end of file diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/provider/SignProvider.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/provider/SignProvider.java index 44b5ac94..b00b96dd 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/provider/SignProvider.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/provider/SignProvider.java @@ -506,6 +506,9 @@ public abstract class SignProvider { private void copyFileAndAlignment(File input, File tmpOutput, int alignment) throws IOException, HapFormatException { Zip zip = new Zip(input); + zip.alignment(); + zip.sort(); + zip.toFile("a.zip"); try (JarFile inputJar = new JarFile(input, false); FileOutputStream outputFile = new FileOutputStream(tmpOutput); JarOutputStream outputJar = new JarOutputStream(outputFile)) { diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/utils/FileUtils.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/utils/FileUtils.java index 2fd4947d..cdc8a8ce 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/utils/FileUtils.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/utils/FileUtils.java @@ -58,7 +58,7 @@ public final class FileUtils { /** * File reader block size */ - public static final int FILE_BUFFER_BLOCK = 16 * 1024; + public static final int FILE_BUFFER_BLOCK = 1024 * 1024; /** * File end */ @@ -233,6 +233,46 @@ public final class FileUtils { return temps[temps.length - 1]; } + /** + * Write data in file to output stream + * + * @param inFile input file path. + * @param outFile output file path. + * @param offset file read offset + * @param size file read size + * @return true, if write successfully. + */ + public static boolean writeFileByOffsetToFile(String inFile, String outFile, long offset, long size) { + if (StringUtils.isEmpty(outFile)) { + return false; + } + File src = new File(inFile); + File outPutFile = new File(outFile); + try (FileInputStream fileStream = new FileInputStream(src); + FileOutputStream fos = new FileOutputStream(outPutFile, true)) { + byte[] buffer = new byte[FILE_BUFFER_BLOCK]; + int read; + long readSum = 0; + fileStream.skip(offset); + while ((read = fileStream.read(buffer)) != FILE_END) { + readSum += read; + if (readSum <= size) { + fos.write(buffer, 0, read); + } else { + long outputLength = size % FILE_BUFFER_BLOCK; + fos.write(buffer, 0, (int) outputLength); + break; + } + } + return true; + } catch (FileNotFoundException e) { + LOGGER.error("Failed to get input stream object."); + } catch (IOException e) { + LOGGER.error("Failed to read or write data."); + } + return false; + } + /** * Write data in file to output stream * @@ -297,13 +337,13 @@ public final class FileUtils { /** * Write byte array data to output file. * - * @param signHeadByte byte array data. + * @param bytes byte array data. * @param outFile output file path. * @return true, if write successfully. */ - public static boolean writeByteToOutFile(byte[] signHeadByte, String outFile) { + public static boolean writeByteToOutFile(byte[] bytes, String outFile) { try (OutputStream ops = new FileOutputStream(outFile, true)) { - ops.write(signHeadByte, 0, signHeadByte.length); + ops.write(bytes, 0, bytes.length); ops.flush(); return true; } catch (FileNotFoundException e) { -- Gitee From 56dcda361ce4e7c0a52b0526be46c8f76f216711 Mon Sep 17 00:00:00 2001 From: wangzeyu Date: Mon, 4 Dec 2023 18:06:12 +0800 Subject: [PATCH 03/37] try to alignment zip data Signed-off-by: wangzeyu --- .../com/ohos/hapsigntool/hap/entity/zip/ZipEntryData.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntryData.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntryData.java index 5bdd1575..49c08fa2 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntryData.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntryData.java @@ -89,6 +89,13 @@ class ZipEntryData { zipEntryHeader.setExtraLength(length); byte[] extra = new byte[length]; zipEntryHeader.setExtraData(extra); + zipEntryHeader.setExtraLength(length); + int newLength = ZipEntryHeader.headerLength + + zipEntryHeader.getFileNameLength() + zipEntryHeader.getExtraData().length; + if (zipEntryHeader.getLength() + add != newLength) { + throw new ZipException("can not align " + zipEntryHeader.getFileName()); + } + zipEntryHeader.setLength(newLength); return (short) add; } -- Gitee From 8ab70caf6a177c5eb26596a4490cef547f679699 Mon Sep 17 00:00:00 2001 From: wangzeyu Date: Tue, 5 Dec 2023 02:06:54 +0000 Subject: [PATCH 04/37] codecheck repair Signed-off-by: wangzeyu --- .../hap/entity/zip/CentralDirectory.java | 39 +++++++++++++------ 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/CentralDirectory.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/CentralDirectory.java index 453850a0..55d981f1 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/CentralDirectory.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/CentralDirectory.java @@ -25,12 +25,15 @@ import java.nio.charset.StandardCharsets; * @since 2023/12/02 */ class CentralDirectory { - public static final int cdLength = 46; + /** + * central directory invariable bytes length + */ + public static final int CD_LENGTH = 46; /** - * 4 bytes + * 4 bytes , central directory signature */ - public static final int signature = 0x02014b50; + public static final int SIGNATURE = 0x02014b50; /** * 2 bytes @@ -133,6 +136,13 @@ class CentralDirectory { private int length; + /** + * init Central Directory + * + * @param bytes Full Central Directory bytes + * @param offset One Central Directory offset + * @return CentralDirectory + */ public static CentralDirectory initCentralDirectory(byte[] bytes, int offset) { if (bytes.length < offset) { return null; @@ -142,7 +152,7 @@ class CentralDirectory { bf.put(bytes, offset, bytes.length - offset); bf.order(ByteOrder.LITTLE_ENDIAN); bf.flip(); - if (bf.getInt() != signature) { + if (bf.getInt() != SIGNATURE) { return null; } cd.setVersion(bf.getShort()); @@ -162,9 +172,9 @@ class CentralDirectory { cd.setExternalFile(bf.getInt()); cd.setOffset(bf.getInt()); if (cd.getFileNameLength() > 0) { - byte[] fileName = new byte[cd.getFileNameLength()]; - bf.get(fileName); - cd.setFileName(new String(fileName, StandardCharsets.UTF_8)); + byte[] readFileName = new byte[cd.getFileNameLength()]; + bf.get(readFileName); + cd.setFileName(new String(readFileName, StandardCharsets.UTF_8)); } if (cd.getExtraLength() > 0) { byte[] extra = new byte[cd.getExtraLength()]; @@ -172,17 +182,22 @@ class CentralDirectory { cd.setExtraData(extra); } if (cd.getCommentLength() > 0) { - byte[] comment = new byte[cd.getCommentLength()]; - bf.get(comment); - cd.setComment(new String(comment, StandardCharsets.UTF_8)); + byte[] readComment = new byte[cd.getCommentLength()]; + bf.get(readComment); + cd.setComment(new String(readComment, StandardCharsets.UTF_8)); } - cd.setLength(cdLength + cd.getFileNameLength() + cd.getExtraLength() + cd.getCommentLength()); + cd.setLength(CD_LENGTH + cd.getFileNameLength() + cd.getExtraLength() + cd.getCommentLength()); return cd; } + /** + * change Central Directory to bytes + * + * @return bytes + */ public byte[] toBytes() { ByteBuffer bf = ByteBuffer.allocate(length).order(ByteOrder.LITTLE_ENDIAN); - bf.putInt(signature); + bf.putInt(SIGNATURE); bf.putShort(version); bf.putShort(versionExtra); bf.putShort(flag); -- Gitee From 5696627192df827207fba9f5c3e0478ce8774dd2 Mon Sep 17 00:00:00 2001 From: wangzeyu Date: Tue, 5 Dec 2023 02:07:27 +0000 Subject: [PATCH 05/37] codecheck repair Signed-off-by: wangzeyu --- .../hap/entity/zip/DataDescriptor.java | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/DataDescriptor.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/DataDescriptor.java index 83a543f3..ebbc7132 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/DataDescriptor.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/DataDescriptor.java @@ -24,23 +24,32 @@ import java.nio.ByteOrder; * @since 2023/12/02 */ public class DataDescriptor { - public static final int desLength = 12; + /** + * DataDescriptor invariable bytes length + */ + public static final int DES_LENGTH = 12; /** * 4 bytes */ - int crc32; + private int crc32; /** * 4 bytes */ - int compressedSize; + private int compressedSize; /** * 4 bytes */ - int unCompressedSize; + private int unCompressedSize; + /** + * init Central Directory + * + * @param bytes DataDescriptor bytes + * @return DataDescriptor + */ public static DataDescriptor initDataDescriptor(byte[] bytes) { if (bytes.length != 12) { return null; @@ -56,8 +65,13 @@ public class DataDescriptor { return data; } + /** + * change DataDescriptor to bytes + * + * @return bytes + */ public byte[] toBytes() { - ByteBuffer bf = ByteBuffer.allocate(desLength).order(ByteOrder.LITTLE_ENDIAN); + ByteBuffer bf = ByteBuffer.allocate(DES_LENGTH).order(ByteOrder.LITTLE_ENDIAN); bf.putInt(crc32); bf.putInt(compressedSize); bf.putInt(unCompressedSize); @@ -74,17 +88,3 @@ public class DataDescriptor { public int getCompressedSize() { return compressedSize; - } - - public void setCompressedSize(int compressedSize) { - this.compressedSize = compressedSize; - } - - public int getUnCompressedSize() { - return unCompressedSize; - } - - public void setUnCompressedSize(int unCompressedSize) { - this.unCompressedSize = unCompressedSize; - } -} -- Gitee From c9a7a5e721d23c60141fc9b94e775b8a36750388 Mon Sep 17 00:00:00 2001 From: wangzeyu Date: Tue, 5 Dec 2023 02:07:45 +0000 Subject: [PATCH 06/37] codecheck repair Signed-off-by: wangzeyu --- .../hap/entity/zip/EndOfCentralDirectory.java | 78 +++++++++++-------- 1 file changed, 45 insertions(+), 33 deletions(-) diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/EndOfCentralDirectory.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/EndOfCentralDirectory.java index 51eead07..272935a5 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/EndOfCentralDirectory.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/EndOfCentralDirectory.java @@ -25,23 +25,25 @@ import java.nio.charset.StandardCharsets; * @since 2023/12/04 */ class EndOfCentralDirectory { - public static final int eocdLength = 22; + /** + * EndOfCentralDirectory invariable bytes length + */ + public static final int EOCD_LENGTH = 22; /** - * 4 bytes + * 4 bytes , central directory signature */ - public static final int signature = 0x06054b50; + public static final int SIGNATURE = 0x06054b50; /** * 2 bytes */ private short diskNum; - /** * 2 bytes */ - private short CDStartDiskNum; + private short cDStartDiskNum; /** * 2 bytes @@ -51,12 +53,12 @@ class EndOfCentralDirectory { /** * 2 bytes */ - private short CDTotal; + private short cDTotal; /** * 4 bytes */ - private int CDSize; + private int cDSize; /** * 4 bytes @@ -75,13 +77,19 @@ class EndOfCentralDirectory { private int length; + /** + * init End Of Central Directory + * + * @param bytes End Of Central Directory bytes + * @return End Of Central Directory + */ public static EndOfCentralDirectory initEOCDByBytes(byte[] bytes) { EndOfCentralDirectory eocd = new EndOfCentralDirectory(); ByteBuffer bf = ByteBuffer.allocate(bytes.length); bf.put(bytes); bf.order(ByteOrder.LITTLE_ENDIAN); bf.flip(); - if (bf.getInt() != signature) { + if (bf.getInt() != SIGNATURE) { return null; } eocd.setDiskNum(bf.getShort()); @@ -92,25 +100,30 @@ class EndOfCentralDirectory { eocd.setOffset(bf.getInt()); eocd.setCommentLength(bf.getShort()); if (eocd.getCommentLength() > 0) { - byte[] comment = new byte[eocd.getCommentLength()]; - bf.get(comment); - eocd.setComment(new String(comment, StandardCharsets.UTF_8)); + byte[] readComment = new byte[eocd.getCommentLength()]; + bf.get(readComment); + eocd.setComment(new String(readComment, StandardCharsets.UTF_8)); } - eocd.setLength(eocdLength + eocd.getCommentLength()); + eocd.setLength(EOCD_LENGTH + eocd.getCommentLength()); if (bf.remaining() != 0) { return null; } return eocd; } + /** + * change End Of Central Directory to bytes + * + * @return bytes + */ public byte[] toBytes() { ByteBuffer bf = ByteBuffer.allocate(length).order(ByteOrder.LITTLE_ENDIAN); - bf.putInt(signature); + bf.putInt(SIGNATURE); bf.putShort(diskNum); - bf.putShort(CDStartDiskNum); + bf.putShort(cDStartDiskNum); bf.putShort(thisDiskCDNum); - bf.putShort(CDTotal); - bf.putInt(CDSize); + bf.putShort(cDTotal); + bf.putInt(cDSize); bf.putInt(offset); bf.putShort(commentLength); if (commentLength > 0) { @@ -128,11 +141,11 @@ class EndOfCentralDirectory { } public short getCDStartDiskNum() { - return CDStartDiskNum; + return cDStartDiskNum; } - public void setCDStartDiskNum(short CDStartDiskNum) { - this.CDStartDiskNum = CDStartDiskNum; + public void setCDStartDiskNum(short cDStartDiskNum) { + this.cDStartDiskNum = cDStartDiskNum; } public short getThisDiskCDNum() { @@ -144,19 +157,19 @@ class EndOfCentralDirectory { } public short getCDTotal() { - return CDTotal; + return cDTotal; } - public void setCDTotal(short CDTotal) { - this.CDTotal = CDTotal; + public void setCDTotal(short cDTotal) { + this.cDTotal = cDTotal; } public int getCDSize() { - return CDSize; + return cDSize; } - public void setCDSize(int CDSize) { - this.CDSize = CDSize; + public void setCDSize(int cDSize) { + this.cDSize = cDSize; } public int getOffset() { @@ -175,14 +188,6 @@ class EndOfCentralDirectory { this.commentLength = commentLength; } - public String getComment() { - return comment; - } - - public void setComment(String comment) { - this.comment = comment; - } - public int getLength() { return length; } @@ -190,4 +195,11 @@ class EndOfCentralDirectory { public void setLength(int length) { this.length = length; } + public String getComment() { + return comment; + } + + public void setComment(String comment) { + this.comment = comment; + } } \ No newline at end of file -- Gitee From 9960ff556835266881b8f3ede440257b1cb0bafb Mon Sep 17 00:00:00 2001 From: wangzeyu Date: Tue, 5 Dec 2023 02:08:51 +0000 Subject: [PATCH 07/37] codecheck repair Signed-off-by: wangzeyu --- .../ohos/hapsigntool/hap/entity/zip/Zip.java | 125 +++++++++++------- 1 file changed, 79 insertions(+), 46 deletions(-) diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/Zip.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/Zip.java index 093d51ce..17a8fb7b 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/Zip.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/Zip.java @@ -15,9 +15,9 @@ package com.ohos.hapsigntool.hap.entity.zip; - import com.ohos.hapsigntool.error.ZipException; import com.ohos.hapsigntool.utils.FileUtils; + import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -40,9 +40,9 @@ public class Zip { private byte[] signingBlock; - private long CDOffset; + private long cDOffset; - private long EOCDOffset; + private long eOCDOffset; private EndOfCentralDirectory endOfCentralDirectory; @@ -55,21 +55,27 @@ public class Zip { private final short unCompressMethod = 0; + /** + * create Zip by file + * + * @param file file + * @throws IOException read file exception + */ public Zip(File file) throws IOException { long start = System.currentTimeMillis(); this.file = file.getPath(); // 1. get eocd data endOfCentralDirectory = getZipEndOfCentralDirectory(file); - long EOCD = System.currentTimeMillis(); - LOGGER.info("read EOCD use " + (EOCD - start) + "ms"); + long eocd = System.currentTimeMillis(); + LOGGER.info("read EOCD use " + (eocd - start) + "ms"); // 2. use eocd's cd offset, get cd data getZipCentralDirectory(file); - long CD = System.currentTimeMillis(); - LOGGER.info("read CD use " + (CD - EOCD) + "ms"); + long cd = System.currentTimeMillis(); + LOGGER.info("read CD use " + (cd - eocd) + "ms"); // 3. use cd's entry offset and file size, get entry data getZipEntries(file); long entry = System.currentTimeMillis(); - LOGGER.info("read entry use " + (entry - CD) + "ms"); + LOGGER.info("read entry use " + (entry - cd) + "ms"); // 4. file all data - eocd - cd - entry = sign block signingBlock = getSigningBlock(file); long signBlock = System.currentTimeMillis(); @@ -77,29 +83,28 @@ public class Zip { } private EndOfCentralDirectory getZipEndOfCentralDirectory(File file) throws IOException { - EndOfCentralDirectory eocd; - if (file.length() < EndOfCentralDirectory.eocdLength) { + if (file.length() < EndOfCentralDirectory.EOCD_LENGTH) { throw new ZipException("find zip eocd failed"); } // try to read EOCD without comment - int eocdMaxLength = EndOfCentralDirectory.eocdLength; - EOCDOffset = file.length() - eocdMaxLength; - byte[] bytes = FileUtils.readFileByOffsetAndLength(file, EOCDOffset, eocdMaxLength); - eocd = EndOfCentralDirectory.initEOCDByBytes(bytes); + int eocdMaxLength = EndOfCentralDirectory.EOCD_LENGTH; + eOCDOffset = file.length() - eocdMaxLength; + byte[] bytes = FileUtils.readFileByOffsetAndLength(file, eOCDOffset, eocdMaxLength); + EndOfCentralDirectory eocd = EndOfCentralDirectory.initEOCDByBytes(bytes); if (eocd != null) { return eocd; } - //try to search EOCD with comment + // try to search EOCD with comment int maxCommentLength = 65535; - eocdMaxLength = EndOfCentralDirectory.eocdLength + maxCommentLength; - EOCDOffset = file.length() - eocdMaxLength; - bytes = FileUtils.readFileByOffsetAndLength(file, EOCDOffset, eocdMaxLength); + eocdMaxLength = EndOfCentralDirectory.EOCD_LENGTH + maxCommentLength; + eOCDOffset = file.length() - eocdMaxLength; + bytes = FileUtils.readFileByOffsetAndLength(file, eOCDOffset, eocdMaxLength); for (int start = 0; start < eocdMaxLength; start++) { eocd = EndOfCentralDirectory.initEOCDByBytes(bytes); if (eocd != null) { - EOCDOffset += start; + eOCDOffset += start; return eocd; } } @@ -108,9 +113,9 @@ public class Zip { private void getZipCentralDirectory(File file) throws IOException { zipEntries = new ArrayList<>(endOfCentralDirectory.getCDTotal()); - CDOffset = endOfCentralDirectory.getOffset(); - byte[] cdBytes = FileUtils.readFileByOffsetAndLength(file, CDOffset, endOfCentralDirectory.getCDSize()); - if (cdBytes.length < CentralDirectory.cdLength) { + cDOffset = endOfCentralDirectory.getOffset(); + byte[] cdBytes = FileUtils.readFileByOffsetAndLength(file, cDOffset, endOfCentralDirectory.getCDSize()); + if (cdBytes.length < CentralDirectory.CD_LENGTH) { throw new ZipException("find zip cd failed"); } int offset = 0; @@ -122,12 +127,12 @@ public class Zip { ZipEntry entry = new ZipEntry(); entry.setCentralDirectory(cd); zipEntries.add(entry); - offset += CentralDirectory.cdLength + cd.getFileNameLength() + cd.getExtraLength() + cd.getCommentLength(); + offset += CentralDirectory.CD_LENGTH + cd.getFileNameLength() + cd.getExtraLength() + cd.getCommentLength(); } } private byte[] getSigningBlock(File file) throws IOException { - return FileUtils.readFileByOffsetAndLength(file, signingOffset, CDOffset - signingOffset); + return FileUtils.readFileByOffsetAndLength(file, signingOffset, cDOffset - signingOffset); } private void getZipEntries(File file) throws IOException { @@ -138,8 +143,8 @@ public class Zip { short flag = cd.getFlag(); short i = 0x08; // set desc null flag - boolean descFlag = (flag & i) != 0; - entry.setZipEntryData(ZipEntryData.initZipEntry(file, offset, fileSize, descFlag)); + boolean hasDesc = (flag & i) != 0; + entry.setZipEntryData(ZipEntryData.initZipEntry(file, offset, fileSize, hasDesc)); } ZipEntry endEntry = zipEntries.get(zipEntries.size() - 1); CentralDirectory endCD = endEntry.getCentralDirectory(); @@ -147,6 +152,12 @@ public class Zip { signingOffset = endCD.getOffset() + endEntryData.getLength(); } + /** + * output zip to zip file + * + * @param file file path + * @throws IOException write exception + */ public void toFile(String file) throws IOException { File f = new File(file); if (!f.exists()) { @@ -154,11 +165,11 @@ public class Zip { } FileUtils.write(new byte[]{}, f); long start = System.currentTimeMillis(); - for (ZipEntry entry : zipEntries) { ZipEntryData zipEntryData = entry.getZipEntryData(); FileUtils.writeByteToOutFile(zipEntryData.getZipEntryHeader().toBytes(), file); - FileUtils.writeFileByOffsetToFile(this.file, file, zipEntryData.getFileOffset(), zipEntryData.getFileSize()); + FileUtils.writeFileByOffsetToFile(this.file, file, + zipEntryData.getFileOffset(), zipEntryData.getFileSize()); if (zipEntryData.getDataDescriptor() != null) { FileUtils.writeByteToOutFile(zipEntryData.getDataDescriptor().toBytes(), file); } @@ -173,16 +184,22 @@ public class Zip { LOGGER.info("write file use " + (end - start) + "ms"); } + /** + * alignment uncompress entry + * + * @throws ZipException alignment exception + */ public void alignment() throws ZipException { + long start = System.currentTimeMillis(); for (ZipEntry entry : zipEntries) { ZipEntryData zipEntryData = entry.getZipEntryData(); short method = zipEntryData.getZipEntryHeader().getMethod(); - // only align uncompressed entry. if (method != unCompressMethod) { + // only align uncompressed entry. continue; } - // some file align 4096 byte. if (is4kAlignSuffix(zipEntryData.getZipEntryHeader().getFileName())) { + // some file align 4096 byte. short align4kBytes = 4096; short alignment = zipEntryData.alignment(align4kBytes); if (alignment > 0) { @@ -191,7 +208,7 @@ public class Zip { endOfCentralDirectory.setOffset(endOfCentralDirectory.getOffset() + alignment); } } else { - // other file align 4 byte. + // other file align 4 byte. short align4Bytes = 4; short alignment = zipEntryData.alignment(align4Bytes); if (alignment > 0) { @@ -201,14 +218,20 @@ public class Zip { } } } + long end = System.currentTimeMillis(); + LOGGER.info("alignment entry use " + (end - start) + "ms"); } + /** + * sort uncompress entry in the front. + */ public void sort() { + long start = System.currentTimeMillis(); int unCompressOffset = 0; - int CompressOffset = zipEntries.size() - 1; + int compressOffset = zipEntries.size() - 1; int pointer = 0; // sort uncompress file (so, abc) - other uncompress file - compress file - while (pointer <= CompressOffset) { + while (pointer <= compressOffset) { ZipEntry entry = zipEntries.get(pointer); if (is4kAlignSuffix(entry.getZipEntryData().getZipEntryHeader().getFileName()) && entry.getZipEntryData().getZipEntryHeader().getMethod() == unCompressMethod) { @@ -220,10 +243,10 @@ public class Zip { continue; } if (entry.getZipEntryData().getZipEntryHeader().getMethod() != unCompressMethod) { - ZipEntry temp = zipEntries.get(CompressOffset); - zipEntries.set(CompressOffset, zipEntries.get(pointer)); + ZipEntry temp = zipEntries.get(compressOffset); + zipEntries.set(compressOffset, zipEntries.get(pointer)); zipEntries.set(pointer, temp); - CompressOffset--; + compressOffset--; continue; } pointer++; @@ -234,6 +257,8 @@ public class Zip { entry.getCentralDirectory().setOffset(offset); offset += entry.getZipEntryData().getLength(); } + long end = System.currentTimeMillis(); + LOGGER.info("sort entry use " + (end - start) + "ms"); } private boolean is4kAlignSuffix(String name) { @@ -245,6 +270,14 @@ public class Zip { return false; } + public List getZipEntries() { + return zipEntries; + } + + public void setZipEntries(List zipEntries) { + this.zipEntries = zipEntries; + } + public long getSigningOffset() { return signingOffset; } @@ -262,19 +295,19 @@ public class Zip { } public long getCDOffset() { - return CDOffset; + return cDOffset; } - public void setCDOffset(long CDOffset) { - this.CDOffset = CDOffset; + public void setCDOffset(long cDOffset) { + this.cDOffset = cDOffset; } public long getEOCDOffset() { - return EOCDOffset; + return eOCDOffset; } - public void setEOCDOffset(long EOCDOffset) { - this.EOCDOffset = EOCDOffset; + public void setEOCDOffset(long eOCDOffset) { + this.eOCDOffset = eOCDOffset; } public EndOfCentralDirectory getEndOfCentralDirectory() { @@ -293,11 +326,11 @@ public class Zip { this.file = file; } - public List getZipEntries() { - return zipEntries; + public List getSuffix4K() { + return suffix4K; } - public void setZipEntries(List zipEntries) { - this.zipEntries = zipEntries; + public short getUnCompressMethod() { + return unCompressMethod; } } \ No newline at end of file -- Gitee From 63721b1255aca4011076d8051a4e14341cfb64c8 Mon Sep 17 00:00:00 2001 From: wangzeyu Date: Tue, 5 Dec 2023 02:09:10 +0000 Subject: [PATCH 08/37] codecheck repair Signed-off-by: wangzeyu --- .../hap/entity/zip/ZipEntryData.java | 98 ++++++++++++------- 1 file changed, 61 insertions(+), 37 deletions(-) diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntryData.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntryData.java index 49c08fa2..46831ebf 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntryData.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntryData.java @@ -19,6 +19,7 @@ import com.ohos.hapsigntool.error.ZipException; import com.ohos.hapsigntool.utils.FileUtils; import java.io.File; +import java.io.FileInputStream; import java.io.IOException; /** @@ -41,41 +42,63 @@ class ZipEntryData { return zipEntryHeader; } - public static ZipEntryData initZipEntry(File file, long entryOffset, long fileSize, boolean descFlag) throws IOException { - ZipEntryData entry = new ZipEntryData(); - long offset = entryOffset; - byte[] headBytes = FileUtils.readFileByOffsetAndLength(file, offset, ZipEntryHeader.headerLength); - ZipEntryHeader zipEntryHeader = ZipEntryHeader.initZipEntryHeader(headBytes); - if (zipEntryHeader == null) { - throw new ZipException("find zip entry head failed"); - } - offset += ZipEntryHeader.headerLength; - byte[] nameAndExtra = FileUtils.readFileByOffsetAndLength(file, offset, - zipEntryHeader.getFileNameLength() + zipEntryHeader.getExtraLength()); - zipEntryHeader.setNameAndExtra(nameAndExtra); - - offset += zipEntryHeader.getFileNameLength() + zipEntryHeader.getExtraLength(); - entry.setFileOffset(offset); - entry.setFileSize(fileSize); - - offset += fileSize; - long length = zipEntryHeader.getLength() + fileSize; - - if (descFlag) { - byte[] desBytes = FileUtils.readFileByOffsetAndLength(file, offset, DataDescriptor.desLength); - DataDescriptor dataDescriptor = DataDescriptor.initDataDescriptor(desBytes); - if (dataDescriptor == null) { - throw new ZipException("find zip entry desc failed"); + /** + * init zip entry by file + * + * @param file zip file + * @param entryOffset entry start offset + * @param compress compress file size + * @param hasDesc has data descriptor + * @return zip entry + * @throws IOException read zip exception + */ + public static ZipEntryData initZipEntry(File file, long entryOffset, long compress, boolean hasDesc) + throws IOException { + try (FileInputStream fs = new FileInputStream(file)) { + long offset = entryOffset; + fs.skip(offset); + byte[] headBytes = FileUtils.readFileByOffsetAndLength(fs, 0, ZipEntryHeader.HEADER_LENGTH); + ZipEntryHeader entryHeader = ZipEntryHeader.initZipEntryHeader(headBytes); + if (entryHeader == null) { + throw new ZipException("find zip entry head failed"); + } + offset += ZipEntryHeader.HEADER_LENGTH; + byte[] nameAndExtra = FileUtils.readFileByOffsetAndLength(fs, 0, + entryHeader.getFileNameLength() + entryHeader.getExtraLength()); + entryHeader.setNameAndExtra(nameAndExtra); + + offset += entryHeader.getFileNameLength() + entryHeader.getExtraLength(); + + ZipEntryData entry = new ZipEntryData(); + entry.setFileOffset(offset); + entry.setFileSize(compress); + fs.skip(compress); + + offset += compress; + long entryLength = entryHeader.getLength() + compress; + + if (hasDesc) { + byte[] desBytes = FileUtils.readFileByOffsetAndLength(fs, 0, DataDescriptor.DES_LENGTH); + DataDescriptor dataDesc = DataDescriptor.initDataDescriptor(desBytes); + if (dataDesc == null) { + throw new ZipException("find zip entry desc failed"); + } + entryLength += DataDescriptor.DES_LENGTH; + entry.setDataDescriptor(dataDesc); } - length += DataDescriptor.desLength; - entry.setDataDescriptor(dataDescriptor); + entry.setZipEntryHeader(entryHeader); + entry.setLength(entryLength); + return entry; } - - entry.setZipEntryHeader(zipEntryHeader); - entry.setLength(length); - return entry; } + /** + * alignment one entry + * + * @param alignNum need align bytes length + * @return add bytes length + * @throws ZipException alignment exception + */ public short alignment(short alignNum) throws ZipException { long add = alignNum - length % alignNum; if (add > Short.MAX_VALUE) { @@ -85,17 +108,18 @@ class ZipEntryData { if (newExtraLength > Short.MAX_VALUE) { throw new ZipException("can not align " + zipEntryHeader.getFileName()); } - short length = (short) newExtraLength; - zipEntryHeader.setExtraLength(length); - byte[] extra = new byte[length]; + short extraLength = (short) newExtraLength; + zipEntryHeader.setExtraLength(extraLength); + byte[] extra = new byte[extraLength]; zipEntryHeader.setExtraData(extra); - zipEntryHeader.setExtraLength(length); - int newLength = ZipEntryHeader.headerLength + - zipEntryHeader.getFileNameLength() + zipEntryHeader.getExtraData().length; + zipEntryHeader.setExtraLength(extraLength); + int newLength = ZipEntryHeader.HEADER_LENGTH + + zipEntryHeader.getFileNameLength() + zipEntryHeader.getExtraData().length; if (zipEntryHeader.getLength() + add != newLength) { throw new ZipException("can not align " + zipEntryHeader.getFileName()); } zipEntryHeader.setLength(newLength); + this.length += length; return (short) add; } -- Gitee From af1ca170f75372276248ce4caf27a67be448f5ab Mon Sep 17 00:00:00 2001 From: wangzeyu Date: Tue, 5 Dec 2023 02:09:28 +0000 Subject: [PATCH 09/37] codecheck repair Signed-off-by: wangzeyu --- .../hap/entity/zip/ZipEntryData.java | 324 ++++++++++++------ 1 file changed, 222 insertions(+), 102 deletions(-) diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntryData.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntryData.java index 46831ebf..146c40de 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntryData.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntryData.java @@ -15,147 +15,267 @@ package com.ohos.hapsigntool.hap.entity.zip; -import com.ohos.hapsigntool.error.ZipException; -import com.ohos.hapsigntool.utils.FileUtils; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.charset.StandardCharsets; /** - * resolve zip ZipEntry data + * resolve zip ZipEntryHeader data * - * @since 2023/12/04 + * @since 2023/12/02 */ -class ZipEntryData { - private ZipEntryHeader zipEntryHeader; +class ZipEntryHeader { + /** + * ZipEntryHeader invariable bytes length + */ + public static final int HEADER_LENGTH = 30; - private long fileOffset; + /** + * 4 bytes , entry header signature + */ + public static final int SIGNATURE = 0x04034b50; - private long fileSize; + /** + * 2 bytes + */ + private short version; - private DataDescriptor dataDescriptor; + /** + * 2 bytes + */ + private short flag; - private long length; + /** + * 2 bytes + */ + private short method; - public ZipEntryHeader getZipEntryHeader() { - return zipEntryHeader; - } + /** + * 2 bytes + */ + private short lastTime; + + /** + * 2 bytes + */ + private short lastDate; /** - * init zip entry by file + * 4 bytes + */ + private int crc32; + + /** + * 4 bytes + */ + private int compressedSize; + + /** + * 4 bytes + */ + private int unCompressedSize; + + /** + * 2 bytes + */ + private short fileNameLength; + + /** + * 2 bytes + */ + private short extraLength; + + /** + * n bytes + */ + private String fileName; + + /** + * n bytes + */ + private byte[] extraData; + + private int length; + + /** + * init Zip Entry Header * - * @param file zip file - * @param entryOffset entry start offset - * @param compress compress file size - * @param hasDesc has data descriptor - * @return zip entry - * @throws IOException read zip exception - */ - public static ZipEntryData initZipEntry(File file, long entryOffset, long compress, boolean hasDesc) - throws IOException { - try (FileInputStream fs = new FileInputStream(file)) { - long offset = entryOffset; - fs.skip(offset); - byte[] headBytes = FileUtils.readFileByOffsetAndLength(fs, 0, ZipEntryHeader.HEADER_LENGTH); - ZipEntryHeader entryHeader = ZipEntryHeader.initZipEntryHeader(headBytes); - if (entryHeader == null) { - throw new ZipException("find zip entry head failed"); - } - offset += ZipEntryHeader.HEADER_LENGTH; - byte[] nameAndExtra = FileUtils.readFileByOffsetAndLength(fs, 0, - entryHeader.getFileNameLength() + entryHeader.getExtraLength()); - entryHeader.setNameAndExtra(nameAndExtra); - - offset += entryHeader.getFileNameLength() + entryHeader.getExtraLength(); - - ZipEntryData entry = new ZipEntryData(); - entry.setFileOffset(offset); - entry.setFileSize(compress); - fs.skip(compress); - - offset += compress; - long entryLength = entryHeader.getLength() + compress; - - if (hasDesc) { - byte[] desBytes = FileUtils.readFileByOffsetAndLength(fs, 0, DataDescriptor.DES_LENGTH); - DataDescriptor dataDesc = DataDescriptor.initDataDescriptor(desBytes); - if (dataDesc == null) { - throw new ZipException("find zip entry desc failed"); - } - entryLength += DataDescriptor.DES_LENGTH; - entry.setDataDescriptor(dataDesc); - } - entry.setZipEntryHeader(entryHeader); - entry.setLength(entryLength); - return entry; + * @param bytes ZipEntryHeader bytes + * @return ZipEntryHeader + */ + public static ZipEntryHeader initZipEntryHeader(byte[] bytes) { + ZipEntryHeader entryHeader = new ZipEntryHeader(); + ByteBuffer bf = ByteBuffer.allocate(bytes.length); + bf.put(bytes); + bf.order(ByteOrder.LITTLE_ENDIAN); + bf.flip(); + if (bf.getInt() != ZipEntryHeader.SIGNATURE) { + return null; } + entryHeader.setVersion(bf.getShort()); + entryHeader.setFlag(bf.getShort()); + entryHeader.setMethod(bf.getShort()); + entryHeader.setLastTime(bf.getShort()); + entryHeader.setLastDate(bf.getShort()); + entryHeader.setCrc32(bf.getInt()); + entryHeader.setCompressedSize(bf.getInt()); + entryHeader.setUnCompressedSize(bf.getInt()); + entryHeader.setFileNameLength(bf.getShort()); + entryHeader.setExtraLength(bf.getShort()); + entryHeader.setLength(HEADER_LENGTH + entryHeader.getFileNameLength() + entryHeader.getExtraLength()); + return entryHeader; } /** - * alignment one entry + * set entry header name and extra * - * @param alignNum need align bytes length - * @return add bytes length - * @throws ZipException alignment exception - */ - public short alignment(short alignNum) throws ZipException { - long add = alignNum - length % alignNum; - if (add > Short.MAX_VALUE) { - throw new ZipException("can not align " + zipEntryHeader.getFileName()); + * @param bytes name and extra bytes + */ + public void setNameAndExtra(byte[] bytes) { + ByteBuffer bf = ByteBuffer.allocate(bytes.length); + bf.put(bytes); + bf.order(ByteOrder.LITTLE_ENDIAN); + bf.flip(); + if (fileNameLength > 0) { + byte[] nameBytes = new byte[fileNameLength]; + bf.get(nameBytes); + this.fileName = new String(nameBytes, StandardCharsets.UTF_8); } - int newExtraLength = zipEntryHeader.getExtraLength() + (short) add; - if (newExtraLength > Short.MAX_VALUE) { - throw new ZipException("can not align " + zipEntryHeader.getFileName()); + if (extraLength > 0) { + byte[] extra = new byte[extraLength]; + bf.get(extra); + this.extraData = extra; } - short extraLength = (short) newExtraLength; - zipEntryHeader.setExtraLength(extraLength); - byte[] extra = new byte[extraLength]; - zipEntryHeader.setExtraData(extra); - zipEntryHeader.setExtraLength(extraLength); - int newLength = ZipEntryHeader.HEADER_LENGTH - + zipEntryHeader.getFileNameLength() + zipEntryHeader.getExtraData().length; - if (zipEntryHeader.getLength() + add != newLength) { - throw new ZipException("can not align " + zipEntryHeader.getFileName()); + } + + /** + * change Zip Entry Header to bytes + * + * @return bytes + */ + public byte[] toBytes() { + ByteBuffer bf = ByteBuffer.allocate(length).order(ByteOrder.LITTLE_ENDIAN); + bf.putInt(SIGNATURE); + bf.putShort(version); + bf.putShort(flag); + bf.putShort(method); + bf.putShort(lastTime); + bf.putShort(lastDate); + bf.putInt(crc32); + bf.putInt(compressedSize); + bf.putInt(unCompressedSize); + bf.putShort(fileNameLength); + bf.putShort(extraLength); + if (fileNameLength > 0) { + bf.put(fileName.getBytes(StandardCharsets.UTF_8)); } - zipEntryHeader.setLength(newLength); - this.length += length; - return (short) add; + if (extraLength > 0) { + bf.put(extraData); + } + return bf.array(); + } + + public short getFlag() { + return flag; + } + + public void setFlag(short flag) { + this.flag = flag; + } + + public short getMethod() { + return method; + } + + public void setMethod(short method) { + this.method = method; + } + + public short getVersion() { + return version; + } + + public void setVersion(short version) { + this.version = version; + } + + public short getLastTime() { + return lastTime; + } + + public void setLastTime(short lastTime) { + this.lastTime = lastTime; + } + + public short getLastDate() { + return lastDate; + } + + public void setLastDate(short lastDate) { + this.lastDate = lastDate; + } + + public int getCrc32() { + return crc32; + } + + public void setCrc32(int crc32) { + this.crc32 = crc32; + } + + public int getCompressedSize() { + return compressedSize; + } + + public void setCompressedSize(int compressedSize) { + this.compressedSize = compressedSize; + } + + public int getUnCompressedSize() { + return unCompressedSize; + } + + public void setUnCompressedSize(int unCompressedSize) { + this.unCompressedSize = unCompressedSize; + } + + public short getFileNameLength() { + return fileNameLength; } - public void setZipEntryHeader(ZipEntryHeader zipEntryHeader) { - this.zipEntryHeader = zipEntryHeader; + public void setFileNameLength(short fileNameLength) { + this.fileNameLength = fileNameLength; } - public DataDescriptor getDataDescriptor() { - return dataDescriptor; + public short getExtraLength() { + return extraLength; } - public void setDataDescriptor(DataDescriptor dataDescriptor) { - this.dataDescriptor = dataDescriptor; + public void setExtraLength(short extraLength) { + this.extraLength = extraLength; } - public long getFileOffset() { - return fileOffset; + public String getFileName() { + return fileName; } - public void setFileOffset(long fileOffset) { - this.fileOffset = fileOffset; + public void setFileName(String fileName) { + this.fileName = fileName; } - public long getFileSize() { - return fileSize; + public byte[] getExtraData() { + return extraData; } - public void setFileSize(long fileSize) { - this.fileSize = fileSize; + public void setExtraData(byte[] extraData) { + this.extraData = extraData; } - public long getLength() { + public int getLength() { return length; } - public void setLength(long length) { + public void setLength(int length) { this.length = length; } } \ No newline at end of file -- Gitee From 36ff7aae1f2c4cea492d16f6797487048c285552 Mon Sep 17 00:00:00 2001 From: wangzeyu Date: Tue, 5 Dec 2023 02:09:53 +0000 Subject: [PATCH 10/37] codecheck repair Signed-off-by: wangzeyu --- .../com/ohos/hapsigntool/utils/FileUtils.java | 56 +++++++++++++++---- 1 file changed, 46 insertions(+), 10 deletions(-) diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/utils/FileUtils.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/utils/FileUtils.java index cdc8a8ce..d4b2d2c8 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/utils/FileUtils.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/utils/FileUtils.java @@ -18,6 +18,7 @@ package com.ohos.hapsigntool.utils; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.ohos.hapsigntool.error.ERROR; + import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -42,27 +43,31 @@ import java.nio.file.Files; * @since 2021/12/28 */ public final class FileUtils { - /** * LOGGER. */ private static final Logger LOGGER = LogManager.getLogger(FileUtils.class); + /** * add GSON static. */ public static final Gson GSON = (new GsonBuilder()).disableHtmlEscaping().create(); + /** * add GSON_PRETTY_PRINT static. */ public static final Gson GSON_PRETTY_PRINT = (new GsonBuilder()).disableHtmlEscaping().setPrettyPrinting().create(); + /** * File reader block size */ public static final int FILE_BUFFER_BLOCK = 1024 * 1024; + /** * File end */ public static final int FILE_END = -1; + /** * Expected split string length */ @@ -103,18 +108,48 @@ public final class FileUtils { * Read byte from input file. * * @param file Which file to read + * @param offset read offset + * @param length read length * @return byte content * @throws IOException Read failed */ public static byte[] readFileByOffsetAndLength(File file, long offset, long length) throws IOException { - if (offset > file.length()) { - throw new IOException("read file failed: offset " + offset + "is too large"); + try (FileInputStream fs = new FileInputStream(file)) { + return readFileByOffsetAndLength(fs, offset, length); } + } - if (length + offset > file.length()) { - throw new IOException("read file failed"); + /** + * Read byte from input file. + * + * @param fs Which file to read + * @param offset read offset + * @param length read length + * @return byte content + * @throws IOException Read failed + */ + public static byte[] readFileByOffsetAndLength(FileInputStream fs, long offset, long length) throws IOException { + try (ByteArrayOutputStream output = new ByteArrayOutputStream()) { + byte[] buffer; + fs.skip(offset); + if (length > FILE_BUFFER_BLOCK) { + long num = length / FILE_BUFFER_BLOCK; + long remainder = length % FILE_BUFFER_BLOCK; + buffer = new byte[FILE_BUFFER_BLOCK]; + byte[] suffix = new byte[(int) remainder]; + for (int i = 0; i < num; i++) { + int read = fs.read(buffer); + output.write(buffer, 0, read); + } + int read = fs.read(suffix); + output.write(buffer, 0, read); + } else { + buffer = new byte[(int) length]; + int read = fs.read(buffer); + output.write(buffer, 0, read); + } + return output.toByteArray(); } - return read(Files.newInputStream(file.toPath()), offset, length); } /** @@ -141,6 +176,8 @@ public final class FileUtils { * Read byte from input stream. * * @param input Input stream + * @param offset read offset + * @param length read length * @return File content * @throws IOException Read failed */ @@ -148,7 +185,7 @@ public final class FileUtils { try (ByteArrayOutputStream output = new ByteArrayOutputStream()) { byte[] buffer = new byte[FILE_BUFFER_BLOCK]; int read; - long readSum = 0; + long readSum = 0L; input.skip(offset); while ((read = input.read(buffer)) != FILE_END) { readSum += read; @@ -161,8 +198,6 @@ public final class FileUtils { } } return output.toByteArray(); - } finally { - close(input); } } @@ -252,7 +287,7 @@ public final class FileUtils { FileOutputStream fos = new FileOutputStream(outPutFile, true)) { byte[] buffer = new byte[FILE_BUFFER_BLOCK]; int read; - long readSum = 0; + long readSum = 0L; fileStream.skip(offset); while ((read = fileStream.read(buffer)) != FILE_END) { readSum += read; @@ -376,6 +411,7 @@ public final class FileUtils { /** * Open an input stream of input file safely. + * * @param file input file. * @return an input stream of input file * @throws IOException file is a directory or can't be read. -- Gitee From 106c9d74eb76c42db19b1f05b7ffd05099269d39 Mon Sep 17 00:00:00 2001 From: wangzeyu Date: Tue, 5 Dec 2023 02:12:27 +0000 Subject: [PATCH 11/37] codecheck repair Signed-off-by: wangzeyu --- .../hap/entity/zip/ZipEntryData.java | 324 ++++++------------ 1 file changed, 102 insertions(+), 222 deletions(-) diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntryData.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntryData.java index 146c40de..46831ebf 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntryData.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntryData.java @@ -15,267 +15,147 @@ package com.ohos.hapsigntool.hap.entity.zip; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.charset.StandardCharsets; +import com.ohos.hapsigntool.error.ZipException; +import com.ohos.hapsigntool.utils.FileUtils; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; /** - * resolve zip ZipEntryHeader data + * resolve zip ZipEntry data * - * @since 2023/12/02 + * @since 2023/12/04 */ -class ZipEntryHeader { - /** - * ZipEntryHeader invariable bytes length - */ - public static final int HEADER_LENGTH = 30; +class ZipEntryData { + private ZipEntryHeader zipEntryHeader; - /** - * 4 bytes , entry header signature - */ - public static final int SIGNATURE = 0x04034b50; + private long fileOffset; - /** - * 2 bytes - */ - private short version; + private long fileSize; - /** - * 2 bytes - */ - private short flag; + private DataDescriptor dataDescriptor; - /** - * 2 bytes - */ - private short method; + private long length; - /** - * 2 bytes - */ - private short lastTime; - - /** - * 2 bytes - */ - private short lastDate; - - /** - * 4 bytes - */ - private int crc32; - - /** - * 4 bytes - */ - private int compressedSize; - - /** - * 4 bytes - */ - private int unCompressedSize; - - /** - * 2 bytes - */ - private short fileNameLength; - - /** - * 2 bytes - */ - private short extraLength; - - /** - * n bytes - */ - private String fileName; - - /** - * n bytes - */ - private byte[] extraData; - - private int length; - - /** - * init Zip Entry Header - * - * @param bytes ZipEntryHeader bytes - * @return ZipEntryHeader - */ - public static ZipEntryHeader initZipEntryHeader(byte[] bytes) { - ZipEntryHeader entryHeader = new ZipEntryHeader(); - ByteBuffer bf = ByteBuffer.allocate(bytes.length); - bf.put(bytes); - bf.order(ByteOrder.LITTLE_ENDIAN); - bf.flip(); - if (bf.getInt() != ZipEntryHeader.SIGNATURE) { - return null; - } - entryHeader.setVersion(bf.getShort()); - entryHeader.setFlag(bf.getShort()); - entryHeader.setMethod(bf.getShort()); - entryHeader.setLastTime(bf.getShort()); - entryHeader.setLastDate(bf.getShort()); - entryHeader.setCrc32(bf.getInt()); - entryHeader.setCompressedSize(bf.getInt()); - entryHeader.setUnCompressedSize(bf.getInt()); - entryHeader.setFileNameLength(bf.getShort()); - entryHeader.setExtraLength(bf.getShort()); - entryHeader.setLength(HEADER_LENGTH + entryHeader.getFileNameLength() + entryHeader.getExtraLength()); - return entryHeader; + public ZipEntryHeader getZipEntryHeader() { + return zipEntryHeader; } /** - * set entry header name and extra + * init zip entry by file * - * @param bytes name and extra bytes - */ - public void setNameAndExtra(byte[] bytes) { - ByteBuffer bf = ByteBuffer.allocate(bytes.length); - bf.put(bytes); - bf.order(ByteOrder.LITTLE_ENDIAN); - bf.flip(); - if (fileNameLength > 0) { - byte[] nameBytes = new byte[fileNameLength]; - bf.get(nameBytes); - this.fileName = new String(nameBytes, StandardCharsets.UTF_8); - } - if (extraLength > 0) { - byte[] extra = new byte[extraLength]; - bf.get(extra); - this.extraData = extra; + * @param file zip file + * @param entryOffset entry start offset + * @param compress compress file size + * @param hasDesc has data descriptor + * @return zip entry + * @throws IOException read zip exception + */ + public static ZipEntryData initZipEntry(File file, long entryOffset, long compress, boolean hasDesc) + throws IOException { + try (FileInputStream fs = new FileInputStream(file)) { + long offset = entryOffset; + fs.skip(offset); + byte[] headBytes = FileUtils.readFileByOffsetAndLength(fs, 0, ZipEntryHeader.HEADER_LENGTH); + ZipEntryHeader entryHeader = ZipEntryHeader.initZipEntryHeader(headBytes); + if (entryHeader == null) { + throw new ZipException("find zip entry head failed"); + } + offset += ZipEntryHeader.HEADER_LENGTH; + byte[] nameAndExtra = FileUtils.readFileByOffsetAndLength(fs, 0, + entryHeader.getFileNameLength() + entryHeader.getExtraLength()); + entryHeader.setNameAndExtra(nameAndExtra); + + offset += entryHeader.getFileNameLength() + entryHeader.getExtraLength(); + + ZipEntryData entry = new ZipEntryData(); + entry.setFileOffset(offset); + entry.setFileSize(compress); + fs.skip(compress); + + offset += compress; + long entryLength = entryHeader.getLength() + compress; + + if (hasDesc) { + byte[] desBytes = FileUtils.readFileByOffsetAndLength(fs, 0, DataDescriptor.DES_LENGTH); + DataDescriptor dataDesc = DataDescriptor.initDataDescriptor(desBytes); + if (dataDesc == null) { + throw new ZipException("find zip entry desc failed"); + } + entryLength += DataDescriptor.DES_LENGTH; + entry.setDataDescriptor(dataDesc); + } + entry.setZipEntryHeader(entryHeader); + entry.setLength(entryLength); + return entry; } } /** - * change Zip Entry Header to bytes + * alignment one entry * - * @return bytes - */ - public byte[] toBytes() { - ByteBuffer bf = ByteBuffer.allocate(length).order(ByteOrder.LITTLE_ENDIAN); - bf.putInt(SIGNATURE); - bf.putShort(version); - bf.putShort(flag); - bf.putShort(method); - bf.putShort(lastTime); - bf.putShort(lastDate); - bf.putInt(crc32); - bf.putInt(compressedSize); - bf.putInt(unCompressedSize); - bf.putShort(fileNameLength); - bf.putShort(extraLength); - if (fileNameLength > 0) { - bf.put(fileName.getBytes(StandardCharsets.UTF_8)); + * @param alignNum need align bytes length + * @return add bytes length + * @throws ZipException alignment exception + */ + public short alignment(short alignNum) throws ZipException { + long add = alignNum - length % alignNum; + if (add > Short.MAX_VALUE) { + throw new ZipException("can not align " + zipEntryHeader.getFileName()); } - if (extraLength > 0) { - bf.put(extraData); + int newExtraLength = zipEntryHeader.getExtraLength() + (short) add; + if (newExtraLength > Short.MAX_VALUE) { + throw new ZipException("can not align " + zipEntryHeader.getFileName()); } - return bf.array(); - } - - public short getFlag() { - return flag; - } - - public void setFlag(short flag) { - this.flag = flag; - } - - public short getMethod() { - return method; - } - - public void setMethod(short method) { - this.method = method; - } - - public short getVersion() { - return version; - } - - public void setVersion(short version) { - this.version = version; - } - - public short getLastTime() { - return lastTime; - } - - public void setLastTime(short lastTime) { - this.lastTime = lastTime; - } - - public short getLastDate() { - return lastDate; - } - - public void setLastDate(short lastDate) { - this.lastDate = lastDate; - } - - public int getCrc32() { - return crc32; - } - - public void setCrc32(int crc32) { - this.crc32 = crc32; - } - - public int getCompressedSize() { - return compressedSize; - } - - public void setCompressedSize(int compressedSize) { - this.compressedSize = compressedSize; - } - - public int getUnCompressedSize() { - return unCompressedSize; - } - - public void setUnCompressedSize(int unCompressedSize) { - this.unCompressedSize = unCompressedSize; - } - - public short getFileNameLength() { - return fileNameLength; + short extraLength = (short) newExtraLength; + zipEntryHeader.setExtraLength(extraLength); + byte[] extra = new byte[extraLength]; + zipEntryHeader.setExtraData(extra); + zipEntryHeader.setExtraLength(extraLength); + int newLength = ZipEntryHeader.HEADER_LENGTH + + zipEntryHeader.getFileNameLength() + zipEntryHeader.getExtraData().length; + if (zipEntryHeader.getLength() + add != newLength) { + throw new ZipException("can not align " + zipEntryHeader.getFileName()); + } + zipEntryHeader.setLength(newLength); + this.length += length; + return (short) add; } - public void setFileNameLength(short fileNameLength) { - this.fileNameLength = fileNameLength; + public void setZipEntryHeader(ZipEntryHeader zipEntryHeader) { + this.zipEntryHeader = zipEntryHeader; } - public short getExtraLength() { - return extraLength; + public DataDescriptor getDataDescriptor() { + return dataDescriptor; } - public void setExtraLength(short extraLength) { - this.extraLength = extraLength; + public void setDataDescriptor(DataDescriptor dataDescriptor) { + this.dataDescriptor = dataDescriptor; } - public String getFileName() { - return fileName; + public long getFileOffset() { + return fileOffset; } - public void setFileName(String fileName) { - this.fileName = fileName; + public void setFileOffset(long fileOffset) { + this.fileOffset = fileOffset; } - public byte[] getExtraData() { - return extraData; + public long getFileSize() { + return fileSize; } - public void setExtraData(byte[] extraData) { - this.extraData = extraData; + public void setFileSize(long fileSize) { + this.fileSize = fileSize; } - public int getLength() { + public long getLength() { return length; } - public void setLength(int length) { + public void setLength(long length) { this.length = length; } } \ No newline at end of file -- Gitee From 278fe2b46d13ab60cd30c8df4378cd9fdeeb07c3 Mon Sep 17 00:00:00 2001 From: wangzeyu Date: Tue, 5 Dec 2023 02:12:51 +0000 Subject: [PATCH 12/37] codecheck repair Signed-off-by: wangzeyu --- .../hap/entity/zip/ZipEntryHeader.java | 48 +++++++++++++------ 1 file changed, 33 insertions(+), 15 deletions(-) diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntryHeader.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntryHeader.java index d005cd38..146c40de 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntryHeader.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntryHeader.java @@ -15,7 +15,6 @@ package com.ohos.hapsigntool.hap.entity.zip; - import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.charset.StandardCharsets; @@ -26,12 +25,15 @@ import java.nio.charset.StandardCharsets; * @since 2023/12/02 */ class ZipEntryHeader { + /** + * ZipEntryHeader invariable bytes length + */ + public static final int HEADER_LENGTH = 30; - public static int headerLength = 30; /** - * 4 bytes + * 4 bytes , entry header signature */ - public static final int signature = 0x04034b50; + public static final int SIGNATURE = 0x04034b50; /** * 2 bytes @@ -95,13 +97,19 @@ class ZipEntryHeader { private int length; + /** + * init Zip Entry Header + * + * @param bytes ZipEntryHeader bytes + * @return ZipEntryHeader + */ public static ZipEntryHeader initZipEntryHeader(byte[] bytes) { ZipEntryHeader entryHeader = new ZipEntryHeader(); ByteBuffer bf = ByteBuffer.allocate(bytes.length); bf.put(bytes); bf.order(ByteOrder.LITTLE_ENDIAN); bf.flip(); - if (bf.getInt() != ZipEntryHeader.signature) { + if (bf.getInt() != ZipEntryHeader.SIGNATURE) { return null; } entryHeader.setVersion(bf.getShort()); @@ -114,10 +122,15 @@ class ZipEntryHeader { entryHeader.setUnCompressedSize(bf.getInt()); entryHeader.setFileNameLength(bf.getShort()); entryHeader.setExtraLength(bf.getShort()); - entryHeader.setLength(headerLength + entryHeader.getFileNameLength() + entryHeader.getExtraLength()); + entryHeader.setLength(HEADER_LENGTH + entryHeader.getFileNameLength() + entryHeader.getExtraLength()); return entryHeader; } + /** + * set entry header name and extra + * + * @param bytes name and extra bytes + */ public void setNameAndExtra(byte[] bytes) { ByteBuffer bf = ByteBuffer.allocate(bytes.length); bf.put(bytes); @@ -135,9 +148,14 @@ class ZipEntryHeader { } } + /** + * change Zip Entry Header to bytes + * + * @return bytes + */ public byte[] toBytes() { ByteBuffer bf = ByteBuffer.allocate(length).order(ByteOrder.LITTLE_ENDIAN); - bf.putInt(signature); + bf.putInt(SIGNATURE); bf.putShort(version); bf.putShort(flag); bf.putShort(method); @@ -157,14 +175,6 @@ class ZipEntryHeader { return bf.array(); } - public short getVersion() { - return version; - } - - public void setVersion(short version) { - this.version = version; - } - public short getFlag() { return flag; } @@ -181,6 +191,14 @@ class ZipEntryHeader { this.method = method; } + public short getVersion() { + return version; + } + + public void setVersion(short version) { + this.version = version; + } + public short getLastTime() { return lastTime; } -- Gitee From 24a237793745603f2685dc35d8184d62dcb47bd9 Mon Sep 17 00:00:00 2001 From: wangzeyu Date: Tue, 5 Dec 2023 10:43:22 +0800 Subject: [PATCH 13/37] codecheck repair Signed-off-by: wangzeyu --- .../hapsigntool/hap/entity/zip/DataDescriptor.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/DataDescriptor.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/DataDescriptor.java index ebbc7132..b1a5edf6 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/DataDescriptor.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/DataDescriptor.java @@ -88,3 +88,17 @@ public class DataDescriptor { public int getCompressedSize() { return compressedSize; + } + + public void setCompressedSize(int compressedSize) { + this.compressedSize = compressedSize; + } + + public int getUnCompressedSize() { + return unCompressedSize; + } + + public void setUnCompressedSize(int unCompressedSize) { + this.unCompressedSize = unCompressedSize; + } +} -- Gitee From de8cf19ed136789aa20bccf25cdbe431d8542f3a Mon Sep 17 00:00:00 2001 From: wangzeyu Date: Tue, 5 Dec 2023 03:54:47 +0000 Subject: [PATCH 14/37] fix bug Signed-off-by: wangzeyu --- .../hap/entity/zip/DataDescriptor.java | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/DataDescriptor.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/DataDescriptor.java index b1a5edf6..d503876b 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/DataDescriptor.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/DataDescriptor.java @@ -15,6 +15,8 @@ package com.ohos.hapsigntool.hap.entity.zip; +import com.ohos.hapsigntool.error.ZipException; + import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -27,7 +29,12 @@ public class DataDescriptor { /** * DataDescriptor invariable bytes length */ - public static final int DES_LENGTH = 12; + public static final int DES_LENGTH = 16; + + /** + * 4 bytes , DataDescriptor signature + */ + public static final int SIGNATURE = 0x08074b50; /** * 4 bytes @@ -49,9 +56,10 @@ public class DataDescriptor { * * @param bytes DataDescriptor bytes * @return DataDescriptor + * @throws ZipException read data descriptor exception */ - public static DataDescriptor initDataDescriptor(byte[] bytes) { - if (bytes.length != 12) { + public static DataDescriptor initDataDescriptor(byte[] bytes) throws ZipException { + if (bytes.length != DES_LENGTH) { return null; } ByteBuffer bf = ByteBuffer.allocate(bytes.length); @@ -59,6 +67,9 @@ public class DataDescriptor { bf.order(ByteOrder.LITTLE_ENDIAN); bf.flip(); DataDescriptor data = new DataDescriptor(); + if (bf.getInt() != SIGNATURE) { + throw new ZipException("read Data Descriptor failed"); + } data.setCrc32(bf.getInt()); data.setCompressedSize(bf.getInt()); data.setUnCompressedSize(bf.getInt()); @@ -72,6 +83,7 @@ public class DataDescriptor { */ public byte[] toBytes() { ByteBuffer bf = ByteBuffer.allocate(DES_LENGTH).order(ByteOrder.LITTLE_ENDIAN); + bf.putInt(SIGNATURE); bf.putInt(crc32); bf.putInt(compressedSize); bf.putInt(unCompressedSize); -- Gitee From f48b528596c358be94ed07fb556d9bb1464ff878 Mon Sep 17 00:00:00 2001 From: wangzeyu Date: Tue, 5 Dec 2023 03:55:07 +0000 Subject: [PATCH 15/37] fix bug Signed-off-by: wangzeyu --- .../ohos/hapsigntool/hap/entity/zip/Zip.java | 49 +++++-------------- 1 file changed, 13 insertions(+), 36 deletions(-) diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/Zip.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/Zip.java index 17a8fb7b..66a30619 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/Zip.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/Zip.java @@ -48,7 +48,7 @@ public class Zip { private String file; - private final List suffix4K = new ArrayList() {{ + private final List suffix4K = new ArrayList<>() {{ add(".so"); add(".abc"); }}; @@ -62,24 +62,15 @@ public class Zip { * @throws IOException read file exception */ public Zip(File file) throws IOException { - long start = System.currentTimeMillis(); this.file = file.getPath(); // 1. get eocd data endOfCentralDirectory = getZipEndOfCentralDirectory(file); - long eocd = System.currentTimeMillis(); - LOGGER.info("read EOCD use " + (eocd - start) + "ms"); // 2. use eocd's cd offset, get cd data getZipCentralDirectory(file); - long cd = System.currentTimeMillis(); - LOGGER.info("read CD use " + (cd - eocd) + "ms"); // 3. use cd's entry offset and file size, get entry data getZipEntries(file); - long entry = System.currentTimeMillis(); - LOGGER.info("read entry use " + (entry - cd) + "ms"); // 4. file all data - eocd - cd - entry = sign block signingBlock = getSigningBlock(file); - long signBlock = System.currentTimeMillis(); - LOGGER.info("read signBlock use " + (signBlock - entry) + "ms"); } private EndOfCentralDirectory getZipEndOfCentralDirectory(File file) throws IOException { @@ -164,7 +155,6 @@ public class Zip { f.createNewFile(); } FileUtils.write(new byte[]{}, f); - long start = System.currentTimeMillis(); for (ZipEntry entry : zipEntries) { ZipEntryData zipEntryData = entry.getZipEntryData(); FileUtils.writeByteToOutFile(zipEntryData.getZipEntryHeader().toBytes(), file); @@ -180,8 +170,6 @@ public class Zip { FileUtils.writeByteToOutFile(cd.toBytes(), file); } FileUtils.writeByteToOutFile(endOfCentralDirectory.toBytes(), file); - long end = System.currentTimeMillis(); - LOGGER.info("write file use " + (end - start) + "ms"); } /** @@ -190,7 +178,6 @@ public class Zip { * @throws ZipException alignment exception */ public void alignment() throws ZipException { - long start = System.currentTimeMillis(); for (ZipEntry entry : zipEntries) { ZipEntryData zipEntryData = entry.getZipEntryData(); short method = zipEntryData.getZipEntryHeader().getMethod(); @@ -198,35 +185,27 @@ public class Zip { // only align uncompressed entry. continue; } + // normal file align 4 byte. + short alignBytes = 4; if (is4kAlignSuffix(zipEntryData.getZipEntryHeader().getFileName())) { - // some file align 4096 byte. - short align4kBytes = 4096; - short alignment = zipEntryData.alignment(align4kBytes); - if (alignment > 0) { - int offset = entry.getCentralDirectory().getOffset() + alignment; - entry.getCentralDirectory().setOffset(offset); - endOfCentralDirectory.setOffset(endOfCentralDirectory.getOffset() + alignment); - } - } else { - // other file align 4 byte. - short align4Bytes = 4; - short alignment = zipEntryData.alignment(align4Bytes); - if (alignment > 0) { - int offset = entry.getCentralDirectory().getOffset() + alignment; - entry.getCentralDirectory().setOffset(offset); - endOfCentralDirectory.setOffset(endOfCentralDirectory.getOffset() + alignment); - } + // .abc and .so file align 4096 byte. + alignBytes = 4096; + } + short alignment = zipEntryData.alignment(alignBytes); + if (alignment > 0) { + int offset = entry.getCentralDirectory().getOffset() + alignment; + entry.getCentralDirectory().setOffset(offset); + endOfCentralDirectory.setOffset(endOfCentralDirectory.getOffset() + alignment); + eOCDOffset += alignment; + cDOffset += alignment; } } - long end = System.currentTimeMillis(); - LOGGER.info("alignment entry use " + (end - start) + "ms"); } /** * sort uncompress entry in the front. */ public void sort() { - long start = System.currentTimeMillis(); int unCompressOffset = 0; int compressOffset = zipEntries.size() - 1; int pointer = 0; @@ -257,8 +236,6 @@ public class Zip { entry.getCentralDirectory().setOffset(offset); offset += entry.getZipEntryData().getLength(); } - long end = System.currentTimeMillis(); - LOGGER.info("sort entry use " + (end - start) + "ms"); } private boolean is4kAlignSuffix(String name) { -- Gitee From ad8de0b39e5cc15faafb4e0665211ade21a95959 Mon Sep 17 00:00:00 2001 From: wangzeyu Date: Tue, 5 Dec 2023 03:55:27 +0000 Subject: [PATCH 16/37] fix bug Signed-off-by: wangzeyu --- .../com/ohos/hapsigntool/hap/entity/zip/ZipEntryData.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntryData.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntryData.java index 46831ebf..fd55f9e7 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntryData.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntryData.java @@ -101,6 +101,9 @@ class ZipEntryData { */ public short alignment(short alignNum) throws ZipException { long add = alignNum - length % alignNum; + if (add == alignNum) { + return 0; + } if (add > Short.MAX_VALUE) { throw new ZipException("can not align " + zipEntryHeader.getFileName()); } @@ -112,14 +115,13 @@ class ZipEntryData { zipEntryHeader.setExtraLength(extraLength); byte[] extra = new byte[extraLength]; zipEntryHeader.setExtraData(extra); - zipEntryHeader.setExtraLength(extraLength); int newLength = ZipEntryHeader.HEADER_LENGTH + zipEntryHeader.getFileNameLength() + zipEntryHeader.getExtraData().length; if (zipEntryHeader.getLength() + add != newLength) { throw new ZipException("can not align " + zipEntryHeader.getFileName()); } zipEntryHeader.setLength(newLength); - this.length += length; + this.length += add; return (short) add; } -- Gitee From deeb1b72de4a433347a6409d714bf2d648881966 Mon Sep 17 00:00:00 2001 From: wangzeyu Date: Tue, 5 Dec 2023 15:09:37 +0800 Subject: [PATCH 17/37] try to alignment zip data Signed-off-by: wangzeyu --- .../ohos/hapsigntool/hap/entity/zip/Zip.java | 12 +- .../hap/entity/zip/ZipEntryData.java | 17 +- .../hap/provider/SignProvider.java | 10 +- .../com/ohos/hapsigntool/utils/FileUtils.java | 195 ++++++++---------- 4 files changed, 104 insertions(+), 130 deletions(-) diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/Zip.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/Zip.java index 66a30619..4240ef87 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/Zip.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/Zip.java @@ -32,8 +32,6 @@ import java.util.List; * @since 2023/12/02 */ public class Zip { - private static final Logger LOGGER = LogManager.getLogger(Zip.class); - private List zipEntries; private long signingOffset; @@ -48,7 +46,7 @@ public class Zip { private String file; - private final List suffix4K = new ArrayList<>() {{ + private final List suffix4K = new ArrayList() {{ add(".so"); add(".abc"); }}; @@ -63,6 +61,9 @@ public class Zip { */ public Zip(File file) throws IOException { this.file = file.getPath(); + if (!file.exists()) { + throw new ZipException("read zip file failed"); + } // 1. get eocd data endOfCentralDirectory = getZipEndOfCentralDirectory(file); // 2. use eocd's cd offset, get cd data @@ -158,8 +159,11 @@ public class Zip { for (ZipEntry entry : zipEntries) { ZipEntryData zipEntryData = entry.getZipEntryData(); FileUtils.writeByteToOutFile(zipEntryData.getZipEntryHeader().toBytes(), file); - FileUtils.writeFileByOffsetToFile(this.file, file, + boolean isSuccess = FileUtils.appendWriteFileByOffsetToFile(this.file, file, zipEntryData.getFileOffset(), zipEntryData.getFileSize()); + if (!isSuccess) { + throw new ZipException("write zip data failed"); + } if (zipEntryData.getDataDescriptor() != null) { FileUtils.writeByteToOutFile(zipEntryData.getDataDescriptor().toBytes(), file); } diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntryData.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntryData.java index fd55f9e7..91a42264 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntryData.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntryData.java @@ -53,32 +53,31 @@ class ZipEntryData { * @throws IOException read zip exception */ public static ZipEntryData initZipEntry(File file, long entryOffset, long compress, boolean hasDesc) - throws IOException { - try (FileInputStream fs = new FileInputStream(file)) { + throws IOException { + try (FileInputStream input = new FileInputStream(file)) { long offset = entryOffset; - fs.skip(offset); - byte[] headBytes = FileUtils.readFileByOffsetAndLength(fs, 0, ZipEntryHeader.HEADER_LENGTH); + byte[] headBytes = FileUtils.readInputByOffsetAndLength(input, entryOffset, ZipEntryHeader.HEADER_LENGTH); ZipEntryHeader entryHeader = ZipEntryHeader.initZipEntryHeader(headBytes); if (entryHeader == null) { throw new ZipException("find zip entry head failed"); } offset += ZipEntryHeader.HEADER_LENGTH; - byte[] nameAndExtra = FileUtils.readFileByOffsetAndLength(fs, 0, - entryHeader.getFileNameLength() + entryHeader.getExtraLength()); + int nameAndExtraLength = entryHeader.getFileNameLength() + entryHeader.getExtraLength(); + byte[] nameAndExtra = FileUtils.readInputByLength(input, nameAndExtraLength); entryHeader.setNameAndExtra(nameAndExtra); - offset += entryHeader.getFileNameLength() + entryHeader.getExtraLength(); + offset += nameAndExtraLength; ZipEntryData entry = new ZipEntryData(); entry.setFileOffset(offset); entry.setFileSize(compress); - fs.skip(compress); + input.skip(compress); offset += compress; long entryLength = entryHeader.getLength() + compress; if (hasDesc) { - byte[] desBytes = FileUtils.readFileByOffsetAndLength(fs, 0, DataDescriptor.DES_LENGTH); + byte[] desBytes = FileUtils.readInputByLength(input, DataDescriptor.DES_LENGTH); DataDescriptor dataDesc = DataDescriptor.initDataDescriptor(desBytes); if (dataDesc == null) { throw new ZipException("find zip entry desc failed"); diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/provider/SignProvider.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/provider/SignProvider.java index b00b96dd..def0dea7 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/provider/SignProvider.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/provider/SignProvider.java @@ -508,15 +508,7 @@ public abstract class SignProvider { Zip zip = new Zip(input); zip.alignment(); zip.sort(); - zip.toFile("a.zip"); - try (JarFile inputJar = new JarFile(input, false); - FileOutputStream outputFile = new FileOutputStream(tmpOutput); - JarOutputStream outputJar = new JarOutputStream(outputFile)) { - long timestamp = TIMESTAMP; - timestamp -= TimeZone.getDefault().getOffset(timestamp); - outputJar.setLevel(COMPRESSION_MODE); - SignHap.copyFiles(inputJar, outputJar, timestamp, alignment); - } + zip.toFile(tmpOutput.getPath()); } /** diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/utils/FileUtils.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/utils/FileUtils.java index d4b2d2c8..6ffd257f 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/utils/FileUtils.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/utils/FileUtils.java @@ -101,106 +101,97 @@ public final class FileUtils { * @throws IOException Read failed */ public static byte[] readFile(File file) throws IOException { - return read(Files.newInputStream(file.toPath()), 0L, file.length()); + return read(Files.newInputStream(file.toPath())); } /** - * Read byte from input file. + * Read byte from input stream. * - * @param file Which file to read - * @param offset read offset - * @param length read length - * @return byte content + * @param input Input stream + * @return File content * @throws IOException Read failed */ - public static byte[] readFileByOffsetAndLength(File file, long offset, long length) throws IOException { - try (FileInputStream fs = new FileInputStream(file)) { - return readFileByOffsetAndLength(fs, offset, length); + public static byte[] read(InputStream input) throws IOException { + try (ByteArrayOutputStream output = new ByteArrayOutputStream()) { + byte[] buffer = new byte[FILE_BUFFER_BLOCK]; + int read; + while ((read = input.read(buffer)) != FILE_END) { + output.write(buffer, 0, read); + } + return output.toByteArray(); + } finally { + close(input); } } /** * Read byte from input file. * - * @param fs Which file to read - * @param offset read offset - * @param length read length - * @return byte content - * @throws IOException Read failed + * @param file input file + * @param offset offset + * @param length length + * @return data bytes */ - public static byte[] readFileByOffsetAndLength(FileInputStream fs, long offset, long length) throws IOException { - try (ByteArrayOutputStream output = new ByteArrayOutputStream()) { - byte[] buffer; - fs.skip(offset); - if (length > FILE_BUFFER_BLOCK) { - long num = length / FILE_BUFFER_BLOCK; - long remainder = length % FILE_BUFFER_BLOCK; - buffer = new byte[FILE_BUFFER_BLOCK]; - byte[] suffix = new byte[(int) remainder]; - for (int i = 0; i < num; i++) { - int read = fs.read(buffer); - output.write(buffer, 0, read); - } - int read = fs.read(suffix); - output.write(buffer, 0, read); - } else { - buffer = new byte[(int) length]; - int read = fs.read(buffer); - output.write(buffer, 0, read); - } - return output.toByteArray(); + public static byte[] readFileByOffsetAndLength(File file, long offset, long length) throws IOException { + try (FileInputStream input = new FileInputStream(file)) { + return readInputByOffsetAndLength(input, offset, length); } } /** * Read byte from input stream. * - * @param input Input stream - * @return File content - * @throws IOException Read failed + * @param input input stream + * @param offset offset + * @param length length + * @return data bytes + * @throws IOException read exception */ - public static byte[] read(InputStream input) throws IOException { - try (ByteArrayOutputStream output = new ByteArrayOutputStream()) { - byte[] buffer = new byte[FILE_BUFFER_BLOCK]; - int read; - while ((read = input.read(buffer)) != FILE_END) { - output.write(buffer, 0, read); - } - return output.toByteArray(); - } finally { - close(input); + public static byte[] readInputByOffsetAndLength(InputStream input, long offset, long length) throws IOException { + long skip = input.skip(offset); + if (skip < offset) { + throw new IOException("can not read bytes by offset"); } + return readInputByLength(input, length); } /** * Read byte from input stream. * - * @param input Input stream - * @param offset read offset - * @param length read length - * @return File content - * @throws IOException Read failed + * @param input InputStream + * @param length length + * @return data bytes */ - public static byte[] read(InputStream input, long offset, long length) throws IOException { + public static byte[] readInputByLength(InputStream input, long length) throws IOException { try (ByteArrayOutputStream output = new ByteArrayOutputStream()) { - byte[] buffer = new byte[FILE_BUFFER_BLOCK]; - int read; - long readSum = 0L; - input.skip(offset); - while ((read = input.read(buffer)) != FILE_END) { - readSum += read; - if (readSum <= length) { - output.write(buffer, 0, read); - } else { - long outputLength = length % FILE_BUFFER_BLOCK; - output.write(buffer, 0, (int) outputLength); - break; - } - } + writeInputToOutPut(input, output, length); return output.toByteArray(); } } + /** + * write input to output by length + */ + private static void writeInputToOutPut(InputStream input, OutputStream output, long length) throws IOException { + byte[] buffer; + if (length > FILE_BUFFER_BLOCK) { + long times = length / FILE_BUFFER_BLOCK; + long remainder = length % FILE_BUFFER_BLOCK; + buffer = new byte[FILE_BUFFER_BLOCK]; + for (int i = 0; i < times; i++) { + int read = input.read(buffer); + output.write(buffer, 0, read); + } + byte[] suffix = new byte[(int) remainder]; + int read = input.read(suffix); + output.write(buffer, 0, read); + } else { + buffer = new byte[(int) length]; + int read = input.read(buffer); + output.write(buffer, 0, read); + } + } + /** * Out put content to file. * @@ -216,6 +207,34 @@ public final class FileUtils { } } + /** + * Write data in file to output stream + * + * @param inFile input file path. + * @param outFile output file path. + * @param offset file read offset + * @param size file read size + * @return true, if write successfully. + */ + public static boolean appendWriteFileByOffsetToFile(String inFile, String outFile, long offset, long size) { + if (StringUtils.isEmpty(outFile)) { + return false; + } + File inputFile = new File(inFile); + File outPutFile = new File(outFile); + try (FileInputStream fis = new FileInputStream(inputFile); + FileOutputStream fos = new FileOutputStream(outPutFile, true)) { + fis.skip(offset); + writeInputToOutPut(fis, fos, size); + return true; + } catch (FileNotFoundException e) { + LOGGER.error("Failed to get input stream object."); + } catch (IOException e) { + LOGGER.error("Failed to read or write data."); + } + return false; + } + /** * Check file exist or not. * @@ -268,46 +287,6 @@ public final class FileUtils { return temps[temps.length - 1]; } - /** - * Write data in file to output stream - * - * @param inFile input file path. - * @param outFile output file path. - * @param offset file read offset - * @param size file read size - * @return true, if write successfully. - */ - public static boolean writeFileByOffsetToFile(String inFile, String outFile, long offset, long size) { - if (StringUtils.isEmpty(outFile)) { - return false; - } - File src = new File(inFile); - File outPutFile = new File(outFile); - try (FileInputStream fileStream = new FileInputStream(src); - FileOutputStream fos = new FileOutputStream(outPutFile, true)) { - byte[] buffer = new byte[FILE_BUFFER_BLOCK]; - int read; - long readSum = 0L; - fileStream.skip(offset); - while ((read = fileStream.read(buffer)) != FILE_END) { - readSum += read; - if (readSum <= size) { - fos.write(buffer, 0, read); - } else { - long outputLength = size % FILE_BUFFER_BLOCK; - fos.write(buffer, 0, (int) outputLength); - break; - } - } - return true; - } catch (FileNotFoundException e) { - LOGGER.error("Failed to get input stream object."); - } catch (IOException e) { - LOGGER.error("Failed to read or write data."); - } - return false; - } - /** * Write data in file to output stream * -- Gitee From 70df9d000e6d77e81fff519613f291df2702cfbd Mon Sep 17 00:00:00 2001 From: wangzeyu Date: Tue, 5 Dec 2023 15:26:44 +0800 Subject: [PATCH 18/37] try to alignment zip data Signed-off-by: wangzeyu --- .../hap/entity/zip/CentralDirectory.java | 19 +++++++++++++------ .../hap/entity/zip/DataDescriptor.java | 2 +- .../ohos/hapsigntool/hap/entity/zip/Zip.java | 8 ++++---- .../hap/entity/zip/ZipEntryData.java | 14 +++++--------- .../hap/entity/zip/ZipEntryHeader.java | 7 +++++-- 5 files changed, 28 insertions(+), 22 deletions(-) diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/CentralDirectory.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/CentralDirectory.java index 55d981f1..cb005d45 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/CentralDirectory.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/CentralDirectory.java @@ -15,6 +15,8 @@ package com.ohos.hapsigntool.hap.entity.zip; +import com.ohos.hapsigntool.error.ZipException; + import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.charset.StandardCharsets; @@ -142,18 +144,20 @@ class CentralDirectory { * @param bytes Full Central Directory bytes * @param offset One Central Directory offset * @return CentralDirectory + * @throws ZipException read Central Directory exception */ - public static CentralDirectory initCentralDirectory(byte[] bytes, int offset) { + public static CentralDirectory initCentralDirectory(byte[] bytes, int offset) throws ZipException { if (bytes.length < offset) { - return null; + throw new ZipException("find zip central directory failed"); } CentralDirectory cd = new CentralDirectory(); - ByteBuffer bf = ByteBuffer.allocate(bytes.length); - bf.put(bytes, offset, bytes.length - offset); + int byteLength = bytes.length - offset; + ByteBuffer bf = ByteBuffer.allocate(byteLength); + bf.put(bytes, offset, byteLength); bf.order(ByteOrder.LITTLE_ENDIAN); bf.flip(); if (bf.getInt() != SIGNATURE) { - return null; + throw new ZipException("find zip central directory failed"); } cd.setVersion(bf.getShort()); cd.setVersionExtra(bf.getShort()); @@ -186,7 +190,10 @@ class CentralDirectory { bf.get(readComment); cd.setComment(new String(readComment, StandardCharsets.UTF_8)); } - cd.setLength(CD_LENGTH + cd.getFileNameLength() + cd.getExtraLength() + cd.getCommentLength()); + if (CD_LENGTH + cd.getFileNameLength() + cd.getExtraLength() + cd.getCommentLength() != byteLength) { + throw new ZipException("find zip central directory failed"); + } + cd.setLength(byteLength); return cd; } diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/DataDescriptor.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/DataDescriptor.java index d503876b..5a5303c5 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/DataDescriptor.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/DataDescriptor.java @@ -60,7 +60,7 @@ public class DataDescriptor { */ public static DataDescriptor initDataDescriptor(byte[] bytes) throws ZipException { if (bytes.length != DES_LENGTH) { - return null; + throw new ZipException("read Data Descriptor failed"); } ByteBuffer bf = ByteBuffer.allocate(bytes.length); bf.put(bytes); diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/Zip.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/Zip.java index 4240ef87..f5e92116 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/Zip.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/Zip.java @@ -106,20 +106,19 @@ public class Zip { private void getZipCentralDirectory(File file) throws IOException { zipEntries = new ArrayList<>(endOfCentralDirectory.getCDTotal()); cDOffset = endOfCentralDirectory.getOffset(); + // read full central directory bytes byte[] cdBytes = FileUtils.readFileByOffsetAndLength(file, cDOffset, endOfCentralDirectory.getCDSize()); if (cdBytes.length < CentralDirectory.CD_LENGTH) { throw new ZipException("find zip cd failed"); } int offset = 0; + // one by one format central directory while (offset < cdBytes.length) { CentralDirectory cd = CentralDirectory.initCentralDirectory(cdBytes, offset); - if (cd == null) { - throw new ZipException("find zip cd failed"); - } ZipEntry entry = new ZipEntry(); entry.setCentralDirectory(cd); zipEntries.add(entry); - offset += CentralDirectory.CD_LENGTH + cd.getFileNameLength() + cd.getExtraLength() + cd.getCommentLength(); + offset += cd.getLength(); } } @@ -128,6 +127,7 @@ public class Zip { } private void getZipEntries(File file) throws IOException { + // use central directory data, find entry data for (ZipEntry entry : zipEntries) { CentralDirectory cd = entry.getCentralDirectory(); long offset = cd.getOffset(); diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntryData.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntryData.java index 91a42264..3b56b40f 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntryData.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntryData.java @@ -56,32 +56,28 @@ class ZipEntryData { throws IOException { try (FileInputStream input = new FileInputStream(file)) { long offset = entryOffset; + // read entry header by file and offset. byte[] headBytes = FileUtils.readInputByOffsetAndLength(input, entryOffset, ZipEntryHeader.HEADER_LENGTH); ZipEntryHeader entryHeader = ZipEntryHeader.initZipEntryHeader(headBytes); - if (entryHeader == null) { - throw new ZipException("find zip entry head failed"); - } offset += ZipEntryHeader.HEADER_LENGTH; + + // read entry file name and extra by offset. int nameAndExtraLength = entryHeader.getFileNameLength() + entryHeader.getExtraLength(); byte[] nameAndExtra = FileUtils.readInputByLength(input, nameAndExtraLength); entryHeader.setNameAndExtra(nameAndExtra); - offset += nameAndExtraLength; + // skip file data , save file offset and size. ZipEntryData entry = new ZipEntryData(); entry.setFileOffset(offset); entry.setFileSize(compress); input.skip(compress); - offset += compress; long entryLength = entryHeader.getLength() + compress; - if (hasDesc) { + // if entry has data descriptor, read entry data descriptor. byte[] desBytes = FileUtils.readInputByLength(input, DataDescriptor.DES_LENGTH); DataDescriptor dataDesc = DataDescriptor.initDataDescriptor(desBytes); - if (dataDesc == null) { - throw new ZipException("find zip entry desc failed"); - } entryLength += DataDescriptor.DES_LENGTH; entry.setDataDescriptor(dataDesc); } diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntryHeader.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntryHeader.java index 146c40de..0fc05fa7 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntryHeader.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntryHeader.java @@ -15,6 +15,8 @@ package com.ohos.hapsigntool.hap.entity.zip; +import com.ohos.hapsigntool.error.ZipException; + import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.charset.StandardCharsets; @@ -102,15 +104,16 @@ class ZipEntryHeader { * * @param bytes ZipEntryHeader bytes * @return ZipEntryHeader + * @throws ZipException read entry header exception */ - public static ZipEntryHeader initZipEntryHeader(byte[] bytes) { + public static ZipEntryHeader initZipEntryHeader(byte[] bytes) throws ZipException { ZipEntryHeader entryHeader = new ZipEntryHeader(); ByteBuffer bf = ByteBuffer.allocate(bytes.length); bf.put(bytes); bf.order(ByteOrder.LITTLE_ENDIAN); bf.flip(); if (bf.getInt() != ZipEntryHeader.SIGNATURE) { - return null; + throw new ZipException("find zip entry head failed"); } entryHeader.setVersion(bf.getShort()); entryHeader.setFlag(bf.getShort()); -- Gitee From d0780d869ba99033e84f7828293c47007a98b75e Mon Sep 17 00:00:00 2001 From: wangzeyu Date: Tue, 5 Dec 2023 15:34:25 +0800 Subject: [PATCH 19/37] try to alignment zip data Signed-off-by: wangzeyu --- .../src/main/java/com/ohos/hapsigntool/hap/entity/zip/Zip.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/Zip.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/Zip.java index f5e92116..7bde0e8b 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/Zip.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/Zip.java @@ -18,9 +18,6 @@ package com.ohos.hapsigntool.hap.entity.zip; import com.ohos.hapsigntool.error.ZipException; import com.ohos.hapsigntool.utils.FileUtils; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - import java.io.File; import java.io.IOException; import java.util.ArrayList; -- Gitee From 6040abf3aaf60249d7be85b3e7584d71aab75ed4 Mon Sep 17 00:00:00 2001 From: wangzeyu Date: Tue, 5 Dec 2023 15:43:09 +0800 Subject: [PATCH 20/37] try to alignment zip data Signed-off-by: wangzeyu --- .../com/ohos/hapsigntool/hap/entity/zip/CentralDirectory.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/CentralDirectory.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/CentralDirectory.java index cb005d45..6a5a7185 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/CentralDirectory.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/CentralDirectory.java @@ -190,9 +190,6 @@ class CentralDirectory { bf.get(readComment); cd.setComment(new String(readComment, StandardCharsets.UTF_8)); } - if (CD_LENGTH + cd.getFileNameLength() + cd.getExtraLength() + cd.getCommentLength() != byteLength) { - throw new ZipException("find zip central directory failed"); - } cd.setLength(byteLength); return cd; } -- Gitee From b37d3fdebb805275ef2213cbe4d6403d7b58c695 Mon Sep 17 00:00:00 2001 From: wangzeyu Date: Tue, 5 Dec 2023 16:03:51 +0800 Subject: [PATCH 21/37] try to alignment zip data Signed-off-by: wangzeyu --- .../com/ohos/hapsigntool/hap/entity/zip/CentralDirectory.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/CentralDirectory.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/CentralDirectory.java index 6a5a7185..a4572de3 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/CentralDirectory.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/CentralDirectory.java @@ -190,7 +190,7 @@ class CentralDirectory { bf.get(readComment); cd.setComment(new String(readComment, StandardCharsets.UTF_8)); } - cd.setLength(byteLength); + cd.setLength(CD_LENGTH + cd.getFileNameLength() + cd.getExtraLength() + cd.getCommentLength()); return cd; } -- Gitee From 19fc4a6bae557cf413dd934a6344323dc657e025 Mon Sep 17 00:00:00 2001 From: wangzeyu Date: Tue, 5 Dec 2023 17:12:59 +0800 Subject: [PATCH 22/37] try to alignment zip data Signed-off-by: wangzeyu --- .../src/main/java/com/ohos/hapsigntool/utils/FileUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/utils/FileUtils.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/utils/FileUtils.java index 6ffd257f..c322e914 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/utils/FileUtils.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/utils/FileUtils.java @@ -184,7 +184,7 @@ public final class FileUtils { } byte[] suffix = new byte[(int) remainder]; int read = input.read(suffix); - output.write(buffer, 0, read); + output.write(suffix, 0, read); } else { buffer = new byte[(int) length]; int read = input.read(buffer); -- Gitee From e426ee6cc68484a6720429a631c70e90311cd91f Mon Sep 17 00:00:00 2001 From: wangzeyu Date: Wed, 6 Dec 2023 07:22:19 +0000 Subject: [PATCH 23/37] change alignment and sort Signed-off-by: wangzeyu --- .../ohos/hapsigntool/hap/entity/zip/Zip.java | 77 ++++++++++++------- 1 file changed, 51 insertions(+), 26 deletions(-) diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/Zip.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/Zip.java index 7bde0e8b..c787f965 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/Zip.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/Zip.java @@ -21,7 +21,11 @@ import com.ohos.hapsigntool.utils.FileUtils; import java.io.File; import java.io.IOException; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * resolve zip data @@ -29,6 +33,12 @@ import java.util.List; * @since 2023/12/02 */ public class Zip { + private static final Map suffixRegex = new HashMap() {{ + put("so", "\\w+\\.so(\\.[0-9]*)*$"); + put("abc", "\\w+\\.abc$"); + put("an", "\\w+\\.an$"); + }}; + private List zipEntries; private long signingOffset; @@ -43,11 +53,6 @@ public class Zip { private String file; - private final List suffix4K = new ArrayList() {{ - add(".so"); - add(".abc"); - }}; - private final short unCompressMethod = 0; /** @@ -179,26 +184,32 @@ public class Zip { * @throws ZipException alignment exception */ public void alignment() throws ZipException { + sort(); + boolean is4KAlign = true; for (ZipEntry entry : zipEntries) { ZipEntryData zipEntryData = entry.getZipEntryData(); short method = zipEntryData.getZipEntryHeader().getMethod(); if (method != unCompressMethod) { // only align uncompressed entry. - continue; + break; } - // normal file align 4 byte. - short alignBytes = 4; - if (is4kAlignSuffix(zipEntryData.getZipEntryHeader().getFileName())) { + short alignBytes; + if (isRunnableFile(zipEntryData.getZipEntryHeader().getFileName())) { // .abc and .so file align 4096 byte. alignBytes = 4096; + } else { + // the first file after runnable file, align 4096 byte. + if (is4KAlign) { + alignBytes = 4096; + is4KAlign = false; + } else { + // normal file align 4 byte. + alignBytes = 4; + } } - short alignment = zipEntryData.alignment(alignBytes); + short alignment = entry.alignment(alignBytes); if (alignment > 0) { - int offset = entry.getCentralDirectory().getOffset() + alignment; - entry.getCentralDirectory().setOffset(offset); - endOfCentralDirectory.setOffset(endOfCentralDirectory.getOffset() + alignment); - eOCDOffset += alignment; - cDOffset += alignment; + resetOffset(); } } } @@ -206,14 +217,14 @@ public class Zip { /** * sort uncompress entry in the front. */ - public void sort() { + private void sort() { int unCompressOffset = 0; int compressOffset = zipEntries.size() - 1; int pointer = 0; - // sort uncompress file (so, abc) - other uncompress file - compress file + // sort uncompress file (so, abc, an) - other uncompress file - compress file while (pointer <= compressOffset) { ZipEntry entry = zipEntries.get(pointer); - if (is4kAlignSuffix(entry.getZipEntryData().getZipEntryHeader().getFileName()) + if (isRunnableFile(entry.getZipEntryData().getZipEntryHeader().getFileName()) && entry.getZipEntryData().getZipEntryHeader().getMethod() == unCompressMethod) { ZipEntry temp = zipEntries.get(unCompressOffset); zipEntries.set(unCompressOffset, zipEntries.get(pointer)); @@ -231,17 +242,35 @@ public class Zip { } pointer++; } - // reset offset + resetOffset(); + } + + private void resetOffset() { int offset = 0; + int cdLength = 0; for (ZipEntry entry : zipEntries) { entry.getCentralDirectory().setOffset(offset); offset += entry.getZipEntryData().getLength(); + cdLength += entry.getCentralDirectory().getLength(); } + offset += signingBlock.length; + cDOffset = offset; + endOfCentralDirectory.setOffset(offset); + offset += cdLength; + eOCDOffset = offset; } - private boolean is4kAlignSuffix(String name) { - for (String suffix : suffix4K) { - if (name.endsWith(suffix)) { + /** + * regex filename + * + * @param name filename + * @return boolean + */ + public static boolean isRunnableFile(String name) { + for (String regex : suffixRegex.values()) { + Pattern pattern = Pattern.compile(regex); + Matcher matcher = pattern.matcher(name); + if (matcher.matches()) { return true; } } @@ -304,10 +333,6 @@ public class Zip { this.file = file; } - public List getSuffix4K() { - return suffix4K; - } - public short getUnCompressMethod() { return unCompressMethod; } -- Gitee From 089cf6b9b01ff5078853f5487405a5f4297947fa Mon Sep 17 00:00:00 2001 From: wangzeyu Date: Wed, 6 Dec 2023 07:22:47 +0000 Subject: [PATCH 24/37] change alignment and sort Signed-off-by: wangzeyu --- .../hapsigntool/hap/entity/zip/ZipEntry.java | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntry.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntry.java index 59fe7c0b..627c127e 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntry.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntry.java @@ -15,6 +15,10 @@ package com.ohos.hapsigntool.hap.entity.zip; +import com.ohos.hapsigntool.error.ZipException; + +import java.util.Arrays; + /** * ZipEntry and CentralDirectory data * @@ -25,6 +29,42 @@ class ZipEntry { private CentralDirectory centralDirectory; + /** + * alignment one entry + * + * @param alignNum need align bytes length + * @return add bytes length + * @throws ZipException alignment exception + */ + public short alignment(short alignNum) throws ZipException { + long add = (zipEntryData.getZipEntryHeader().getLength() + centralDirectory.getOffset()) % alignNum; + if (add == 0) { + return 0; + } + int newExtraLength = zipEntryData.getZipEntryHeader().getExtraLength() + (short) add; + if (newExtraLength > Short.MAX_VALUE) { + throw new ZipException("can not align " + zipEntryData.getZipEntryHeader().getFileName()); + } + short extraLength = (short) newExtraLength; + zipEntryData.getZipEntryHeader().setExtraLength(extraLength); + byte[] oldExtraData = zipEntryData.getZipEntryHeader().getExtraData(); + byte[] newExtra; + if (oldExtraData == null) { + newExtra = new byte[newExtraLength]; + } else { + newExtra = Arrays.copyOf(oldExtraData, newExtraLength); + } + zipEntryData.getZipEntryHeader().setExtraData(newExtra); + int newLength = ZipEntryHeader.HEADER_LENGTH + zipEntryData.getZipEntryHeader().getFileNameLength() + + newExtraLength; + if (zipEntryData.getZipEntryHeader().getLength() + add != newLength) { + throw new ZipException("can not align " + zipEntryData.getZipEntryHeader().getFileName()); + } + zipEntryData.getZipEntryHeader().setLength(newLength); + zipEntryData.setLength(zipEntryData.getLength() + add); + return (short) add; + } + public ZipEntryData getZipEntryData() { return zipEntryData; } -- Gitee From 93e0f33ca15a3a95cfc884a9d182f4aa087ed1c4 Mon Sep 17 00:00:00 2001 From: wangzeyu Date: Wed, 6 Dec 2023 07:23:26 +0000 Subject: [PATCH 25/37] change alignment and sort Signed-off-by: wangzeyu --- .../hap/entity/zip/ZipEntryData.java | 34 ------------------- 1 file changed, 34 deletions(-) diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntryData.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntryData.java index 3b56b40f..fb1d25ec 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntryData.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntryData.java @@ -15,7 +15,6 @@ package com.ohos.hapsigntool.hap.entity.zip; -import com.ohos.hapsigntool.error.ZipException; import com.ohos.hapsigntool.utils.FileUtils; import java.io.File; @@ -87,39 +86,6 @@ class ZipEntryData { } } - /** - * alignment one entry - * - * @param alignNum need align bytes length - * @return add bytes length - * @throws ZipException alignment exception - */ - public short alignment(short alignNum) throws ZipException { - long add = alignNum - length % alignNum; - if (add == alignNum) { - return 0; - } - if (add > Short.MAX_VALUE) { - throw new ZipException("can not align " + zipEntryHeader.getFileName()); - } - int newExtraLength = zipEntryHeader.getExtraLength() + (short) add; - if (newExtraLength > Short.MAX_VALUE) { - throw new ZipException("can not align " + zipEntryHeader.getFileName()); - } - short extraLength = (short) newExtraLength; - zipEntryHeader.setExtraLength(extraLength); - byte[] extra = new byte[extraLength]; - zipEntryHeader.setExtraData(extra); - int newLength = ZipEntryHeader.HEADER_LENGTH - + zipEntryHeader.getFileNameLength() + zipEntryHeader.getExtraData().length; - if (zipEntryHeader.getLength() + add != newLength) { - throw new ZipException("can not align " + zipEntryHeader.getFileName()); - } - zipEntryHeader.setLength(newLength); - this.length += add; - return (short) add; - } - public void setZipEntryHeader(ZipEntryHeader zipEntryHeader) { this.zipEntryHeader = zipEntryHeader; } -- Gitee From 9319c50d1671be5e9e65559b127b875255a603e5 Mon Sep 17 00:00:00 2001 From: wangzeyu Date: Wed, 6 Dec 2023 15:25:00 +0800 Subject: [PATCH 26/37] try to alignment zip data Signed-off-by: wangzeyu --- .../java/com/ohos/hapsigntool/hap/provider/SignProvider.java | 1 - 1 file changed, 1 deletion(-) diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/provider/SignProvider.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/provider/SignProvider.java index def0dea7..9c79780b 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/provider/SignProvider.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/provider/SignProvider.java @@ -507,7 +507,6 @@ public abstract class SignProvider { throws IOException, HapFormatException { Zip zip = new Zip(input); zip.alignment(); - zip.sort(); zip.toFile(tmpOutput.getPath()); } -- Gitee From 7966c8d5f02a92d70f381cc5ec5454edbf2a3472 Mon Sep 17 00:00:00 2001 From: wangzeyu Date: Thu, 7 Dec 2023 02:19:46 +0000 Subject: [PATCH 27/37] codecheck repair Signed-off-by: wangzeyu --- .../ohos/hapsigntool/error/ZipException.java | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/error/ZipException.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/error/ZipException.java index fc525d97..c59110a9 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/error/ZipException.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/error/ZipException.java @@ -2,15 +2,27 @@ package com.ohos.hapsigntool.error; import java.io.IOException; +/** + * Zip exception for programs. + * + * @since 2023/12/07 + */ public class ZipException extends IOException { - public ZipException() { - - } - + /** + * new ZipException + * + * @param message exception message + */ public ZipException(String message) { super(message); } + /** + * new ZipException + * + * @param message exception message + * @param e exception + */ public ZipException(String message, Exception e) { super(message, e); } -- Gitee From d2cf9f3dc63b9c643b75ea2893a3e10aa2602213 Mon Sep 17 00:00:00 2001 From: wangzeyu Date: Thu, 7 Dec 2023 02:38:37 +0000 Subject: [PATCH 28/37] codecheck repair Signed-off-by: wangzeyu --- .../ohos/hapsigntool/error/ZipException.java | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/error/ZipException.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/error/ZipException.java index c59110a9..a7062424 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/error/ZipException.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/error/ZipException.java @@ -1,4 +1,19 @@ -package com.ohos.hapsigntool.error; +/* + * Copyright (c) 2023-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + package com.ohos.hapsigntool.error; import java.io.IOException; -- Gitee From cce8f2bdf7607c883bf793ba201bf54c6289096a Mon Sep 17 00:00:00 2001 From: wangzeyu Date: Thu, 7 Dec 2023 15:36:43 +0800 Subject: [PATCH 29/37] try to alignment zip data Signed-off-by: wangzeyu --- .../com/ohos/hapsigntool/hap/entity/zip/Zip.java | 14 +++++++------- .../ohos/hapsigntool/hap/entity/zip/ZipEntry.java | 9 ++++----- .../hapsigntool/hap/provider/SignProvider.java | 2 +- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/Zip.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/Zip.java index c787f965..cd1364ae 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/Zip.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/Zip.java @@ -135,9 +135,9 @@ public class Zip { long offset = cd.getOffset(); long fileSize = cd.getCompressedSize(); short flag = cd.getFlag(); - short i = 0x08; + short mask = 0x08; // set desc null flag - boolean hasDesc = (flag & i) != 0; + boolean hasDesc = (flag & mask) != 0; entry.setZipEntryData(ZipEntryData.initZipEntry(file, offset, fileSize, hasDesc)); } ZipEntry endEntry = zipEntries.get(zipEntries.size() - 1); @@ -183,7 +183,7 @@ public class Zip { * * @throws ZipException alignment exception */ - public void alignment() throws ZipException { + public void alignment(int alignment) throws ZipException { sort(); boolean is4KAlign = true; for (ZipEntry entry : zipEntries) { @@ -193,7 +193,7 @@ public class Zip { // only align uncompressed entry. break; } - short alignBytes; + int alignBytes; if (isRunnableFile(zipEntryData.getZipEntryHeader().getFileName())) { // .abc and .so file align 4096 byte. alignBytes = 4096; @@ -204,11 +204,11 @@ public class Zip { is4KAlign = false; } else { // normal file align 4 byte. - alignBytes = 4; + alignBytes = alignment; } } - short alignment = entry.alignment(alignBytes); - if (alignment > 0) { + int add = entry.alignment(alignBytes); + if (add > 0) { resetOffset(); } } diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntry.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntry.java index 627c127e..e1b0ec94 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntry.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntry.java @@ -36,17 +36,16 @@ class ZipEntry { * @return add bytes length * @throws ZipException alignment exception */ - public short alignment(short alignNum) throws ZipException { + public int alignment(int alignNum) throws ZipException { long add = (zipEntryData.getZipEntryHeader().getLength() + centralDirectory.getOffset()) % alignNum; if (add == 0) { return 0; } - int newExtraLength = zipEntryData.getZipEntryHeader().getExtraLength() + (short) add; + int newExtraLength = zipEntryData.getZipEntryHeader().getExtraLength() + (int) add; if (newExtraLength > Short.MAX_VALUE) { throw new ZipException("can not align " + zipEntryData.getZipEntryHeader().getFileName()); } - short extraLength = (short) newExtraLength; - zipEntryData.getZipEntryHeader().setExtraLength(extraLength); + zipEntryData.getZipEntryHeader().setExtraLength((short) newExtraLength); byte[] oldExtraData = zipEntryData.getZipEntryHeader().getExtraData(); byte[] newExtra; if (oldExtraData == null) { @@ -62,7 +61,7 @@ class ZipEntry { } zipEntryData.getZipEntryHeader().setLength(newLength); zipEntryData.setLength(zipEntryData.getLength() + add); - return (short) add; + return (int) add; } public ZipEntryData getZipEntryData() { diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/provider/SignProvider.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/provider/SignProvider.java index 9c79780b..817c4f3d 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/provider/SignProvider.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/provider/SignProvider.java @@ -506,7 +506,7 @@ public abstract class SignProvider { private void copyFileAndAlignment(File input, File tmpOutput, int alignment) throws IOException, HapFormatException { Zip zip = new Zip(input); - zip.alignment(); + zip.alignment(alignment); zip.toFile(tmpOutput.getPath()); } -- Gitee From cea3d76044ad922f2228f2254011669a8fb1298a Mon Sep 17 00:00:00 2001 From: wangzeyu Date: Sat, 9 Dec 2023 09:31:16 +0000 Subject: [PATCH 30/37] unsigned int overflow Signed-off-by: wangzeyu --- .../hap/entity/zip/CentralDirectory.java | 97 ++++++++++--------- 1 file changed, 53 insertions(+), 44 deletions(-) diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/CentralDirectory.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/CentralDirectory.java index a4572de3..66501ee2 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/CentralDirectory.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/CentralDirectory.java @@ -76,32 +76,32 @@ class CentralDirectory { /** * 4 bytes */ - private int compressedSize; + private long compressedSize; /** * 4 bytes */ - private int unCompressedSize; + private long unCompressedSize; /** * 2 bytes */ - private short fileNameLength; + private int fileNameLength; /** * 2 bytes */ - private short extraLength; + private int extraLength; /** * 2 bytes */ - private short commentLength; + private int commentLength; /** * 2 bytes */ - private short diskNumStart; + private int diskNumStart; /** @@ -119,7 +119,7 @@ class CentralDirectory { /** * 4 bytes */ - private int offset; + private long offset; /** * n bytes @@ -159,6 +159,7 @@ class CentralDirectory { if (bf.getInt() != SIGNATURE) { throw new ZipException("find zip central directory failed"); } + cd.setVersion(bf.getShort()); cd.setVersionExtra(bf.getShort()); cd.setFlag(bf.getShort()); @@ -166,15 +167,15 @@ class CentralDirectory { cd.setLastTime(bf.getShort()); cd.setLastDate(bf.getShort()); cd.setCrc32(bf.getInt()); - cd.setCompressedSize(bf.getInt()); - cd.setUnCompressedSize(bf.getInt()); - cd.setFileNameLength(bf.getShort()); - cd.setExtraLength(bf.getShort()); - cd.setCommentLength(bf.getShort()); - cd.setDiskNumStart(bf.getShort()); + cd.setCompressedSize(UnsignedDecimalUtil.getUnsignedInt(bf)); + cd.setUnCompressedSize(UnsignedDecimalUtil.getUnsignedInt(bf)); + cd.setFileNameLength(UnsignedDecimalUtil.getUnsignedShort(bf)); + cd.setExtraLength(UnsignedDecimalUtil.getUnsignedShort(bf)); + cd.setCommentLength(UnsignedDecimalUtil.getUnsignedShort(bf)); + cd.setDiskNumStart(UnsignedDecimalUtil.getUnsignedShort(bf)); cd.setInternalFile(bf.getShort()); cd.setExternalFile(bf.getInt()); - cd.setOffset(bf.getInt()); + cd.setOffset(UnsignedDecimalUtil.getUnsignedInt(bf)); if (cd.getFileNameLength() > 0) { byte[] readFileName = new byte[cd.getFileNameLength()]; bf.get(readFileName); @@ -202,22 +203,22 @@ class CentralDirectory { public byte[] toBytes() { ByteBuffer bf = ByteBuffer.allocate(length).order(ByteOrder.LITTLE_ENDIAN); bf.putInt(SIGNATURE); - bf.putShort(version); - bf.putShort(versionExtra); - bf.putShort(flag); - bf.putShort(method); - bf.putShort(lastTime); - bf.putShort(lastDate); - bf.putInt(crc32); - bf.putInt(compressedSize); - bf.putInt(unCompressedSize); - bf.putShort(fileNameLength); - bf.putShort(extraLength); - bf.putShort(commentLength); - bf.putShort(diskNumStart); - bf.putShort(internalFile); - bf.putInt(externalFile); - bf.putInt(offset); + UnsignedDecimalUtil.setUnsignedShort(bf, version); + UnsignedDecimalUtil.setUnsignedShort(bf, versionExtra); + UnsignedDecimalUtil.setUnsignedShort(bf, flag); + UnsignedDecimalUtil.setUnsignedShort(bf, method); + UnsignedDecimalUtil.setUnsignedShort(bf, lastTime); + UnsignedDecimalUtil.setUnsignedShort(bf, lastDate); + UnsignedDecimalUtil.setUnsignedInt(bf, crc32); + UnsignedDecimalUtil.setUnsignedInt(bf, compressedSize); + UnsignedDecimalUtil.setUnsignedInt(bf, unCompressedSize); + UnsignedDecimalUtil.setUnsignedShort(bf, fileNameLength); + UnsignedDecimalUtil.setUnsignedShort(bf, extraLength); + UnsignedDecimalUtil.setUnsignedShort(bf, commentLength); + UnsignedDecimalUtil.setUnsignedShort(bf, diskNumStart); + UnsignedDecimalUtil.setUnsignedShort(bf, internalFile); + UnsignedDecimalUtil.setUnsignedInt(bf, externalFile); + UnsignedDecimalUtil.setUnsignedInt(bf, offset); if (fileNameLength > 0) { bf.put(fileName.getBytes(StandardCharsets.UTF_8)); } @@ -230,6 +231,14 @@ class CentralDirectory { return bf.array(); } + public static int getCdLength() { + return CD_LENGTH; + } + + public static int getSIGNATURE() { + return SIGNATURE; + } + public short getVersion() { return version; } @@ -286,51 +295,51 @@ class CentralDirectory { this.crc32 = crc32; } - public int getCompressedSize() { + public long getCompressedSize() { return compressedSize; } - public void setCompressedSize(int compressedSize) { + public void setCompressedSize(long compressedSize) { this.compressedSize = compressedSize; } - public int getUnCompressedSize() { + public long getUnCompressedSize() { return unCompressedSize; } - public void setUnCompressedSize(int unCompressedSize) { + public void setUnCompressedSize(long unCompressedSize) { this.unCompressedSize = unCompressedSize; } - public short getFileNameLength() { + public int getFileNameLength() { return fileNameLength; } - public void setFileNameLength(short fileNameLength) { + public void setFileNameLength(int fileNameLength) { this.fileNameLength = fileNameLength; } - public short getExtraLength() { + public int getExtraLength() { return extraLength; } - public void setExtraLength(short extraLength) { + public void setExtraLength(int extraLength) { this.extraLength = extraLength; } - public short getCommentLength() { + public int getCommentLength() { return commentLength; } - public void setCommentLength(short commentLength) { + public void setCommentLength(int commentLength) { this.commentLength = commentLength; } - public short getDiskNumStart() { + public int getDiskNumStart() { return diskNumStart; } - public void setDiskNumStart(short diskNumStart) { + public void setDiskNumStart(int diskNumStart) { this.diskNumStart = diskNumStart; } @@ -350,11 +359,11 @@ class CentralDirectory { this.externalFile = externalFile; } - public int getOffset() { + public long getOffset() { return offset; } - public void setOffset(int offset) { + public void setOffset(long offset) { this.offset = offset; } -- Gitee From 763c08941a5a8fb0191c85f27fb1ebd60b921812 Mon Sep 17 00:00:00 2001 From: wangzeyu Date: Sat, 9 Dec 2023 09:33:18 +0000 Subject: [PATCH 31/37] unsigned int overflow Signed-off-by: wangzeyu --- .../hap/entity/zip/DataDescriptor.java | 28 ++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/DataDescriptor.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/DataDescriptor.java index 5a5303c5..fc3da08e 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/DataDescriptor.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/DataDescriptor.java @@ -44,12 +44,12 @@ public class DataDescriptor { /** * 4 bytes */ - private int compressedSize; + private long compressedSize; /** * 4 bytes */ - private int unCompressedSize; + private long unCompressedSize; /** * init Central Directory @@ -71,8 +71,8 @@ public class DataDescriptor { throw new ZipException("read Data Descriptor failed"); } data.setCrc32(bf.getInt()); - data.setCompressedSize(bf.getInt()); - data.setUnCompressedSize(bf.getInt()); + data.setCompressedSize(UnsignedDecimalUtil.getUnsignedInt(bf)); + data.setUnCompressedSize(UnsignedDecimalUtil.getUnsignedInt(bf)); return data; } @@ -85,11 +85,19 @@ public class DataDescriptor { ByteBuffer bf = ByteBuffer.allocate(DES_LENGTH).order(ByteOrder.LITTLE_ENDIAN); bf.putInt(SIGNATURE); bf.putInt(crc32); - bf.putInt(compressedSize); - bf.putInt(unCompressedSize); + UnsignedDecimalUtil.setUnsignedInt(bf, compressedSize); + UnsignedDecimalUtil.setUnsignedInt(bf, unCompressedSize); return bf.array(); } + public static int getDesLength() { + return DES_LENGTH; + } + + public static int getSIGNATURE() { + return SIGNATURE; + } + public int getCrc32() { return crc32; } @@ -98,19 +106,19 @@ public class DataDescriptor { this.crc32 = crc32; } - public int getCompressedSize() { + public long getCompressedSize() { return compressedSize; } - public void setCompressedSize(int compressedSize) { + public void setCompressedSize(long compressedSize) { this.compressedSize = compressedSize; } - public int getUnCompressedSize() { + public long getUnCompressedSize() { return unCompressedSize; } - public void setUnCompressedSize(int unCompressedSize) { + public void setUnCompressedSize(long unCompressedSize) { this.unCompressedSize = unCompressedSize; } } -- Gitee From 87677602718a2a1a7a23597065436071f7202a6f Mon Sep 17 00:00:00 2001 From: wangzeyu Date: Sat, 9 Dec 2023 09:33:31 +0000 Subject: [PATCH 32/37] unsigned int overflow Signed-off-by: wangzeyu --- .../hap/entity/zip/DataDescriptor.java | 184 +++++++++++++----- 1 file changed, 137 insertions(+), 47 deletions(-) diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/DataDescriptor.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/DataDescriptor.java index fc3da08e..dfc2ba14 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/DataDescriptor.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/DataDescriptor.java @@ -15,110 +15,200 @@ package com.ohos.hapsigntool.hap.entity.zip; -import com.ohos.hapsigntool.error.ZipException; - import java.nio.ByteBuffer; import java.nio.ByteOrder; +import java.nio.charset.StandardCharsets; /** - * resolve zip DataDescriptor data + * resolve zip EndOfCentralDirectory data * - * @since 2023/12/02 + * @since 2023/12/04 */ -public class DataDescriptor { +class EndOfCentralDirectory { /** - * DataDescriptor invariable bytes length + * EndOfCentralDirectory invariable bytes length */ - public static final int DES_LENGTH = 16; + public static final int EOCD_LENGTH = 22; /** - * 4 bytes , DataDescriptor signature + * 4 bytes , central directory signature */ - public static final int SIGNATURE = 0x08074b50; + public static final int SIGNATURE = 0x06054b50; /** - * 4 bytes + * 2 bytes + */ + private int diskNum; + + /** + * 2 bytes + */ + private int cDStartDiskNum; + + /** + * 2 bytes + */ + private int thisDiskCDNum; + + /** + * 2 bytes */ - private int crc32; + private int cDTotal; /** * 4 bytes */ - private long compressedSize; + private long cDSize; /** * 4 bytes */ - private long unCompressedSize; + private long offset; /** - * init Central Directory + * 2 bytes + */ + private int commentLength; + + /** + * n bytes + */ + private String comment; + + private int length; + + /** + * init End Of Central Directory * - * @param bytes DataDescriptor bytes - * @return DataDescriptor - * @throws ZipException read data descriptor exception + * @param bytes End Of Central Directory bytes + * @return End Of Central Directory */ - public static DataDescriptor initDataDescriptor(byte[] bytes) throws ZipException { - if (bytes.length != DES_LENGTH) { - throw new ZipException("read Data Descriptor failed"); - } + public static EndOfCentralDirectory initEOCDByBytes(byte[] bytes) { + EndOfCentralDirectory eocd = new EndOfCentralDirectory(); ByteBuffer bf = ByteBuffer.allocate(bytes.length); bf.put(bytes); bf.order(ByteOrder.LITTLE_ENDIAN); bf.flip(); - DataDescriptor data = new DataDescriptor(); if (bf.getInt() != SIGNATURE) { - throw new ZipException("read Data Descriptor failed"); + return null; + } + eocd.setDiskNum(UnsignedDecimalUtil.getUnsignedShort(bf)); + eocd.setcDStartDiskNum(UnsignedDecimalUtil.getUnsignedShort(bf)); + eocd.setThisDiskCDNum(UnsignedDecimalUtil.getUnsignedShort(bf)); + eocd.setcDTotal(UnsignedDecimalUtil.getUnsignedShort(bf)); + eocd.setcDSize(UnsignedDecimalUtil.getUnsignedInt(bf)); + eocd.setOffset(UnsignedDecimalUtil.getUnsignedInt(bf)); + eocd.setCommentLength(UnsignedDecimalUtil.getUnsignedShort(bf)); + if (eocd.getCommentLength() > 0) { + byte[] readComment = new byte[eocd.getCommentLength()]; + bf.get(readComment); + eocd.setComment(new String(readComment, StandardCharsets.UTF_8)); + } + eocd.setLength(EOCD_LENGTH + eocd.getCommentLength()); + if (bf.remaining() != 0) { + return null; } - data.setCrc32(bf.getInt()); - data.setCompressedSize(UnsignedDecimalUtil.getUnsignedInt(bf)); - data.setUnCompressedSize(UnsignedDecimalUtil.getUnsignedInt(bf)); - return data; + return eocd; } /** - * change DataDescriptor to bytes + * change End Of Central Directory to bytes * * @return bytes */ public byte[] toBytes() { - ByteBuffer bf = ByteBuffer.allocate(DES_LENGTH).order(ByteOrder.LITTLE_ENDIAN); + ByteBuffer bf = ByteBuffer.allocate(length).order(ByteOrder.LITTLE_ENDIAN); bf.putInt(SIGNATURE); - bf.putInt(crc32); - UnsignedDecimalUtil.setUnsignedInt(bf, compressedSize); - UnsignedDecimalUtil.setUnsignedInt(bf, unCompressedSize); + UnsignedDecimalUtil.setUnsignedShort(bf, diskNum); + UnsignedDecimalUtil.setUnsignedShort(bf, cDStartDiskNum); + UnsignedDecimalUtil.setUnsignedShort(bf, thisDiskCDNum); + UnsignedDecimalUtil.setUnsignedShort(bf, cDTotal); + UnsignedDecimalUtil.setUnsignedInt(bf, cDSize); + UnsignedDecimalUtil.setUnsignedInt(bf, offset); + UnsignedDecimalUtil.setUnsignedShort(bf, commentLength); + if (commentLength > 0) { + bf.put(comment.getBytes(StandardCharsets.UTF_8)); + } return bf.array(); } - public static int getDesLength() { - return DES_LENGTH; + public static int getEocdLength() { + return EOCD_LENGTH; } public static int getSIGNATURE() { return SIGNATURE; } - public int getCrc32() { - return crc32; + public int getDiskNum() { + return diskNum; + } + + public void setDiskNum(int diskNum) { + this.diskNum = diskNum; + } + + public int getcDStartDiskNum() { + return cDStartDiskNum; + } + + public void setcDStartDiskNum(int cDStartDiskNum) { + this.cDStartDiskNum = cDStartDiskNum; + } + + public int getThisDiskCDNum() { + return thisDiskCDNum; + } + + public void setThisDiskCDNum(int thisDiskCDNum) { + this.thisDiskCDNum = thisDiskCDNum; + } + + public int getcDTotal() { + return cDTotal; + } + + public void setcDTotal(int cDTotal) { + this.cDTotal = cDTotal; + } + + public long getcDSize() { + return cDSize; + } + + public void setcDSize(long cDSize) { + this.cDSize = cDSize; + } + + public long getOffset() { + return offset; + } + + public void setOffset(long offset) { + this.offset = offset; + } + + public int getCommentLength() { + return commentLength; } - public void setCrc32(int crc32) { - this.crc32 = crc32; + public void setCommentLength(int commentLength) { + this.commentLength = commentLength; } - public long getCompressedSize() { - return compressedSize; + public String getComment() { + return comment; } - public void setCompressedSize(long compressedSize) { - this.compressedSize = compressedSize; + public void setComment(String comment) { + this.comment = comment; } - public long getUnCompressedSize() { - return unCompressedSize; + public int getLength() { + return length; } - public void setUnCompressedSize(long unCompressedSize) { - this.unCompressedSize = unCompressedSize; + public void setLength(int length) { + this.length = length; } -} +} \ No newline at end of file -- Gitee From 90e8e4cab37336867fa6951381cea1b54f5f6b30 Mon Sep 17 00:00:00 2001 From: wangzeyu Date: Sat, 9 Dec 2023 09:33:55 +0000 Subject: [PATCH 33/37] unsigned int overflow Signed-off-by: wangzeyu --- .../java/com/ohos/hapsigntool/hap/entity/zip/Zip.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/Zip.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/Zip.java index cd1364ae..54851e15 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/Zip.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/Zip.java @@ -106,10 +106,10 @@ public class Zip { } private void getZipCentralDirectory(File file) throws IOException { - zipEntries = new ArrayList<>(endOfCentralDirectory.getCDTotal()); + zipEntries = new ArrayList<>(endOfCentralDirectory.getcDTotal()); cDOffset = endOfCentralDirectory.getOffset(); // read full central directory bytes - byte[] cdBytes = FileUtils.readFileByOffsetAndLength(file, cDOffset, endOfCentralDirectory.getCDSize()); + byte[] cdBytes = FileUtils.readFileByOffsetAndLength(file, cDOffset, endOfCentralDirectory.getcDSize()); if (cdBytes.length < CentralDirectory.CD_LENGTH) { throw new ZipException("find zip cd failed"); } @@ -246,8 +246,8 @@ public class Zip { } private void resetOffset() { - int offset = 0; - int cdLength = 0; + long offset = 0; + long cdLength = 0; for (ZipEntry entry : zipEntries) { entry.getCentralDirectory().setOffset(offset); offset += entry.getZipEntryData().getLength(); -- Gitee From f69ea2da9d10fe5deb5e27136c517d6a028944e2 Mon Sep 17 00:00:00 2001 From: wangzeyu Date: Sat, 9 Dec 2023 09:34:07 +0000 Subject: [PATCH 34/37] unsigned int overflow Signed-off-by: wangzeyu --- .../hap/entity/zip/ZipEntryHeader.java | 64 +++++++++++-------- 1 file changed, 36 insertions(+), 28 deletions(-) diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntryHeader.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntryHeader.java index 0fc05fa7..bf921df6 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntryHeader.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/ZipEntryHeader.java @@ -70,22 +70,22 @@ class ZipEntryHeader { /** * 4 bytes */ - private int compressedSize; + private long compressedSize; /** * 4 bytes */ - private int unCompressedSize; + private long unCompressedSize; /** * 2 bytes */ - private short fileNameLength; + private int fileNameLength; /** * 2 bytes */ - private short extraLength; + private int extraLength; /** * n bytes @@ -121,10 +121,10 @@ class ZipEntryHeader { entryHeader.setLastTime(bf.getShort()); entryHeader.setLastDate(bf.getShort()); entryHeader.setCrc32(bf.getInt()); - entryHeader.setCompressedSize(bf.getInt()); - entryHeader.setUnCompressedSize(bf.getInt()); - entryHeader.setFileNameLength(bf.getShort()); - entryHeader.setExtraLength(bf.getShort()); + entryHeader.setCompressedSize(UnsignedDecimalUtil.getUnsignedInt(bf)); + entryHeader.setUnCompressedSize(UnsignedDecimalUtil.getUnsignedInt(bf)); + entryHeader.setFileNameLength(UnsignedDecimalUtil.getUnsignedShort(bf)); + entryHeader.setExtraLength(UnsignedDecimalUtil.getUnsignedShort(bf)); entryHeader.setLength(HEADER_LENGTH + entryHeader.getFileNameLength() + entryHeader.getExtraLength()); return entryHeader; } @@ -165,10 +165,10 @@ class ZipEntryHeader { bf.putShort(lastTime); bf.putShort(lastDate); bf.putInt(crc32); - bf.putInt(compressedSize); - bf.putInt(unCompressedSize); - bf.putShort(fileNameLength); - bf.putShort(extraLength); + UnsignedDecimalUtil.setUnsignedInt(bf, compressedSize); + UnsignedDecimalUtil.setUnsignedInt(bf, unCompressedSize); + UnsignedDecimalUtil.setUnsignedShort(bf, fileNameLength); + UnsignedDecimalUtil.setUnsignedShort(bf, extraLength); if (fileNameLength > 0) { bf.put(fileName.getBytes(StandardCharsets.UTF_8)); } @@ -178,6 +178,22 @@ class ZipEntryHeader { return bf.array(); } + public static int getHeaderLength() { + return HEADER_LENGTH; + } + + public static int getSIGNATURE() { + return SIGNATURE; + } + + public short getVersion() { + return version; + } + + public void setVersion(short version) { + this.version = version; + } + public short getFlag() { return flag; } @@ -194,14 +210,6 @@ class ZipEntryHeader { this.method = method; } - public short getVersion() { - return version; - } - - public void setVersion(short version) { - this.version = version; - } - public short getLastTime() { return lastTime; } @@ -226,35 +234,35 @@ class ZipEntryHeader { this.crc32 = crc32; } - public int getCompressedSize() { + public long getCompressedSize() { return compressedSize; } - public void setCompressedSize(int compressedSize) { + public void setCompressedSize(long compressedSize) { this.compressedSize = compressedSize; } - public int getUnCompressedSize() { + public long getUnCompressedSize() { return unCompressedSize; } - public void setUnCompressedSize(int unCompressedSize) { + public void setUnCompressedSize(long unCompressedSize) { this.unCompressedSize = unCompressedSize; } - public short getFileNameLength() { + public int getFileNameLength() { return fileNameLength; } - public void setFileNameLength(short fileNameLength) { + public void setFileNameLength(int fileNameLength) { this.fileNameLength = fileNameLength; } - public short getExtraLength() { + public int getExtraLength() { return extraLength; } - public void setExtraLength(short extraLength) { + public void setExtraLength(int extraLength) { this.extraLength = extraLength; } -- Gitee From b9b75ed83dd4ae0f897d5605b461a419852dcbc9 Mon Sep 17 00:00:00 2001 From: wangzeyu Date: Sat, 9 Dec 2023 09:34:29 +0000 Subject: [PATCH 35/37] unsigned int overflow Signed-off-by: wangzeyu --- .../hap/entity/zip/UnsignedDecimalUtil.java | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/UnsignedDecimalUtil.java diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/UnsignedDecimalUtil.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/UnsignedDecimalUtil.java new file mode 100644 index 00000000..fe804fd7 --- /dev/null +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/UnsignedDecimalUtil.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2023-2023 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.ohos.hapsigntool.hap.entity.zip; + +import java.nio.ByteBuffer; + +/** + * Unsigned Decimal Util + * + * @since 2023/12/09 + */ +public class UnsignedDecimalUtil { + private static final int BIT_SIZE = 8; + + private static final int DOUBLE_BIT_SIZE = 16; + + private static final int TRIPLE_BIT_SIZE = 24; + + /** + * get unsigned int to long + * + * @param bf byteBuffer + * @return long + */ + public static long getUnsignedInt(ByteBuffer bf) { + int i = bf.getInt(); + if (i >= 0) { + return i; + } + return i & 0xFFFFFFFFL; + } + + /** + * get unsigned short to int + * + * @param bf byteBuffer + * @return int + */ + public static int getUnsignedShort(ByteBuffer bf) { + short s = bf.getShort(); + if (s >= 0) { + return s; + } + return s & 0xFFFF; + } + + /** + * set long to unsigned int + * + * @param bf byteBuffer + * @param l long + */ + public static void setUnsignedInt(ByteBuffer bf, long l) { + byte[] bytes = { + (byte) (l & 0xff), + (byte) ((l >> BIT_SIZE) & 0xff), + (byte) ((l >> DOUBLE_BIT_SIZE) & 0xff), + (byte) ((l >> TRIPLE_BIT_SIZE) & 0xff), + }; + bf.put(bytes); + } + + /** + * set int to unsigned short + * + * @param bf byteBuffer + * @param i int + */ + public static void setUnsignedShort(ByteBuffer bf, int i) { + byte[] bytes = { + (byte) (i & 0xff), + (byte) ((i >> BIT_SIZE) & 0xff), + }; + bf.put(bytes); + } +} -- Gitee From a8276baf3975d64cc0bc4d0d98418eac4546db88 Mon Sep 17 00:00:00 2001 From: wangzeyu Date: Sat, 9 Dec 2023 09:35:45 +0000 Subject: [PATCH 36/37] unsigned int overflow Signed-off-by: wangzeyu --- .../hap/entity/zip/DataDescriptor.java | 184 +++++------------- 1 file changed, 47 insertions(+), 137 deletions(-) diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/DataDescriptor.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/DataDescriptor.java index dfc2ba14..fc3da08e 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/DataDescriptor.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/DataDescriptor.java @@ -15,200 +15,110 @@ package com.ohos.hapsigntool.hap.entity.zip; +import com.ohos.hapsigntool.error.ZipException; + import java.nio.ByteBuffer; import java.nio.ByteOrder; -import java.nio.charset.StandardCharsets; /** - * resolve zip EndOfCentralDirectory data + * resolve zip DataDescriptor data * - * @since 2023/12/04 + * @since 2023/12/02 */ -class EndOfCentralDirectory { - /** - * EndOfCentralDirectory invariable bytes length - */ - public static final int EOCD_LENGTH = 22; - - /** - * 4 bytes , central directory signature - */ - public static final int SIGNATURE = 0x06054b50; - - /** - * 2 bytes - */ - private int diskNum; - +public class DataDescriptor { /** - * 2 bytes + * DataDescriptor invariable bytes length */ - private int cDStartDiskNum; + public static final int DES_LENGTH = 16; /** - * 2 bytes + * 4 bytes , DataDescriptor signature */ - private int thisDiskCDNum; - - /** - * 2 bytes - */ - private int cDTotal; + public static final int SIGNATURE = 0x08074b50; /** * 4 bytes */ - private long cDSize; + private int crc32; /** * 4 bytes */ - private long offset; - - /** - * 2 bytes - */ - private int commentLength; + private long compressedSize; /** - * n bytes + * 4 bytes */ - private String comment; - - private int length; + private long unCompressedSize; /** - * init End Of Central Directory + * init Central Directory * - * @param bytes End Of Central Directory bytes - * @return End Of Central Directory + * @param bytes DataDescriptor bytes + * @return DataDescriptor + * @throws ZipException read data descriptor exception */ - public static EndOfCentralDirectory initEOCDByBytes(byte[] bytes) { - EndOfCentralDirectory eocd = new EndOfCentralDirectory(); + public static DataDescriptor initDataDescriptor(byte[] bytes) throws ZipException { + if (bytes.length != DES_LENGTH) { + throw new ZipException("read Data Descriptor failed"); + } ByteBuffer bf = ByteBuffer.allocate(bytes.length); bf.put(bytes); bf.order(ByteOrder.LITTLE_ENDIAN); bf.flip(); + DataDescriptor data = new DataDescriptor(); if (bf.getInt() != SIGNATURE) { - return null; - } - eocd.setDiskNum(UnsignedDecimalUtil.getUnsignedShort(bf)); - eocd.setcDStartDiskNum(UnsignedDecimalUtil.getUnsignedShort(bf)); - eocd.setThisDiskCDNum(UnsignedDecimalUtil.getUnsignedShort(bf)); - eocd.setcDTotal(UnsignedDecimalUtil.getUnsignedShort(bf)); - eocd.setcDSize(UnsignedDecimalUtil.getUnsignedInt(bf)); - eocd.setOffset(UnsignedDecimalUtil.getUnsignedInt(bf)); - eocd.setCommentLength(UnsignedDecimalUtil.getUnsignedShort(bf)); - if (eocd.getCommentLength() > 0) { - byte[] readComment = new byte[eocd.getCommentLength()]; - bf.get(readComment); - eocd.setComment(new String(readComment, StandardCharsets.UTF_8)); - } - eocd.setLength(EOCD_LENGTH + eocd.getCommentLength()); - if (bf.remaining() != 0) { - return null; + throw new ZipException("read Data Descriptor failed"); } - return eocd; + data.setCrc32(bf.getInt()); + data.setCompressedSize(UnsignedDecimalUtil.getUnsignedInt(bf)); + data.setUnCompressedSize(UnsignedDecimalUtil.getUnsignedInt(bf)); + return data; } /** - * change End Of Central Directory to bytes + * change DataDescriptor to bytes * * @return bytes */ public byte[] toBytes() { - ByteBuffer bf = ByteBuffer.allocate(length).order(ByteOrder.LITTLE_ENDIAN); + ByteBuffer bf = ByteBuffer.allocate(DES_LENGTH).order(ByteOrder.LITTLE_ENDIAN); bf.putInt(SIGNATURE); - UnsignedDecimalUtil.setUnsignedShort(bf, diskNum); - UnsignedDecimalUtil.setUnsignedShort(bf, cDStartDiskNum); - UnsignedDecimalUtil.setUnsignedShort(bf, thisDiskCDNum); - UnsignedDecimalUtil.setUnsignedShort(bf, cDTotal); - UnsignedDecimalUtil.setUnsignedInt(bf, cDSize); - UnsignedDecimalUtil.setUnsignedInt(bf, offset); - UnsignedDecimalUtil.setUnsignedShort(bf, commentLength); - if (commentLength > 0) { - bf.put(comment.getBytes(StandardCharsets.UTF_8)); - } + bf.putInt(crc32); + UnsignedDecimalUtil.setUnsignedInt(bf, compressedSize); + UnsignedDecimalUtil.setUnsignedInt(bf, unCompressedSize); return bf.array(); } - public static int getEocdLength() { - return EOCD_LENGTH; + public static int getDesLength() { + return DES_LENGTH; } public static int getSIGNATURE() { return SIGNATURE; } - public int getDiskNum() { - return diskNum; - } - - public void setDiskNum(int diskNum) { - this.diskNum = diskNum; - } - - public int getcDStartDiskNum() { - return cDStartDiskNum; - } - - public void setcDStartDiskNum(int cDStartDiskNum) { - this.cDStartDiskNum = cDStartDiskNum; - } - - public int getThisDiskCDNum() { - return thisDiskCDNum; - } - - public void setThisDiskCDNum(int thisDiskCDNum) { - this.thisDiskCDNum = thisDiskCDNum; - } - - public int getcDTotal() { - return cDTotal; - } - - public void setcDTotal(int cDTotal) { - this.cDTotal = cDTotal; - } - - public long getcDSize() { - return cDSize; - } - - public void setcDSize(long cDSize) { - this.cDSize = cDSize; - } - - public long getOffset() { - return offset; - } - - public void setOffset(long offset) { - this.offset = offset; - } - - public int getCommentLength() { - return commentLength; + public int getCrc32() { + return crc32; } - public void setCommentLength(int commentLength) { - this.commentLength = commentLength; + public void setCrc32(int crc32) { + this.crc32 = crc32; } - public String getComment() { - return comment; + public long getCompressedSize() { + return compressedSize; } - public void setComment(String comment) { - this.comment = comment; + public void setCompressedSize(long compressedSize) { + this.compressedSize = compressedSize; } - public int getLength() { - return length; + public long getUnCompressedSize() { + return unCompressedSize; } - public void setLength(int length) { - this.length = length; + public void setUnCompressedSize(long unCompressedSize) { + this.unCompressedSize = unCompressedSize; } -} \ No newline at end of file +} -- Gitee From 76d285b3da8b81b00c3d00bc5b92e3b6fd62e64b Mon Sep 17 00:00:00 2001 From: wangzeyu Date: Sat, 9 Dec 2023 09:37:12 +0000 Subject: [PATCH 37/37] unsigned int overflow Signed-off-by: wangzeyu --- .../hap/entity/zip/EndOfCentralDirectory.java | 93 ++++++++++--------- 1 file changed, 51 insertions(+), 42 deletions(-) diff --git a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/EndOfCentralDirectory.java b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/EndOfCentralDirectory.java index 272935a5..dfc2ba14 100644 --- a/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/EndOfCentralDirectory.java +++ b/hapsigntool/hap_sign_tool_lib/src/main/java/com/ohos/hapsigntool/hap/entity/zip/EndOfCentralDirectory.java @@ -38,37 +38,37 @@ class EndOfCentralDirectory { /** * 2 bytes */ - private short diskNum; + private int diskNum; /** * 2 bytes */ - private short cDStartDiskNum; + private int cDStartDiskNum; /** * 2 bytes */ - private short thisDiskCDNum; + private int thisDiskCDNum; /** * 2 bytes */ - private short cDTotal; + private int cDTotal; /** * 4 bytes */ - private int cDSize; + private long cDSize; /** * 4 bytes */ - private int offset; + private long offset; /** * 2 bytes */ - private short commentLength; + private int commentLength; /** * n bytes @@ -92,13 +92,13 @@ class EndOfCentralDirectory { if (bf.getInt() != SIGNATURE) { return null; } - eocd.setDiskNum(bf.getShort()); - eocd.setCDStartDiskNum(bf.getShort()); - eocd.setThisDiskCDNum(bf.getShort()); - eocd.setCDTotal(bf.getShort()); - eocd.setCDSize(bf.getInt()); - eocd.setOffset(bf.getInt()); - eocd.setCommentLength(bf.getShort()); + eocd.setDiskNum(UnsignedDecimalUtil.getUnsignedShort(bf)); + eocd.setcDStartDiskNum(UnsignedDecimalUtil.getUnsignedShort(bf)); + eocd.setThisDiskCDNum(UnsignedDecimalUtil.getUnsignedShort(bf)); + eocd.setcDTotal(UnsignedDecimalUtil.getUnsignedShort(bf)); + eocd.setcDSize(UnsignedDecimalUtil.getUnsignedInt(bf)); + eocd.setOffset(UnsignedDecimalUtil.getUnsignedInt(bf)); + eocd.setCommentLength(UnsignedDecimalUtil.getUnsignedShort(bf)); if (eocd.getCommentLength() > 0) { byte[] readComment = new byte[eocd.getCommentLength()]; bf.get(readComment); @@ -119,82 +119,83 @@ class EndOfCentralDirectory { public byte[] toBytes() { ByteBuffer bf = ByteBuffer.allocate(length).order(ByteOrder.LITTLE_ENDIAN); bf.putInt(SIGNATURE); - bf.putShort(diskNum); - bf.putShort(cDStartDiskNum); - bf.putShort(thisDiskCDNum); - bf.putShort(cDTotal); - bf.putInt(cDSize); - bf.putInt(offset); - bf.putShort(commentLength); + UnsignedDecimalUtil.setUnsignedShort(bf, diskNum); + UnsignedDecimalUtil.setUnsignedShort(bf, cDStartDiskNum); + UnsignedDecimalUtil.setUnsignedShort(bf, thisDiskCDNum); + UnsignedDecimalUtil.setUnsignedShort(bf, cDTotal); + UnsignedDecimalUtil.setUnsignedInt(bf, cDSize); + UnsignedDecimalUtil.setUnsignedInt(bf, offset); + UnsignedDecimalUtil.setUnsignedShort(bf, commentLength); if (commentLength > 0) { bf.put(comment.getBytes(StandardCharsets.UTF_8)); } return bf.array(); } - public short getDiskNum() { + public static int getEocdLength() { + return EOCD_LENGTH; + } + + public static int getSIGNATURE() { + return SIGNATURE; + } + + public int getDiskNum() { return diskNum; } - public void setDiskNum(short diskNum) { + public void setDiskNum(int diskNum) { this.diskNum = diskNum; } - public short getCDStartDiskNum() { + public int getcDStartDiskNum() { return cDStartDiskNum; } - public void setCDStartDiskNum(short cDStartDiskNum) { + public void setcDStartDiskNum(int cDStartDiskNum) { this.cDStartDiskNum = cDStartDiskNum; } - public short getThisDiskCDNum() { + public int getThisDiskCDNum() { return thisDiskCDNum; } - public void setThisDiskCDNum(short thisDiskCDNum) { + public void setThisDiskCDNum(int thisDiskCDNum) { this.thisDiskCDNum = thisDiskCDNum; } - public short getCDTotal() { + public int getcDTotal() { return cDTotal; } - public void setCDTotal(short cDTotal) { + public void setcDTotal(int cDTotal) { this.cDTotal = cDTotal; } - public int getCDSize() { + public long getcDSize() { return cDSize; } - public void setCDSize(int cDSize) { + public void setcDSize(long cDSize) { this.cDSize = cDSize; } - public int getOffset() { + public long getOffset() { return offset; } - public void setOffset(int offset) { + public void setOffset(long offset) { this.offset = offset; } - public short getCommentLength() { + public int getCommentLength() { return commentLength; } - public void setCommentLength(short commentLength) { + public void setCommentLength(int commentLength) { this.commentLength = commentLength; } - public int getLength() { - return length; - } - - public void setLength(int length) { - this.length = length; - } public String getComment() { return comment; } @@ -202,4 +203,12 @@ class EndOfCentralDirectory { public void setComment(String comment) { this.comment = comment; } + + public int getLength() { + return length; + } + + public void setLength(int length) { + this.length = length; + } } \ No newline at end of file -- Gitee