You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by bo...@apache.org on 2018/05/07 14:26:13 UTC

[2/3] commons-compress git commit: add char[] constructors to SevenZFile

add char[] constructors to SevenZFile


Project: http://git-wip-us.apache.org/repos/asf/commons-compress/repo
Commit: http://git-wip-us.apache.org/repos/asf/commons-compress/commit/237e1721
Tree: http://git-wip-us.apache.org/repos/asf/commons-compress/tree/237e1721
Diff: http://git-wip-us.apache.org/repos/asf/commons-compress/diff/237e1721

Branch: refs/heads/COMPRESS-452
Commit: 237e1721221d158f6800e868cbefc83f02385029
Parents: 3eeb22c
Author: Stefan Bodewig <bo...@apache.org>
Authored: Mon May 7 08:08:45 2018 +0200
Committer: Stefan Bodewig <bo...@apache.org>
Committed: Mon May 7 16:25:46 2018 +0200

----------------------------------------------------------------------
 .../compress/archivers/sevenz/SevenZFile.java   | 77 +++++++++++++++++++-
 .../archivers/sevenz/SevenZFileTest.java        | 22 +++++-
 .../archivers/sevenz/SevenZOutputFileTest.java  |  2 +-
 3 files changed, 96 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-compress/blob/237e1721/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZFile.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZFile.java b/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZFile.java
index 6690847..902174c 100644
--- a/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZFile.java
+++ b/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZFile.java
@@ -27,7 +27,10 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
+import java.nio.CharBuffer;
 import java.nio.channels.SeekableByteChannel;
+import java.nio.charset.StandardCharsets;
+import java.nio.charset.CharsetEncoder;
 import java.nio.file.Files;
 import java.nio.file.StandardOpenOption;
 import java.util.ArrayList;
