diff options
Diffstat (limited to 'libjava/classpath/java/util/jar/JarFile.java')
-rw-r--r-- | libjava/classpath/java/util/jar/JarFile.java | 981 |
1 files changed, 0 insertions, 981 deletions
diff --git a/libjava/classpath/java/util/jar/JarFile.java b/libjava/classpath/java/util/jar/JarFile.java deleted file mode 100644 index b67c953..0000000 --- a/libjava/classpath/java/util/jar/JarFile.java +++ /dev/null @@ -1,981 +0,0 @@ -/* JarFile.java - Representation of a jar file - Copyright (C) 2000, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - - -package java.util.jar; - -import gnu.java.io.Base64InputStream; -import gnu.java.security.OID; -import gnu.java.security.pkcs.PKCS7SignedData; -import gnu.java.security.pkcs.SignerInfo; -import gnu.java.security.provider.Gnu; - -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FilterInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.security.InvalidKeyException; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.security.Signature; -import java.security.SignatureException; -import java.security.cert.CRLException; -import java.security.cert.Certificate; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; -import java.util.Arrays; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.zip.ZipEntry; -import java.util.zip.ZipException; -import java.util.zip.ZipFile; - -/** - * Representation of a jar file. - * <p> - * Note that this class is not a subclass of java.io.File but a subclass of - * java.util.zip.ZipFile and you can only read JarFiles with it (although - * there are constructors that take a File object). - * - * @since 1.2 - * @author Mark Wielaard (mark@klomp.org) - * @author Casey Marshall (csm@gnu.org) wrote the certificate and entry - * verification code. - */ -public class JarFile extends ZipFile -{ - // Fields - - /** The name of the manifest entry: META-INF/MANIFEST.MF */ - public static final String MANIFEST_NAME = "META-INF/MANIFEST.MF"; - - /** The META-INF directory entry. */ - private static final String META_INF = "META-INF/"; - - /** The suffix for PKCS7 DSA signature entries. */ - private static final String PKCS7_DSA_SUFFIX = ".DSA"; - - /** The suffix for PKCS7 RSA signature entries. */ - private static final String PKCS7_RSA_SUFFIX = ".RSA"; - - /** The suffix for digest attributes. */ - private static final String DIGEST_KEY_SUFFIX = "-Digest"; - - /** The suffix for signature files. */ - private static final String SF_SUFFIX = ".SF"; - - /** - * The security provider to use for signature verification. - * We need a known fallback to be able to read any signed jar file - * (which might contain the user selected security provider). - * This is package-private to avoid accessor methods for inner classes. - */ - static final Gnu provider = new Gnu(); - - // Signature OIDs. - private static final OID MD2_OID = new OID("1.2.840.113549.2.2"); - private static final OID MD4_OID = new OID("1.2.840.113549.2.4"); - private static final OID MD5_OID = new OID("1.2.840.113549.2.5"); - private static final OID SHA1_OID = new OID("1.3.14.3.2.26"); - private static final OID DSA_ENCRYPTION_OID = new OID("1.2.840.10040.4.1"); - private static final OID RSA_ENCRYPTION_OID = new OID("1.2.840.113549.1.1.1"); - - /** - * The manifest of this file, if any, otherwise null. - * Read when first needed. - */ - private Manifest manifest; - - /** Whether to verify the manifest and all entries. */ - boolean verify; - - /** Whether the has already been loaded. */ - private boolean manifestRead = false; - - /** Whether the signature files have been loaded. */ - boolean signaturesRead = false; - - /** - * A map between entry names and booleans, signaling whether or - * not that entry has been verified. - * Only be accessed with lock on this JarFile*/ - HashMap verified = new HashMap(); - - /** - * A mapping from entry name to certificates, if any. - * Only accessed with lock on this JarFile. - */ - HashMap entryCerts; - - /** - * A {@link Map} of message digest algorithm names to their implementation. - * Used to reduce object (algorithm implementation) instantiation. - */ - private HashMap digestAlgorithms = new HashMap(); - - static boolean DEBUG = false; - static void debug(Object msg) - { - System.err.print(JarFile.class.getName()); - System.err.print(" >>> "); - System.err.println(msg); - } - - // Constructors - - /** - * Creates a new JarFile. All jar entries are verified (when a Manifest file - * for this JarFile exists). You need to actually open and read the complete - * jar entry (with <code>getInputStream()</code>) to check its signature. - * - * @param fileName the name of the file to open - * @exception FileNotFoundException if the fileName cannot be found - * @exception IOException if another IO exception occurs while reading - */ - public JarFile(String fileName) throws FileNotFoundException, IOException - { - this(fileName, true); - } - - /** - * Creates a new JarFile. If verify is true then all jar entries are - * verified (when a Manifest file for this JarFile exists). You need to - * actually open and read the complete jar entry - * (with <code>getInputStream()</code>) to check its signature. - * - * @param fileName the name of the file to open - * @param verify checks manifest and entries when true and a manifest - * exists, when false no checks are made - * @exception FileNotFoundException if the fileName cannot be found - * @exception IOException if another IO exception occurs while reading - */ - public JarFile(String fileName, boolean verify) throws - FileNotFoundException, IOException - { - super(fileName); - if (verify) - { - manifest = readManifest(); - verify(); - } - } - - /** - * Creates a new JarFile. All jar entries are verified (when a Manifest file - * for this JarFile exists). You need to actually open and read the complete - * jar entry (with <code>getInputStream()</code>) to check its signature. - * - * @param file the file to open as a jar file - * @exception FileNotFoundException if the file does not exits - * @exception IOException if another IO exception occurs while reading - */ - public JarFile(File file) throws FileNotFoundException, IOException - { - this(file, true); - } - - /** - * Creates a new JarFile. If verify is true then all jar entries are - * verified (when a Manifest file for this JarFile exists). You need to - * actually open and read the complete jar entry - * (with <code>getInputStream()</code>) to check its signature. - * - * @param file the file to open to open as a jar file - * @param verify checks manifest and entries when true and a manifest - * exists, when false no checks are made - * @exception FileNotFoundException if file does not exist - * @exception IOException if another IO exception occurs while reading - */ - public JarFile(File file, boolean verify) throws FileNotFoundException, - IOException - { - super(file); - if (verify) - { - manifest = readManifest(); - verify(); - } - } - - /** - * Creates a new JarFile with the indicated mode. If verify is true then - * all jar entries are verified (when a Manifest file for this JarFile - * exists). You need to actually open and read the complete jar entry - * (with <code>getInputStream()</code>) to check its signature. - * manifest and if the manifest exists and verify is true verfies it. - * - * @param file the file to open to open as a jar file - * @param verify checks manifest and entries when true and a manifest - * exists, when false no checks are made - * @param mode either ZipFile.OPEN_READ or - * (ZipFile.OPEN_READ | ZipFile.OPEN_DELETE) - * @exception FileNotFoundException if the file does not exist - * @exception IOException if another IO exception occurs while reading - * @exception IllegalArgumentException when given an illegal mode - * - * @since 1.3 - */ - public JarFile(File file, boolean verify, int mode) throws - FileNotFoundException, IOException, IllegalArgumentException - { - super(file, mode); - if (verify) - { - manifest = readManifest(); - verify(); - } - } - - // Methods - - /** - * XXX - should verify the manifest file - */ - private void verify() - { - // only check if manifest is not null - if (manifest == null) - { - verify = false; - return; - } - - verify = true; - // XXX - verify manifest - } - - /** - * Parses and returns the manifest if it exists, otherwise returns null. - */ - private Manifest readManifest() - { - try - { - ZipEntry manEntry = super.getEntry(MANIFEST_NAME); - if (manEntry != null) - { - InputStream in = super.getInputStream(manEntry); - manifestRead = true; - return new Manifest(in); - } - else - { - manifestRead = true; - return null; - } - } - catch (IOException ioe) - { - manifestRead = true; - return null; - } - } - - /** - * Returns a enumeration of all the entries in the JarFile. - * Note that also the Jar META-INF entries are returned. - * - * @exception IllegalStateException when the JarFile is already closed - */ - public Enumeration<JarEntry> entries() throws IllegalStateException - { - return new JarEnumeration(super.entries(), this); - } - - /** - * Wraps a given Zip Entries Enumeration. For every zip entry a - * JarEntry is created and the corresponding Attributes are looked up. - */ - private static class JarEnumeration implements Enumeration<JarEntry> - { - - private final Enumeration<? extends ZipEntry> entries; - private final JarFile jarfile; - - JarEnumeration(Enumeration<? extends ZipEntry> e, JarFile f) - { - entries = e; - jarfile = f; - } - - public boolean hasMoreElements() - { - return entries.hasMoreElements(); - } - - public JarEntry nextElement() - { - ZipEntry zip = (ZipEntry) entries.nextElement(); - JarEntry jar = new JarEntry(zip); - Manifest manifest; - try - { - manifest = jarfile.getManifest(); - } - catch (IOException ioe) - { - manifest = null; - } - - if (manifest != null) - { - jar.attr = manifest.getAttributes(jar.getName()); - } - - synchronized(jarfile) - { - if (jarfile.verify && !jarfile.signaturesRead) - try - { - jarfile.readSignatures(); - } - catch (IOException ioe) - { - if (JarFile.DEBUG) - { - JarFile.debug(ioe); - ioe.printStackTrace(); - } - jarfile.signaturesRead = true; // fudge it. - } - } - jar.jarfile = jarfile; - return jar; - } - } - - /** - * XXX - * It actually returns a JarEntry not a zipEntry - * @param name XXX - */ - public synchronized ZipEntry getEntry(String name) - { - ZipEntry entry = super.getEntry(name); - if (entry != null) - { - JarEntry jarEntry = new JarEntry(entry); - Manifest manifest; - try - { - manifest = getManifest(); - } - catch (IOException ioe) - { - manifest = null; - } - - if (manifest != null) - { - jarEntry.attr = manifest.getAttributes(name); - } - - if (verify && !signaturesRead) - try - { - readSignatures(); - } - catch (IOException ioe) - { - if (DEBUG) - { - debug(ioe); - ioe.printStackTrace(); - } - signaturesRead = true; - } - jarEntry.jarfile = this; - return jarEntry; - } - return null; - } - - /** - * Returns an input stream for the given entry. If configured to - * verify entries, the input stream returned will verify them while - * the stream is read, but only on the first time. - * - * @param entry The entry to get the input stream for. - * @exception ZipException XXX - * @exception IOException XXX - */ - public synchronized InputStream getInputStream(ZipEntry entry) throws - ZipException, IOException - { - // If we haven't verified the hash, do it now. - if (!verified.containsKey(entry.getName()) && verify) - { - if (DEBUG) - debug("reading and verifying " + entry); - return new EntryInputStream(entry, super.getInputStream(entry), this); - } - else - { - if (DEBUG) - debug("reading already verified entry " + entry); - if (verify && verified.get(entry.getName()) == Boolean.FALSE) - throw new ZipException("digest for " + entry + " is invalid"); - return super.getInputStream(entry); - } - } - - /** - * Returns the JarEntry that belongs to the name if such an entry - * exists in the JarFile. Returns null otherwise - * Convenience method that just casts the result from <code>getEntry</code> - * to a JarEntry. - * - * @param name the jar entry name to look up - * @return the JarEntry if it exists, null otherwise - */ - public JarEntry getJarEntry(String name) - { - return (JarEntry) getEntry(name); - } - - /** - * Returns the manifest for this JarFile or null when the JarFile does not - * contain a manifest file. - */ - public synchronized Manifest getManifest() throws IOException - { - if (!manifestRead) - manifest = readManifest(); - - return manifest; - } - - // Only called with lock on this JarFile. - // Package private for use in inner classes. - void readSignatures() throws IOException - { - Map pkcs7Dsa = new HashMap(); - Map pkcs7Rsa = new HashMap(); - Map sigFiles = new HashMap(); - - // Phase 1: Read all signature files. These contain the user - // certificates as well as the signatures themselves. - for (Enumeration e = super.entries(); e.hasMoreElements(); ) - { - ZipEntry ze = (ZipEntry) e.nextElement(); - String name = ze.getName(); - if (name.startsWith(META_INF)) - { - String alias = name.substring(META_INF.length()); - if (alias.lastIndexOf('.') >= 0) - alias = alias.substring(0, alias.lastIndexOf('.')); - - if (name.endsWith(PKCS7_DSA_SUFFIX) || name.endsWith(PKCS7_RSA_SUFFIX)) - { - if (DEBUG) - debug("reading PKCS7 info from " + name + ", alias=" + alias); - PKCS7SignedData sig = null; - try - { - sig = new PKCS7SignedData(super.getInputStream(ze)); - } - catch (CertificateException ce) - { - IOException ioe = new IOException("certificate parsing error"); - ioe.initCause(ce); - throw ioe; - } - catch (CRLException crle) - { - IOException ioe = new IOException("CRL parsing error"); - ioe.initCause(crle); - throw ioe; - } - if (name.endsWith(PKCS7_DSA_SUFFIX)) - pkcs7Dsa.put(alias, sig); - else if (name.endsWith(PKCS7_RSA_SUFFIX)) - pkcs7Rsa.put(alias, sig); - } - else if (name.endsWith(SF_SUFFIX)) - { - if (DEBUG) - debug("reading signature file for " + alias + ": " + name); - Manifest sf = new Manifest(super.getInputStream(ze)); - sigFiles.put(alias, sf); - if (DEBUG) - debug("result: " + sf); - } - } - } - - // Phase 2: verify the signatures on any signature files. - Set validCerts = new HashSet(); - Map entryCerts = new HashMap(); - for (Iterator it = sigFiles.entrySet().iterator(); it.hasNext(); ) - { - int valid = 0; - Map.Entry e = (Map.Entry) it.next(); - String alias = (String) e.getKey(); - - PKCS7SignedData sig = (PKCS7SignedData) pkcs7Dsa.get(alias); - if (sig != null) - { - Certificate[] certs = sig.getCertificates(); - Set signerInfos = sig.getSignerInfos(); - for (Iterator it2 = signerInfos.iterator(); it2.hasNext(); ) - verify(certs, (SignerInfo) it2.next(), alias, validCerts); - } - - sig = (PKCS7SignedData) pkcs7Rsa.get(alias); - if (sig != null) - { - Certificate[] certs = sig.getCertificates(); - Set signerInfos = sig.getSignerInfos(); - for (Iterator it2 = signerInfos.iterator(); it2.hasNext(); ) - verify(certs, (SignerInfo) it2.next(), alias, validCerts); - } - - // It isn't a signature for anything. Punt it. - if (validCerts.isEmpty()) - { - it.remove(); - continue; - } - - entryCerts.put(e.getValue(), new HashSet(validCerts)); - validCerts.clear(); - } - - // Read the manifest into a HashMap (String fileName, String entry) - // The fileName might be split into multiple lines in the manifest. - // Such additional lines will start with a space. - InputStream in = super.getInputStream(super.getEntry(MANIFEST_NAME)); - ByteArrayOutputStream baStream = new ByteArrayOutputStream(); - byte[] ba = new byte[1024]; - while (true) - { - int len = in.read(ba); - if (len < 0) - break; - baStream.write(ba, 0, len); - } - in.close(); - - HashMap hmManifestEntries = new HashMap(); - Pattern p = Pattern.compile("Name: (.+?\r?\n(?: .+?\r?\n)*)" - + ".+?-Digest: .+?\r?\n\r?\n"); - Matcher m = p.matcher(baStream.toString()); - while (m.find()) - { - String fileName = m.group(1).replaceAll("\r?\n ?", ""); - hmManifestEntries.put(fileName, m.group()); - } - - // Phase 3: verify the signature file signatures against the manifest, - // mapping the entry name to the target certificates. - this.entryCerts = new HashMap(); - for (Iterator it = entryCerts.entrySet().iterator(); it.hasNext(); ) - { - Map.Entry e = (Map.Entry) it.next(); - Manifest sigfile = (Manifest) e.getKey(); - Map entries = sigfile.getEntries(); - Set certificates = (Set) e.getValue(); - - for (Iterator it2 = entries.entrySet().iterator(); it2.hasNext(); ) - { - Map.Entry e2 = (Map.Entry) it2.next(); - String entryname = String.valueOf(e2.getKey()); - Attributes attr = (Attributes) e2.getValue(); - if (verifyHashes(entryname, attr, hmManifestEntries)) - { - if (DEBUG) - debug("entry " + entryname + " has certificates " + certificates); - Set s = (Set) this.entryCerts.get(entryname); - if (s != null) - s.addAll(certificates); - else - this.entryCerts.put(entryname, new HashSet(certificates)); - } - } - } - - signaturesRead = true; - } - - /** - * Tell if the given signer info is over the given alias's signature file, - * given one of the certificates specified. - */ - private void verify(Certificate[] certs, SignerInfo signerInfo, - String alias, Set validCerts) - { - Signature sig = null; - try - { - OID alg = signerInfo.getDigestEncryptionAlgorithmId(); - if (alg.equals(DSA_ENCRYPTION_OID)) - { - if (!signerInfo.getDigestAlgorithmId().equals(SHA1_OID)) - return; - sig = Signature.getInstance("SHA1withDSA", provider); - } - else if (alg.equals(RSA_ENCRYPTION_OID)) - { - OID hash = signerInfo.getDigestAlgorithmId(); - if (hash.equals(MD2_OID)) - sig = Signature.getInstance("md2WithRsaEncryption", provider); - else if (hash.equals(MD4_OID)) - sig = Signature.getInstance("md4WithRsaEncryption", provider); - else if (hash.equals(MD5_OID)) - sig = Signature.getInstance("md5WithRsaEncryption", provider); - else if (hash.equals(SHA1_OID)) - sig = Signature.getInstance("sha1WithRsaEncryption", provider); - else - return; - } - else - { - if (DEBUG) - debug("unsupported signature algorithm: " + alg); - return; - } - } - catch (NoSuchAlgorithmException nsae) - { - if (DEBUG) - { - debug(nsae); - nsae.printStackTrace(); - } - return; - } - ZipEntry sigFileEntry = super.getEntry(META_INF + alias + SF_SUFFIX); - if (sigFileEntry == null) - return; - for (int i = 0; i < certs.length; i++) - { - if (!(certs[i] instanceof X509Certificate)) - continue; - X509Certificate cert = (X509Certificate) certs[i]; - if (!cert.getIssuerX500Principal().equals(signerInfo.getIssuer()) || - !cert.getSerialNumber().equals(signerInfo.getSerialNumber())) - continue; - try - { - sig.initVerify(cert.getPublicKey()); - InputStream in = super.getInputStream(sigFileEntry); - if (in == null) - continue; - byte[] buf = new byte[1024]; - int len = 0; - while ((len = in.read(buf)) != -1) - sig.update(buf, 0, len); - if (sig.verify(signerInfo.getEncryptedDigest())) - { - if (DEBUG) - debug("signature for " + cert.getSubjectDN() + " is good"); - validCerts.add(cert); - } - } - catch (IOException ioe) - { - continue; - } - catch (InvalidKeyException ike) - { - continue; - } - catch (SignatureException se) - { - continue; - } - } - } - - /** - * Verifies that the digest(s) in a signature file were, in fact, made over - * the manifest entry for ENTRY. - * - * @param entry The entry name. - * @param attr The attributes from the signature file to verify. - * @param hmManifestEntries Mappings of Jar file entry names to their manifest - * entry text; i.e. the base-64 encoding of their - */ - private boolean verifyHashes(String entry, Attributes attr, - HashMap hmManifestEntries) - { - int verified = 0; - - String stringEntry = (String) hmManifestEntries.get(entry); - if (stringEntry == null) - { - if (DEBUG) - debug("could not find " + entry + " in manifest"); - return false; - } - // The bytes for ENTRY's manifest entry, which are signed in the - // signature file. - byte[] entryBytes = stringEntry.getBytes(); - - for (Iterator it = attr.entrySet().iterator(); it.hasNext(); ) - { - Map.Entry e = (Map.Entry) it.next(); - String key = String.valueOf(e.getKey()); - if (!key.endsWith(DIGEST_KEY_SUFFIX)) - continue; - String alg = key.substring(0, key.length() - DIGEST_KEY_SUFFIX.length()); - try - { - byte[] hash = Base64InputStream.decode((String) e.getValue()); - MessageDigest md = (MessageDigest) digestAlgorithms.get(alg); - if (md == null) - { - md = MessageDigest.getInstance(alg, provider); - digestAlgorithms.put(alg, md); - } - md.reset(); - byte[] hash2 = md.digest(entryBytes); - if (DEBUG) - debug("verifying SF entry " + entry + " alg: " + md.getAlgorithm() - + " expect=" + new java.math.BigInteger(hash).toString(16) - + " comp=" + new java.math.BigInteger(hash2).toString(16)); - if (!Arrays.equals(hash, hash2)) - return false; - verified++; - } - catch (IOException ioe) - { - if (DEBUG) - { - debug(ioe); - ioe.printStackTrace(); - } - return false; - } - catch (NoSuchAlgorithmException nsae) - { - if (DEBUG) - { - debug(nsae); - nsae.printStackTrace(); - } - return false; - } - } - - // We have to find at least one valid digest. - return verified > 0; - } - - /** - * A utility class that verifies jar entries as they are read. - */ - private static class EntryInputStream extends FilterInputStream - { - private final JarFile jarfile; - private final long length; - private long pos; - private final ZipEntry entry; - private final byte[][] hashes; - private final MessageDigest[] md; - private boolean checked; - - EntryInputStream(final ZipEntry entry, - final InputStream in, - final JarFile jar) - throws IOException - { - super(in); - this.entry = entry; - this.jarfile = jar; - - length = entry.getSize(); - pos = 0; - checked = false; - - Attributes attr; - Manifest manifest = jarfile.getManifest(); - if (manifest != null) - attr = manifest.getAttributes(entry.getName()); - else - attr = null; - if (DEBUG) - debug("verifying entry " + entry + " attr=" + attr); - if (attr == null) - { - hashes = new byte[0][]; - md = new MessageDigest[0]; - } - else - { - List hashes = new LinkedList(); - List md = new LinkedList(); - for (Iterator it = attr.entrySet().iterator(); it.hasNext(); ) - { - Map.Entry e = (Map.Entry) it.next(); - String key = String.valueOf(e.getKey()); - if (key == null) - continue; - if (!key.endsWith(DIGEST_KEY_SUFFIX)) - continue; - hashes.add(Base64InputStream.decode((String) e.getValue())); - try - { - int length = key.length() - DIGEST_KEY_SUFFIX.length(); - String alg = key.substring(0, length); - md.add(MessageDigest.getInstance(alg, provider)); - } - catch (NoSuchAlgorithmException nsae) - { - IOException ioe = new IOException("no such message digest: " + key); - ioe.initCause(nsae); - throw ioe; - } - } - if (DEBUG) - debug("digests=" + md); - this.hashes = (byte[][]) hashes.toArray(new byte[hashes.size()][]); - this.md = (MessageDigest[]) md.toArray(new MessageDigest[md.size()]); - } - } - - public boolean markSupported() - { - return false; - } - - public void mark(int readLimit) - { - } - - public void reset() - { - } - - public int read() throws IOException - { - int b = super.read(); - if (b == -1) - { - eof(); - return -1; - } - for (int i = 0; i < md.length; i++) - md[i].update((byte) b); - pos++; - if (length > 0 && pos >= length) - eof(); - return b; - } - - public int read(byte[] buf, int off, int len) throws IOException - { - int count = super.read(buf, off, (int) Math.min(len, (length != 0 - ? length - pos - : Integer.MAX_VALUE))); - if (count == -1 || (length > 0 && pos >= length)) - { - eof(); - return -1; - } - for (int i = 0; i < md.length; i++) - md[i].update(buf, off, count); - pos += count; - if (length != 0 && pos >= length) - eof(); - return count; - } - - public int read(byte[] buf) throws IOException - { - return read(buf, 0, buf.length); - } - - public long skip(long bytes) throws IOException - { - byte[] b = new byte[1024]; - long amount = 0; - while (amount < bytes) - { - int l = read(b, 0, (int) Math.min(b.length, bytes - amount)); - if (l == -1) - break; - amount += l; - } - return amount; - } - - private void eof() throws IOException - { - if (checked) - return; - checked = true; - for (int i = 0; i < md.length; i++) - { - byte[] hash = md[i].digest(); - if (DEBUG) - debug("verifying " + md[i].getAlgorithm() + " expect=" - + new java.math.BigInteger(hashes[i]).toString(16) - + " comp=" + new java.math.BigInteger(hash).toString(16)); - if (!Arrays.equals(hash, hashes[i])) - { - synchronized(jarfile) - { - if (DEBUG) - debug(entry + " could NOT be verified"); - jarfile.verified.put(entry.getName(), Boolean.FALSE); - } - return; - // XXX ??? what do we do here? - // throw new ZipException("message digest mismatch"); - } - } - - synchronized(jarfile) - { - if (DEBUG) - debug(entry + " has been VERIFIED"); - jarfile.verified.put(entry.getName(), Boolean.TRUE); - } - } - } -} |