mirror of
https://github.com/revanced/ARSCLib.git
synced 2025-04-30 06:14:25 +02:00
accessible ZipAligner
This commit is contained in:
parent
c517505cbf
commit
61b3b6aee5
@ -30,20 +30,30 @@ import java.util.List;
|
|||||||
|
|
||||||
public class ApkWriter extends ZipFileOutput {
|
public class ApkWriter extends ZipFileOutput {
|
||||||
private final Collection<? extends InputSource> sourceList;
|
private final Collection<? extends InputSource> sourceList;
|
||||||
|
private ZipAligner zipAligner;
|
||||||
|
|
||||||
public ApkWriter(File file, Collection<? extends InputSource> sourceList) throws IOException {
|
public ApkWriter(File file, Collection<? extends InputSource> sourceList) throws IOException {
|
||||||
super(file);
|
super(file);
|
||||||
this.sourceList = sourceList;
|
this.sourceList = sourceList;
|
||||||
|
this.zipAligner = ZipAligner.apkAligner();
|
||||||
}
|
}
|
||||||
public void write()throws IOException {
|
public void write()throws IOException {
|
||||||
List<OutputSource> outputList = buildOutputEntry();
|
List<OutputSource> outputList = buildOutputEntry();
|
||||||
BufferFileInput buffer = writeBuffer(outputList);
|
BufferFileInput buffer = writeBuffer(outputList);
|
||||||
buffer.unlock();
|
buffer.unlock();
|
||||||
ZipAligner aligner = new ZipAligner();
|
align(outputList);
|
||||||
align(aligner, outputList);
|
|
||||||
writeApk(outputList);
|
writeApk(outputList);
|
||||||
writeCEH(outputList);
|
writeCEH(outputList);
|
||||||
buffer.close();
|
buffer.close();
|
||||||
|
this.close();
|
||||||
}
|
}
|
||||||
|
public ZipAligner getZipAligner() {
|
||||||
|
return zipAligner;
|
||||||
|
}
|
||||||
|
public void setZipAligner(ZipAligner zipAligner) {
|
||||||
|
this.zipAligner = zipAligner;
|
||||||
|
}
|
||||||
|
|
||||||
private void writeCEH(List<OutputSource> outputList) throws IOException{
|
private void writeCEH(List<OutputSource> outputList) throws IOException{
|
||||||
EndRecord endRecord = new EndRecord();
|
EndRecord endRecord = new EndRecord();
|
||||||
endRecord.setSignature(ZipSignature.END_RECORD);
|
endRecord.setSignature(ZipSignature.END_RECORD);
|
||||||
@ -73,7 +83,8 @@ public class ApkWriter extends ZipFileOutput {
|
|||||||
output.close();
|
output.close();
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
private void align(ZipAligner aligner, List<OutputSource> outputList) throws IOException{
|
private void align(List<OutputSource> outputList){
|
||||||
|
ZipAligner aligner = getZipAligner();
|
||||||
for(OutputSource outputSource:outputList){
|
for(OutputSource outputSource:outputList){
|
||||||
outputSource.align(aligner);
|
outputSource.align(aligner);
|
||||||
}
|
}
|
||||||
|
@ -29,18 +29,23 @@ import java.util.zip.Deflater;
|
|||||||
import java.util.zip.DeflaterOutputStream;
|
import java.util.zip.DeflaterOutputStream;
|
||||||
import java.util.zip.ZipEntry;
|
import java.util.zip.ZipEntry;
|
||||||
|
|
||||||
public class OutputSource {
|
class OutputSource {
|
||||||
private final InputSource inputSource;
|
private final InputSource inputSource;
|
||||||
private LocalFileHeader lfh;
|
private LocalFileHeader lfh;
|
||||||
private EntryBuffer entryBuffer;
|
private EntryBuffer entryBuffer;
|
||||||
|
|
||||||
public OutputSource(InputSource inputSource){
|
OutputSource(InputSource inputSource){
|
||||||
this.inputSource = inputSource;
|
this.inputSource = inputSource;
|
||||||
}
|
}
|
||||||
public void align(ZipAligner aligner){
|
void align(ZipAligner aligner){
|
||||||
aligner.align(getInputSource(), getLocalFileHeader());
|
LocalFileHeader lfh = getLocalFileHeader();
|
||||||
|
if(aligner == null){
|
||||||
|
lfh.setExtra(null);
|
||||||
|
}else {
|
||||||
|
aligner.align(getInputSource(), lfh);
|
||||||
}
|
}
|
||||||
public void makeBuffer(BufferFileInput input, BufferFileOutput output) throws IOException {
|
}
|
||||||
|
void makeBuffer(BufferFileInput input, BufferFileOutput output) throws IOException {
|
||||||
EntryBuffer entryBuffer = this.entryBuffer;
|
EntryBuffer entryBuffer = this.entryBuffer;
|
||||||
if(entryBuffer != null){
|
if(entryBuffer != null){
|
||||||
return;
|
return;
|
||||||
@ -62,7 +67,7 @@ public class OutputSource {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void writeApk(ApkWriter apkWriter) throws IOException{
|
void writeApk(ApkWriter apkWriter) throws IOException{
|
||||||
EntryBuffer entryBuffer = this.entryBuffer;
|
EntryBuffer entryBuffer = this.entryBuffer;
|
||||||
FileChannel input = entryBuffer.getZipFileInput().getFileChannel();
|
FileChannel input = entryBuffer.getZipFileInput().getFileChannel();
|
||||||
input.position(entryBuffer.getOffset());
|
input.position(entryBuffer.getOffset());
|
||||||
@ -71,7 +76,7 @@ public class OutputSource {
|
|||||||
writeData(input, entryBuffer.getLength(), apkWriter);
|
writeData(input, entryBuffer.getLength(), apkWriter);
|
||||||
writeDD(lfh.getDataDescriptor(), apkWriter);
|
writeDD(lfh.getDataDescriptor(), apkWriter);
|
||||||
}
|
}
|
||||||
public void writeCEH(ApkWriter apkWriter) throws IOException{
|
void writeCEH(ApkWriter apkWriter) throws IOException{
|
||||||
LocalFileHeader lfh = getLocalFileHeader();
|
LocalFileHeader lfh = getLocalFileHeader();
|
||||||
CentralEntryHeader ceh = CentralEntryHeader.fromLocalFileHeader(lfh);
|
CentralEntryHeader ceh = CentralEntryHeader.fromLocalFileHeader(lfh);
|
||||||
ceh.writeBytes(apkWriter.getOutputStream());
|
ceh.writeBytes(apkWriter.getOutputStream());
|
||||||
@ -127,10 +132,10 @@ public class OutputSource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public InputSource getInputSource() {
|
InputSource getInputSource() {
|
||||||
return inputSource;
|
return inputSource;
|
||||||
}
|
}
|
||||||
public LocalFileHeader getLocalFileHeader(){
|
LocalFileHeader getLocalFileHeader(){
|
||||||
if(lfh == null){
|
if(lfh == null){
|
||||||
lfh = createLocalFileHeader();
|
lfh = createLocalFileHeader();
|
||||||
clearAlignment(lfh);
|
clearAlignment(lfh);
|
||||||
|
@ -19,21 +19,56 @@ import com.reandroid.archive.InputSource;
|
|||||||
import com.reandroid.archive2.block.DataDescriptor;
|
import com.reandroid.archive2.block.DataDescriptor;
|
||||||
import com.reandroid.archive2.block.LocalFileHeader;
|
import com.reandroid.archive2.block.LocalFileHeader;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
import java.util.zip.ZipEntry;
|
import java.util.zip.ZipEntry;
|
||||||
|
|
||||||
public class ZipAligner {
|
public class ZipAligner {
|
||||||
|
private final Map<Pattern, Integer> alignmentMap;
|
||||||
|
private int defaultAlignment;
|
||||||
|
private boolean enableDataDescriptor;
|
||||||
private long mTotalPadding;
|
private long mTotalPadding;
|
||||||
private long mCurrentOffset;
|
private long mCurrentOffset;
|
||||||
private boolean enableDataDescriptor = true;
|
|
||||||
public ZipAligner(){
|
public ZipAligner(){
|
||||||
|
alignmentMap = new HashMap<>();
|
||||||
}
|
}
|
||||||
public void align(InputSource inputSource, LocalFileHeader lfh){
|
|
||||||
|
public void setFileAlignment(Pattern patternFileName, int alignment){
|
||||||
|
if(patternFileName == null){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
alignmentMap.remove(patternFileName);
|
||||||
|
if(alignment >= 0){
|
||||||
|
alignmentMap.put(patternFileName, alignment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void clearFileAlignment(){
|
||||||
|
alignmentMap.clear();
|
||||||
|
}
|
||||||
|
public void setDefaultAlignment(int defaultAlignment) {
|
||||||
|
if(defaultAlignment < 0){
|
||||||
|
defaultAlignment = 0;
|
||||||
|
}
|
||||||
|
this.defaultAlignment = defaultAlignment;
|
||||||
|
}
|
||||||
|
public void reset(){
|
||||||
|
mTotalPadding = 0;
|
||||||
|
mCurrentOffset = 0;
|
||||||
|
}
|
||||||
|
public void setEnableDataDescriptor(boolean enableDataDescriptor) {
|
||||||
|
this.enableDataDescriptor = enableDataDescriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
void align(InputSource inputSource, LocalFileHeader lfh){
|
||||||
int padding;
|
int padding;
|
||||||
if(inputSource.getMethod() != ZipEntry.STORED){
|
if(inputSource.getMethod() != ZipEntry.STORED){
|
||||||
padding = 0;
|
padding = 0;
|
||||||
createDataDescriptor(lfh);
|
createDataDescriptor(lfh);
|
||||||
}else {
|
}else {
|
||||||
int alignment = getAlignment(inputSource);
|
int alignment = getAlignment(inputSource.getAlias());
|
||||||
long newOffset = mCurrentOffset + mTotalPadding;
|
long newOffset = mCurrentOffset + mTotalPadding;
|
||||||
padding = (int) ((alignment - (newOffset % alignment)) % alignment);
|
padding = (int) ((alignment - (newOffset % alignment)) % alignment);
|
||||||
mTotalPadding += padding;
|
mTotalPadding += padding;
|
||||||
@ -54,21 +89,23 @@ public class ZipAligner {
|
|||||||
}
|
}
|
||||||
lfh.setDataDescriptor(dataDescriptor);
|
lfh.setDataDescriptor(dataDescriptor);
|
||||||
}
|
}
|
||||||
public void reset(){
|
private int getAlignment(String name){
|
||||||
mTotalPadding = 0;
|
for(Map.Entry<Pattern, Integer> entry:alignmentMap.entrySet()){
|
||||||
mCurrentOffset = 0;
|
Matcher matcher = entry.getKey().matcher(name);
|
||||||
|
if(matcher.matches()){
|
||||||
|
return entry.getValue();
|
||||||
}
|
}
|
||||||
public void setEnableDataDescriptor(boolean enableDataDescriptor) {
|
}
|
||||||
this.enableDataDescriptor = enableDataDescriptor;
|
return defaultAlignment;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getAlignment(InputSource inputSource){
|
public static ZipAligner apkAligner(){
|
||||||
String name = inputSource.getAlias();
|
ZipAligner zipAligner = new ZipAligner();
|
||||||
if(name.startsWith("lib/") && name.endsWith(".so")){
|
zipAligner.setDefaultAlignment(ALIGNMENT_4);
|
||||||
return ALIGNMENT_PAGE;
|
Pattern patternNativeLib = Pattern.compile("^lib/.+\\.so$");
|
||||||
}else {
|
zipAligner.setFileAlignment(patternNativeLib, ALIGNMENT_PAGE);
|
||||||
return ALIGNMENT_4;
|
zipAligner.setEnableDataDescriptor(true);
|
||||||
}
|
return zipAligner;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final int ALIGNMENT_4 = 4;
|
private static final int ALIGNMENT_4 = 4;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user