1 /*
   2  * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /* @test
  25    @bug 4334846
  26    @summary Make sure zip file comments of various sizes can be written.
  27    @author Martin Buchholz
  28  */
  29 
  30 import java.io.*;
  31 
  32 import java.util.zip.ZipEntry;
  33 import java.util.zip.ZipFile;
  34 import java.util.zip.ZipOutputStream;
  35 
  36 public class Comment {
  37     private static final String entryName = "entryName";
  38     private static final String entryContents = "entryContents";
  39     private static final int commentMaxLength = 0xFFFF;
  40     private static final int [] commentLengths
  41         = { 0, 1, 32768, commentMaxLength - 1, commentMaxLength };
  42 
  43     public static void main(String argv[])
  44         throws Exception
  45     {
  46         for (int i = 0; i < commentLengths.length; ++i) {
  47             int commentLength = commentLengths[i];
  48             String comment = buildComment(commentLength);
  49             String name = "Test" + commentLength + ".zip";
  50             writeZipFile(name, comment);
  51             verifyZipFile(name, comment);
  52             new File(name).delete();
  53             System.out.println(commentLength + ": successful");
  54         }
  55     }
  56 
  57     private static void writeZipFile(String name, String comment)
  58         throws IOException
  59     {
  60         try (FileOutputStream fos = new FileOutputStream(name);
  61              ZipOutputStream zos = new ZipOutputStream(fos))
  62         {
  63             zos.setComment(comment);
  64             ZipEntry ze = new ZipEntry(entryName);
  65             ze.setMethod(ZipEntry.DEFLATED);
  66             zos.putNextEntry(ze);
  67             new DataOutputStream(zos).writeUTF(entryContents);
  68             zos.closeEntry();
  69         }
  70     }
  71 
  72     private static void verifyZipFile(String name, String comment)
  73         throws Exception
  74     {
  75         // Check that Zip entry was correctly written.
  76         try (ZipFile zipFile = new ZipFile(name)) {
  77             ZipEntry zipEntry = zipFile.getEntry(entryName);
  78             InputStream is = zipFile.getInputStream(zipEntry);
  79             String result = new DataInputStream(is).readUTF();
  80             if (!result.equals(entryContents))
  81                 throw new Exception("Entry contents corrupted");
  82         }
  83 
  84         try (RandomAccessFile file = new RandomAccessFile(name, "r")) {
  85             // Check that comment length was correctly written.
  86             file.seek(file.length() - comment.length()
  87                       - ZipFile.ENDHDR + ZipFile.ENDCOM);
  88             int b1 = file.readUnsignedByte();
  89             int b2 = file.readUnsignedByte();
  90             if (b1 + (b2 << 8) != comment.length())
  91                 throw new Exception("Zip file comment length corrupted");
  92 
  93             // Check that comment was correctly written.
  94             file.seek(file.length() - comment.length());
  95             byte [] bytes = new byte [comment.length()];
  96             file.readFully(bytes);
  97             if (! comment.equals(new String(bytes, "UTF8")))
  98                 throw new Exception("Zip file comment corrupted");
  99         }
 100     }
 101 
 102     private static String buildComment(int length) {
 103         StringBuffer result = new StringBuffer();
 104         while (result.length() < length) {
 105             /* Endhdr is 22 bytes long, so this pattern makes it easy
 106              * to see if it is copied correctly */
 107             result.append("abcdefghijklmnopqrstuvABCDEFGHIJKLMNOPQRSTUV");
 108         }
 109         String string = result.toString();
 110         string = string.substring(string.length() - length);
 111         return string;
 112     }
 113 }