/* * dex2jar - Tools to work with android .dex and java .class files * Copyright (c) 2009-2013 Panxiaobo * * 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.googlecode.dex2jar.reader; import java.io.InputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; /** * A hack to the ZipInputStream, clean the encrypted-bit flag before checking. * * from the code we know the {@link #createZipEntry(String)} is always invoked before the check in openjdk7, and in * openjdk6 flag is read from tmpbuf after {@link #createZipEntry(String)} , so this class will change * {@link ZipInputStream#flag} and {@link ZipInputStream#tmpbuf} in {@link #createZipEntry(String)} using reflection API * * <pre> * // here are the code from openjdk-7 * // Force to use UTF-8 if the EFS bit is ON, even the cs is NOT UTF-8 * ZipEntry e = createZipEntry(((flag & EFS) != 0) ? zc.toStringUTF8(b, len) : zc.toString(b, len)); * // now get the remaining fields for the entry * if ((flag & 1) == 1) { * throw new ZipException("encrypted ZIP entry not supported"); * } * e.method = get16(tmpbuf, LOCHOW); * e.time = get32(tmpbuf, LOCTIM); * </pre> * * <pre> * // here are the code from openjdk-6 * ZipEntry e = createZipEntry(getUTF8String(b, 0, len)); * // now get the remaining fields for the entry * flag = get16(tmpbuf, LOCFLG); * if ((flag & 1) == 1) { * throw new ZipException("encrypted ZIP entry not supported"); * } * e.method = get16(tmpbuf, LOCHOW); * e.time = get32(tmpbuf, LOCTIM); * </pre> * * @author Panxiaobo * */ public class ZipInputStreamHack extends ZipInputStream { static java.lang.reflect.Field flagField; static java.lang.reflect.Field tmpbufField; static { try { flagField = ZipInputStream.class.getDeclaredField("flag"); flagField.setAccessible(true); } catch (Exception ignored) { } try { tmpbufField = ZipInputStream.class.getDeclaredField("tmpbuf"); tmpbufField.setAccessible(true); } catch (Exception ignored) { } } public ZipInputStreamHack(InputStream in) { super(in); } @Override protected ZipEntry createZipEntry(String name) { if (flagField != null) { // for openjdk7 try { int flag = (Integer) flagField.get(this); flagField.set(this, (flag >> 1) << 1); } catch (Exception e) { } } if (tmpbufField != null) {// for openjdk6 try { byte[] buffer = (byte[]) tmpbufField.get(this); int flagLow8 = buffer[6];// 6 is for LOCFLG flagLow8 = (flagLow8 >> 1) << 1; buffer[6] = (byte) flagLow8; } catch (Exception e) { } } return super.createZipEntry(name); } }