Index: src/test/java/org/apache/commons/compress/archivers/zip/Maven221MultiVolumeTest.java
===================================================================
--- src/test/java/org/apache/commons/compress/archivers/zip/Maven221MultiVolumeTest.java	(revision 832477)
+++ src/test/java/org/apache/commons/compress/archivers/zip/Maven221MultiVolumeTest.java	(working copy)
@@ -46,78 +46,80 @@
 public class Maven221MultiVolumeTest extends TestCase {
 
     private static final String [] ENTRIES = new String [] {
-	"apache-maven-2.2.1/",
-	"apache-maven-2.2.1/LICENSE.txt",
-	"apache-maven-2.2.1/NOTICE.txt",
-	"apache-maven-2.2.1/README.txt",
-	"apache-maven-2.2.1/bin/",
-	"apache-maven-2.2.1/bin/m2.conf",
-	"apache-maven-2.2.1/bin/mvn",
-	"apache-maven-2.2.1/bin/mvn.bat",
-	"apache-maven-2.2.1/bin/mvnDebug",
-	"apache-maven-2.2.1/bin/mvnDebug.bat",
-	"apache-maven-2.2.1/boot/",
-	"apache-maven-2.2.1/boot/classworlds-1.1.jar",
-	"apache-maven-2.2.1/conf/",
-	"apache-maven-2.2.1/conf/settings.xml",
-	"apache-maven-2.2.1/lib/"
+        "apache-maven-2.2.1/",
+        "apache-maven-2.2.1/LICENSE.txt",
+        "apache-maven-2.2.1/NOTICE.txt",
+        "apache-maven-2.2.1/README.txt",
+        "apache-maven-2.2.1/bin/",
+        "apache-maven-2.2.1/bin/m2.conf",
+        "apache-maven-2.2.1/bin/mvn",
+        "apache-maven-2.2.1/bin/mvn.bat",
+        "apache-maven-2.2.1/bin/mvnDebug",
+        "apache-maven-2.2.1/bin/mvnDebug.bat",
+        "apache-maven-2.2.1/boot/",
+        "apache-maven-2.2.1/boot/classworlds-1.1.jar",
+        "apache-maven-2.2.1/conf/",
+        "apache-maven-2.2.1/conf/settings.xml",
+        "apache-maven-2.2.1/lib/"
     };
     
     private static final String LAST_ENTRY_NAME = 
-	"apache-maven-2.2.1/lib/maven-2.2.1-uber.jar";
+        "apache-maven-2.2.1/lib/maven-2.2.1-uber.jar";
     
     public void testRead7ZipMultiVolumeArchiveForStream() throws IOException,
-	    URISyntaxException {
-	
-	URL zip = getClass().getResource("/apache-maven-2.2.1.zip.001");
-	FileInputStream archive = new FileInputStream(
-		new File(new URI(zip.toString())));
-	ZipArchiveInputStream zi = null;
-	try {
-	    zi = new ZipArchiveInputStream(archive,null,false);
-	    
-	    // these are the entries that are supposed to be processed
-	    // correctly without any problems
-	    for (int i = 0; i < ENTRIES.length; i++) {
-		assertEquals(ENTRIES[i], zi.getNextEntry().getName());
-	    }
-	    
-	    // this is the last entry that is truncated
-	    ArchiveEntry lastEntry = zi.getNextEntry();
-	    assertEquals(LAST_ENTRY_NAME, lastEntry.getName());
-	    byte [] buffer = new byte [4096];
-	    
-	    // before the fix, we'd get 0 bytes on this read and all
-	    // subsequent reads thus a client application might enter
-	    // an infinite loop after the fix, we should get an
-	    // exception
-	    try {
+            URISyntaxException {
+        
+        URL zip = getClass().getResource("/apache-maven-2.2.1.zip.001");
+        FileInputStream archive = new FileInputStream(
+                new File(new URI(zip.toString())));
+        ZipArchiveInputStream zi = null;
+        try {
+            zi = new ZipArchiveInputStream(archive,null,false);
+            
+            // these are the entries that are supposed to be processed
+            // correctly without any problems
+            for (int i = 0; i < ENTRIES.length; i++) {
+                ZipArchiveEntry entry = zi.getNextZipEntry();
+                assertEquals(ENTRIES[i], entry.getName());
+                assertFalse(entry.isEncrypted()); // these entries are not encrypted
+            }
+            
+            // this is the last entry that is truncated
+            ArchiveEntry lastEntry = zi.getNextEntry();
+            assertEquals(LAST_ENTRY_NAME, lastEntry.getName());
+            byte [] buffer = new byte [4096];
+            
+            // before the fix, we'd get 0 bytes on this read and all
+            // subsequent reads thus a client application might enter
+            // an infinite loop after the fix, we should get an
+            // exception
+            try {
                 int read = 0;
-		while ((read = zi.read(buffer)) > 0) { }
-		fail("shouldn't be able to read from truncated entry");
-	    } catch (IOException e) {
+                while ((read = zi.read(buffer)) > 0) { }
+                fail("shouldn't be able to read from truncated entry");
+            } catch (IOException e) {
                 assertEquals("Truncated ZIP file", e.getMessage());
-	    }
-	    
-	    // and now we get another entry, which should also yield
-	    // an exception
-	    try {
-		zi.getNextEntry();
-		fail("shouldn't be able to read another entry from truncated"
+            }
+            
+            // and now we get another entry, which should also yield
+            // an exception
+            try {
+                zi.getNextEntry();
+                fail("shouldn't be able to read another entry from truncated"
                      + " file");
-	    } catch (IOException e) {
-		// this is to be expected
-	    }
-	} finally {
-	    if (zi != null) {
-		zi.close();
-	    }
-	}
+            } catch (IOException e) {
+                // this is to be expected
+            }
+        } finally {
+            if (zi != null) {
+                zi.close();
+            }
+        }
     }
 
     public void testRead7ZipMultiVolumeArchiveForFile()
         throws IOException, URISyntaxException {
-	URL zip = getClass().getResource("/apache-maven-2.2.1.zip.001");
+        URL zip = getClass().getResource("/apache-maven-2.2.1.zip.001");
         File file = new File(new URI(zip.toString()));
         try {
             new ZipFile(file);
Index: src/test/java/org/apache/commons/compress/archivers/zip/Maven221EncryptedTest.java
===================================================================
--- src/test/java/org/apache/commons/compress/archivers/zip/Maven221EncryptedTest.java	(revision 0)
+++ src/test/java/org/apache/commons/compress/archivers/zip/Maven221EncryptedTest.java	(revision 0)
@@ -0,0 +1,130 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You 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 org.apache.commons.compress.archivers.zip;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.zip.ZipException;
+
+import org.apache.commons.compress.archivers.ArchiveEntry;
+
+import junit.framework.TestCase;
+
+/**
+ * JUnit 3 testcase for an encrypted zip file.
+ * 
+ * The ZIP format allows for individual Archive entries to be encrypted.
+ * This is signified by the first bit in the general purpose flag in the
+ * File Header. This test tests the {@link ZipArchiveEntry#isEncrypted()}
+ * method, if it correctly returns true on all entries of the file.
+ * <p>
+ * The file in question has been generated with the linux 7za tool. I
+ * downloaded the release of the maven 2.2.1, got into that folder and typed
+ * 
+ * <pre>
+ * 7za a -tzip -phello -r maven.zip conf/ README.txt NOTICE.txt LICENSE.txt bin/ boot/
+ * </pre>
+ * 
+ */
+public class Maven221EncryptedTest extends TestCase {
+
+    private static final String FIRST_ENTRY = "LICENSE.txt";
+    
+    private static final String [] ENTRIES = new String [] {
+        "NOTICE.txt",
+        "boot/classworlds-1.1.jar",
+        "bin/",
+        "bin/mvn.bat",
+        "bin/mvnDebug",
+        "conf/settings.xml",
+        "LICENSE.txt",
+        "conf/",
+        "bin/mvnDebug.bat",
+        "bin/mvn",
+        "bin/m2.conf",
+        "boot/",
+        "README.txt"
+    };
+    
+    public void testRead7ZipEncryptedArchiveForStream() throws IOException,
+            URISyntaxException {
+        
+        URL zip = getClass().getResource("/apache-maven-2.2.1-encrypted-passhello.zip");
+        FileInputStream archive = new FileInputStream(
+                new File(new URI(zip.toString())));
+        ZipArchiveInputStream zi = null;
+        try {
+            zi = new ZipArchiveInputStream(archive,null,false);
+            
+            // the first entry is supposed to be read correctly
+            ZipArchiveEntry firstEntry = zi.getNextZipEntry();
+            assertEquals(FIRST_ENTRY, firstEntry.getName());
+            assertTrue(firstEntry.isEncrypted());
+            
+            // now since we don't support decrypting encrypted zips a call to read()
+            // should end with an error
+            try {
+                byte [] buffer = new byte[1024];
+                zi.read(buffer);
+                fail();
+            } catch (ZipException e) {
+                // the error message should contain some indication that
+                // the file is encrypted
+                assertTrue(e.getMessage().contains("file is encrypted"));
+            } catch (Exception e) {
+                fail(); // this can't be any other exception
+            }
+            
+        } finally {
+            if (zi != null) {
+                zi.close();
+            }
+        }
+    }
+    
+    public void testRead7ZipEncryptedArchiveForFile() throws IOException,
+            URISyntaxException {
+        URL zip = getClass().getResource("/apache-maven-2.2.1-encrypted-passhello.zip");
+        File file = new File(new URI(zip.toString()));
+        ZipFile zipFile = new ZipFile(file);
+        Enumeration entries = zipFile.getEntries();
+        int index = 0;
+        while (entries.hasMoreElements()) {
+            ZipArchiveEntry entry = (ZipArchiveEntry)entries.nextElement();
+            assertEquals(ENTRIES[index], entry.getName());
+            assertTrue(entry.isDirectory() || entry.isEncrypted()); // all entries are encrypted
+            
+            try {
+                // any attempt to read something should end with an exception
+                zipFile.getInputStream(entry);
+            } catch (ZipException e) {
+                assertTrue(e.getMessage().contains("File is encrypted"));
+            }
+            
+            index++;
+        }
+        assertEquals(ENTRIES.length, index);// see that all entries have been seen
+    }
+}
Index: src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java
===================================================================
--- src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java	(revision 832477)
+++ src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveInputStream.java	(working copy)
@@ -70,6 +70,7 @@
     private int bytesReadFromStream = 0;
     private int lengthOfLastRead = 0;
     private boolean hasDataDescriptor = false;
+    private boolean foundEncryptedEntries = false;
 
     private static final int LFH_LEN = 30;
     /*
@@ -137,6 +138,12 @@
         final int generalPurposeFlag = ZipShort.getValue(lfh, off);
         final boolean hasEFS = 
             (generalPurposeFlag & ZipArchiveOutputStream.EFS_FLAG) != 0;
+        final boolean isEncrypted =
+            (generalPurposeFlag & ZipArchiveOutputStream.ENCRYPTED_FLAG) != 0;
+        if (isEncrypted) {
+            foundEncryptedEntries = true;
+        }
+        current.setEncrypted(isEncrypted);
         final ZipEncoding entryEncoding =
             hasEFS ? ZipEncodingHelper.UTF8_ZIP_ENCODING : zipEncoding;
         hasDataDescriptor = (generalPurposeFlag & 8) != 0;
@@ -234,7 +241,8 @@
             try {
                 read = inf.inflate(buffer, start, length);
             } catch (DataFormatException e) {
-                throw new ZipException(e.getMessage());
+                throw new ZipException(e.getMessage() + 
+                        (foundEncryptedEntries ? " - the ZIP file is encrypted" : ""));
             }
             if (read == 0) {
                 if (inf.finished()) {
Index: src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveOutputStream.java
===================================================================
--- src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveOutputStream.java	(revision 832477)
+++ src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveOutputStream.java	(working copy)
@@ -99,6 +99,12 @@
      * written in utf-8.
      */
     public static final int EFS_FLAG = 1 << 11;
+    
+    /**
+     * General purpsoe flag which indicates that the entry is
+     * encrypted.
+     */
+    public static final int ENCRYPTED_FLAG = 1;
 
     /**
      * Current entry.
Index: src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveEntry.java
===================================================================
--- src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveEntry.java	(revision 832477)
+++ src/main/java/org/apache/commons/compress/archivers/zip/ZipArchiveEntry.java	(working copy)
@@ -42,7 +42,8 @@
     private long externalAttributes = 0;
     private LinkedHashMap/*<ZipShort, ZipExtraField>*/ extraFields = null;
     private String name = null;
-
+    private boolean encrypted;
+    
     /**
      * Creates a new zip entry with the specified name.
      * @param name the name of the entry
@@ -340,6 +341,22 @@
     public boolean isDirectory() {
         return getName().endsWith("/");
     }
+    
+    /**
+     * Is this entry encrypted?
+     * @return true if this entry is encrypted
+     */
+    public boolean isEncrypted() {
+        return encrypted;
+    }
+    
+    /**
+     * Sets the encryption status of this entry 
+     * @param encrypted
+     */
+    protected void setEncrypted(boolean encrypted) {
+        this.encrypted = encrypted;
+    }
 
     /**
      * Set the name of the entry.
Index: src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java
===================================================================
--- src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java	(revision 832477)
+++ src/main/java/org/apache/commons/compress/archivers/zip/ZipFile.java	(working copy)
@@ -257,6 +257,9 @@
         if (offsetEntry == null) {
             return null;
         }
+        if (ze.isEncrypted()) {
+            throw new ZipException("Can't read from entry. File is encrypted");
+        }
         long start = offsetEntry.dataOffset;
         BoundedInputStream bis =
             new BoundedInputStream(start, ze.getCompressedSize());
@@ -487,6 +490,10 @@
         /* crc-32                          */ + WORD
         /* compressed size                 */ + WORD
         /* uncompressed size               */ + WORD;
+    
+    private static final long LFH_OFFSET_FOR_GENERAL_PURPOSE_BIT_FLAG =
+        /* local file header signature     */ WORD
+        /* version needed to extract       */ + SHORT;
 
     /**
      * Walks through all recorded entries and adds the data available
@@ -502,8 +509,12 @@
             ZipArchiveEntry ze = (ZipArchiveEntry) e.nextElement();
             OffsetEntry offsetEntry = (OffsetEntry) entries.get(ze);
             long offset = offsetEntry.headerOffset;
-            archive.seek(offset + LFH_OFFSET_FOR_FILENAME_LENGTH);
             byte[] b = new byte[SHORT];
+            archive.seek(offset + LFH_OFFSET_FOR_GENERAL_PURPOSE_BIT_FLAG);
+            archive.readFully(b);
+            int generalPurposeBitFlag = ZipShort.getValue(b);
+            ze.setEncrypted((generalPurposeBitFlag & ZipArchiveOutputStream.ENCRYPTED_FLAG) != 0 ); 
+            archive.seek(offset + LFH_OFFSET_FOR_FILENAME_LENGTH);
             archive.readFully(b);
             int fileNameLen = ZipShort.getValue(b);
             archive.readFully(b);
