/* 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);
        }
    }
  }
}
