COMPRESS-203 the "file name" of a PAX header must not end with a slash or it is mistaken as a directory

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/compress/trunk@1426334 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 19f40a4..eef3eb2 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -74,6 +74,10 @@
         would write unreadable names in GNU mode or even cause errors
         in POSIX mode for file names longer than 66 characters.
       </action>
+      <action type="fix" date="2012-12-27" issue="COMPRESS-203">
+        Writing TAR PAX headers failed if the generated entry name
+        ended with a "/".
+      </action>
     </release>
     <release version="1.4.1" date="2012-05-23"
              description="Release 1.4.1">
diff --git a/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveOutputStream.java b/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveOutputStream.java
index de140b4..5a7e4a3 100644
--- a/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveOutputStream.java
+++ b/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveOutputStream.java
@@ -454,6 +454,11 @@
     void writePaxHeaders(String entryName,
                          Map<String, String> headers) throws IOException {
         String name = "./PaxHeaders.X/" + stripTo7Bits(entryName);
+        while (name.endsWith("/")) {
+            // TarEntry's constructor would think this is a directory
+            // and not allow any data to be written
+            name = name.substring(0, name.length() - 1);
+        }
         if (name.length() >= TarConstants.NAMELEN) {
             name = name.substring(0, TarConstants.NAMELEN - 1);
         }
diff --git a/src/test/java/org/apache/commons/compress/archivers/tar/TarArchiveOutputStreamTest.java b/src/test/java/org/apache/commons/compress/archivers/tar/TarArchiveOutputStreamTest.java
index 4ab1805..7a50820 100644
--- a/src/test/java/org/apache/commons/compress/archivers/tar/TarArchiveOutputStreamTest.java
+++ b/src/test/java/org/apache/commons/compress/archivers/tar/TarArchiveOutputStreamTest.java
@@ -372,4 +372,59 @@
         tin.close();
     }
 
+    /**
+     * @see https://issues.apache.org/jira/browse/COMPRESS-203
+     */
+    public void testWriteLongDirectoryNameGnuMode() throws Exception {
+        testWriteLongDirectoryName(TarArchiveOutputStream.LONGFILE_GNU);
+    }
+
+    /**
+     * @see https://issues.apache.org/jira/browse/COMPRESS-203
+     */
+    public void testWriteLongDirectoryNamePosixMode() throws Exception {
+        testWriteLongDirectoryName(TarArchiveOutputStream.LONGFILE_POSIX);
+    }
+
+    private void testWriteLongDirectoryName(int mode) throws Exception {
+        String n = "01234567890123456789012345678901234567890123456789"
+            + "01234567890123456789012345678901234567890123456789"
+            + "01234567890123456789012345678901234567890123456789/";
+        TarArchiveEntry t = new TarArchiveEntry(n);
+        ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        TarArchiveOutputStream tos = new TarArchiveOutputStream(bos, "ASCII");
+        tos.setLongFileMode(mode);
+        tos.putArchiveEntry(t);
+        tos.closeArchiveEntry();
+        tos.close();
+        byte[] data = bos.toByteArray();
+        TarArchiveInputStream tin =
+            new TarArchiveInputStream(new ByteArrayInputStream(data));
+        TarArchiveEntry e = tin.getNextTarEntry();
+        assertEquals(n, e.getName());
+        assertTrue(e.isDirectory());
+        tin.close();
+    }
+
+    /**
+     * @see https://issues.apache.org/jira/browse/COMPRESS-203
+     */
+    public void testWriteNonAsciiDirectoryNamePosixMode() throws Exception {
+        String n = "f\u00f6\u00f6/";
+        TarArchiveEntry t = new TarArchiveEntry(n);
+        ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        TarArchiveOutputStream tos = new TarArchiveOutputStream(bos);
+        tos.setAddPaxHeadersForNonAsciiNames(true);
+        tos.putArchiveEntry(t);
+        tos.closeArchiveEntry();
+        tos.close();
+        byte[] data = bos.toByteArray();
+        TarArchiveInputStream tin =
+            new TarArchiveInputStream(new ByteArrayInputStream(data));
+        TarArchiveEntry e = tin.getNextTarEntry();
+        assertEquals(n, e.getName());
+        assertTrue(e.isDirectory());
+        tin.close();
+    }
+
 }