@@ -97,10 +100,24 @@ public class SevenZFile implements Closeable {
      * Reads a file as 7z archive
      *
      * @param filename the file to read
+     * @param password optional password if the archive is encrypted
+     * @throws IOException if reading the archive fails
+     * @since 1.17
+     */
+    public SevenZFile(final File filename, final char[] password) throws IOException {
+        this(Files.newByteChannel(filename.toPath(), EnumSet.of(StandardOpenOption.READ)),
+             filename.getAbsolutePath(), utf16Decode(password), true);
+    }
+
+    /**
+     * Reads a file as 7z archive
+     *
+     * @param filename the file to read
      * @param password optional password if the archive is encrypted -
      * the byte array is supposed to be the UTF16-LE encoded
      * representation of the password.
      * @throws IOException if reading the archive fails
+     * @deprecated use the char[]-arg version for the password instead
      */
     public SevenZFile(final File filename, final byte[] password) throws IOException {
         this(Files.newByteChannel(filename.toPath(), EnumSet.of(StandardOpenOption.READ)),
@@ -119,7 +136,46 @@ public class SevenZFile implements Closeable {
      * @since 1.13
      */
     public SevenZFile(final SeekableByteChannel channel) throws IOException {
-        this(channel, "unknown archive", null);
+        this(channel, "unknown archive", (char[]) null);
+    }
+
+    /**
+     * Reads a SeekableByteChannel as 7z archive
+     *
+     * <p>{@link
+     * org.apache.commons.compress.utils.SeekableInMemoryByteChannel}
+     * allows you to read from an in-memory archive.</p>
+     *
+     * @param channel the channel to read
+     * @param password optional password if the archive is encrypted -
+     * the byte array is supposed to be the UTF16-LE encoded
+     * representation of the password.
+     * @throws IOException if reading the archive fails
+     * @since 1.17
+     */
+    public SevenZFile(final SeekableByteChannel channel,
+                      final char[] password) throws IOException {
+        this(channel, "unknown archive", utf16Decode(password));
+    }
+
+    /**
+     * Reads a SeekableByteChannel as 7z archive
+     *
+     * <p>{@link
+     * org.apache.commons.compress.utils.SeekableInMemoryByteChannel}
+     * allows you to read from an in-memory archive.</p>
+     *
+     * @param channel the channel to read
+     * @param filename name of the archive - only used for error reporting
+     * @param password optional password if the archive is encrypted -
+     * the byte array is supposed to be the UTF16-LE encoded
+     * representation of the password.
+     * @throws IOException if reading the archive fails
+     * @since 1.17
+     */
+    public SevenZFile(final SeekableByteChannel channel, String filename,
+                      final char[] password) throws IOException {
+        this(channel, filename, utf16Decode(password), false);
     }
 
     /**
@@ -135,6 +191,7 @@ public class SevenZFile implements Closeable {
      * representation of the password.
      * @throws IOException if reading the archive fails
      * @since 1.13
+     * @deprecated use the char[]-arg version for the password instead
      */
     public SevenZFile(final SeekableByteChannel channel,
                       final byte[] password) throws IOException {
@@ -155,6 +212,7 @@ public class SevenZFile implements Closeable {
      * representation of the password.
      * @throws IOException if reading the archive fails
      * @since 1.13
+     * @deprecated use the char[]-arg version for the password instead
      */
     public SevenZFile(final SeekableByteChannel channel, String filename,
                       final byte[] password) throws IOException {
@@ -188,7 +246,7 @@ public class SevenZFile implements Closeable {
      * @throws IOException if reading the archive fails
      */
     public SevenZFile(final File filename) throws IOException {
-        this(filename, null);
+        this(filename, (char[]) null);
     }
 
     /**
@@ -1122,4 +1180,19 @@ public class SevenZFile implements Closeable {
     public String toString() {
       return archive.toString();
     }
+
+    private static final CharsetEncoder PASSWORD_ENCODER = StandardCharsets.UTF_16LE.newEncoder();
+
+    private static byte[] utf16Decode(char[] chars) throws IOException {
+        if (chars == null) {
+            return null;
+        }
+        ByteBuffer encoded = PASSWORD_ENCODER.encode(CharBuffer.wrap(chars));
+        if (encoded.hasArray()) {
+            return encoded.array();
+        }
+        byte[] e = new byte[encoded.remaining()];
+        encoded.get(e);
+        return e;
+    }
 }

http://git-wip-us.apache.org/repos/asf/commons-compress/blob/237e1721/src/test/java/org/apache/commons/compress/archivers/sevenz/SevenZFileTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/compress/archivers/sevenz/SevenZFileTest.java b/src/test/java/org/apache/commons/compress/archivers/sevenz/SevenZFileTest.java
index 954cd09..6ad7224 100644
--- a/src/test/java/org/apache/commons/compress/archivers/sevenz/SevenZFileTest.java
+++ b/src/test/java/org/apache/commons/compress/archivers/sevenz/SevenZFileTest.java
@@ -144,8 +144,16 @@ public class SevenZFileTest extends AbstractTestCase {
         }
     }
 
+    @Test
+    public void test7zDecryptUnarchiveUsingCharArrayPassword() throws Exception {
+        if (isStrongCryptoAvailable()) {
+            test7zUnarchive(getFile("bla.encrypted.7z"), SevenZMethod.LZMA, // stack LZMA + AES
+                            "foo".toCharArray());
+        }
+    }
+
     private void test7zUnarchive(final File f, final SevenZMethod m) throws Exception {
-        test7zUnarchive(f, m, null);
+        test7zUnarchive(f, m, (char[]) null);
     }
 
     @Test
@@ -288,6 +296,17 @@ public class SevenZFileTest extends AbstractTestCase {
 
     private void test7zUnarchive(final File f, final SevenZMethod m, final byte[] password) throws Exception {
         try (SevenZFile sevenZFile = new SevenZFile(f, password)) {
+            test7zUnarchive(sevenZFile, m);
+        }
+    }
+
+    private void test7zUnarchive(final File f, final SevenZMethod m, final char[] password) throws Exception {
+        try (SevenZFile sevenZFile = new SevenZFile(f, password)) {
+            test7zUnarchive(sevenZFile, m);
+        }
+    }
+
+    private void test7zUnarchive(SevenZFile sevenZFile, final SevenZMethod m) throws Exception {
             SevenZArchiveEntry entry = sevenZFile.getNextEntry();
             assertEquals("test1.xml", entry.getName());
             assertEquals(m, entry.getContentMethods().iterator().next().getMethod());
@@ -303,7 +322,6 @@ public class SevenZFileTest extends AbstractTestCase {
             }
             assertEquals(TEST2_CONTENT, new String(contents, "UTF-8"));
             assertNull(sevenZFile.getNextEntry());
-        }
     }
 
     private void checkHelloWorld(final String filename) throws Exception {

http://git-wip-us.apache.org/repos/asf/commons-compress/blob/237e1721/src/test/java/org/apache/commons/compress/archivers/sevenz/SevenZOutputFileTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/compress/archivers/sevenz/SevenZOutputFileTest.java b/src/test/java/org/apache/commons/compress/archivers/sevenz/SevenZOutputFileTest.java
index 058c9e3..092e520 100644
--- a/src/test/java/org/apache/commons/compress/archivers/sevenz/SevenZOutputFileTest.java
+++ b/src/test/java/org/apache/commons/compress/archivers/sevenz/SevenZOutputFileTest.java
@@ -502,7 +502,7 @@ public class SevenZOutputFileTest extends AbstractTestCase {
         }
         try (SevenZFile archive =
              new SevenZFile(new SeekableInMemoryByteChannel(output.array()), "in memory",
-                            null)) {
+                            (char[]) null)) {
             assertEquals(Boolean.TRUE, verifyFile(archive, 0, methods));
         }
     }