Throw correct ZipException from ZipFile's method.
[backport.git] / src / com / saurik / backport / Hook.java
1 /* Backport - Bring New Fixes to old Androids
2 * Copyright (C) 2013 Jay Freeman (saurik)
3 */
4
5 /* GNU Lesser General Public License, Version 3 {{{ */
6 /*
7 * Substrate is free software: you can redistribute it and/or modify it under
8 * the terms of the GNU Lesser General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * Substrate is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 * License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with Substrate. If not, see <http://www.gnu.org/licenses/>.
19 **/
20 /* }}} */
21
22 package com.saurik.backport;
23
24 import java.lang.reflect.Field;
25 import java.lang.reflect.Method;
26
27 import java.util.LinkedHashMap;
28
29 import java.util.jar.JarFile;
30
31 import java.util.zip.ZipEntry;
32 import java.util.zip.ZipException;
33 import java.util.zip.ZipFile;
34
35 import android.util.Log;
36
37 import com.saurik.substrate.MS;
38
39 public class Hook {
40 private static class WrongException
41 extends RuntimeException
42 {
43 public WrongException(Throwable cause) {
44 super(cause);
45 }
46 }
47
48 public static void initialize() {
49 MS.hookClassLoad("java.util.zip.ZipFile", new MS.ClassLoadHook() {
50 public void classLoaded(Class<?> ZipFile$) {
51 Field entries = null; {
52 if (entries == null) try {
53 entries = ZipFile$.getDeclaredField("entries");
54 } catch (NoSuchFieldException e) {}
55
56 if (entries == null) try {
57 entries = ZipFile$.getDeclaredField("mEntries");
58 } catch (NoSuchFieldException e) {}
59 }
60
61 if (entries == null)
62 return;
63 final Field ZipFile$entries = entries;
64 ZipFile$entries.setAccessible(true);
65
66 final Method ZipFile$readCentralDir; try {
67 ZipFile$readCentralDir = ZipFile$.getDeclaredMethod("readCentralDir");
68 } catch (NoSuchMethodException e) {
69 Log.e("Backport", "ZipFile$readCentralDir", e);
70 return;
71 }
72
73 MS.hookMethod(ZipFile$, ZipFile$readCentralDir,
74 new MS.MethodAlteration<ZipFile, Void>() {
75 public Void invoked(ZipFile thiz, Object... args)
76 throws Throwable
77 {
78 ZipFile$entries.set(thiz, new LinkedHashMap<String, ZipEntry>() {
79 public ZipEntry put(String key, ZipEntry value) {
80 if (super.put(key, value) != null)
81 throw new WrongException(new ZipException("Duplicate entry name: " + key));
82 return null;
83 }
84 });
85
86 try {
87 return invoke(thiz, args);
88 } catch (WrongException wrong) {
89 throw wrong.getCause();
90 }
91 }
92 }
93 );
94 }
95 });
96 }
97 }