/** Add the SHA1 of every file to the manifest, creating it if necessary. */ private Manifest addDigestsToManifest(Map<String, ZioEntry> entries) throws IOException, GeneralSecurityException { Manifest input = null; ZioEntry manifestEntry = entries.get(JarFile.MANIFEST_NAME); if (manifestEntry != null) { input = new Manifest(); input.read(manifestEntry.getInputStream()); } Manifest output = new Manifest(); Attributes main = output.getMainAttributes(); if (input != null) { main.putAll(input.getMainAttributes()); } else { main.putValue("Manifest-Version", "1.0"); main.putValue("Created-By", "1.0 (Android SignApk)"); } // BASE64Encoder base64 = new BASE64Encoder(); MessageDigest md = MessageDigest.getInstance("SHA1"); byte[] buffer = new byte[512]; int num; // We sort the input entries by name, and add them to the // output manifest in sorted order. We expect that the output // map will be deterministic. TreeMap<String, ZioEntry> byName = new TreeMap<String, ZioEntry>(); byName.putAll(entries); boolean debug = getLogger().isDebugEnabled(); if (debug) getLogger().debug("Manifest entries:"); for (ZioEntry entry : byName.values()) { if (canceled) break; String name = entry.getName(); if (debug) getLogger().debug(name); if (!entry.isDirectory() && !name.equals(JarFile.MANIFEST_NAME) && !name.equals(CERT_SF_NAME) && !name.equals(CERT_RSA_NAME) && (stripPattern == null || !stripPattern.matcher(name).matches())) { progressHelper.progress(ProgressEvent.PRORITY_NORMAL, "Generating manifest"); InputStream data = entry.getInputStream(); while ((num = data.read(buffer)) > 0) { md.update(buffer, 0, num); } Attributes attr = null; if (input != null) { java.util.jar.Attributes inAttr = input.getAttributes(name); if (inAttr != null) attr = new Attributes(inAttr); } if (attr == null) attr = new Attributes(); attr.putValue("SHA1-Digest", Base64.encode(md.digest())); output.getEntries().put(name, attr); } } return output; }
/** @tests java.util.jar.Attributes#putAll(java.util.Map) */ public void test_putAllLjava_util_Map() { Attributes b = new Attributes(); b.putValue("3", "san"); b.putValue("4", "shi"); b.putValue("5", "go"); b.putValue("6", "roku"); a.putAll(b); assertEquals("Should not have been replaced", "one", a.getValue("1")); assertEquals("Should have been replaced", "san", a.getValue("3")); assertEquals("Should have been added", "go", a.getValue("5")); Attributes atts = new Attributes(); assertNull("Assert 0: ", atts.put(Attributes.Name.CLASS_PATH, "tools.jar")); assertNull("Assert 1: ", atts.put(Attributes.Name.MANIFEST_VERSION, "1")); Attributes atts2 = new Attributes(); atts2.putAll(atts); assertEquals("Assert 2:", "tools.jar", atts2.get(Attributes.Name.CLASS_PATH)); assertEquals("Assert 3: ", "1", atts2.get(Attributes.Name.MANIFEST_VERSION)); try { atts.putAll(Collections.EMPTY_MAP); fail("Assert 4: no class cast from attrib parameter"); } catch (ClassCastException e) { // Expected } }
private static Manifest addDigestsToManifest(JarFile jar) throws IOException, GeneralSecurityException { Manifest input = jar.getManifest(); Manifest output = new Manifest(); Attributes main = output.getMainAttributes(); if (input != null) { main.putAll(input.getMainAttributes()); } else { main.putValue("Manifest-Version", "1.0"); main.putValue("Created-By", "1.0 (KApkSigner)"); } BASE64Encoder base64 = new BASE64Encoder(); MessageDigest md = MessageDigest.getInstance("SHA1"); byte[] buffer = new byte[4096]; int num; TreeMap<String, JarEntry> byName = new TreeMap<String, JarEntry>(); for (Enumeration<JarEntry> e = jar.entries(); e.hasMoreElements(); ) { JarEntry entry = e.nextElement(); byName.put(entry.getName(), entry); } for (JarEntry entry : byName.values()) { String name = entry.getName(); if (!entry.isDirectory() && !name.equals(JarFile.MANIFEST_NAME) && !name.equals(Signer.CERT_SF_NAME) && !name.equals(Signer.CERT_RSA_NAME) && (Signer.stripPattern == null || !Signer.stripPattern.matcher(name).matches())) { InputStream data = jar.getInputStream(entry); while ((num = data.read(buffer)) > 0) { md.update(buffer, 0, num); } Attributes attr = null; if (input != null) { attr = input.getAttributes(name); } attr = attr != null ? new Attributes(attr) : new Attributes(); attr.putValue("SHA1-Digest", base64.encode(md.digest())); output.getEntries().put(name, attr); } } return output; }
public Manifest getManifest() throws IOException { if (!isSuperMan()) { return null; } Manifest man = new Manifest(); Attributes attr = man.getMainAttributes(); attr.putAll((Map) superAttr.clone()); // now deep copy the manifest entries if (superEntries != null) { Map entries = man.getEntries(); Iterator it = superEntries.keySet().iterator(); while (it.hasNext()) { Object key = it.next(); Attributes at = (Attributes) superEntries.get(key); entries.put(key, at.clone()); } } return man; }
/** * Constructs a new Manifest that is a copy of the specified Manifest. * * @param man the Manifest to copy */ public Manifest(Manifest man) { attr.putAll(man.getMainAttributes()); entries.putAll(man.getEntries()); }