Merge
This commit is contained in:
commit
dd28a663e4
@ -29,7 +29,6 @@ FILES_c = \
|
||||
Deflater.c \
|
||||
Inflater.c \
|
||||
ZipFile.c \
|
||||
ZipEntry.c \
|
||||
zadler32.c \
|
||||
zcrc32.c \
|
||||
deflate.c \
|
||||
|
@ -50,15 +50,17 @@ SUNWprivate_1.1 {
|
||||
Java_java_util_zip_Inflater_initIDs;
|
||||
Java_java_util_zip_Inflater_reset;
|
||||
Java_java_util_zip_Inflater_setDictionary;
|
||||
Java_java_util_zip_ZipEntry_initFields;
|
||||
Java_java_util_zip_ZipEntry_initIDs;
|
||||
Java_java_util_zip_ZipFile_close;
|
||||
Java_java_util_zip_ZipFile_freeEntry;
|
||||
Java_java_util_zip_ZipFile_getCSize;
|
||||
Java_java_util_zip_ZipFile_getEntry;
|
||||
Java_java_util_zip_ZipFile_getMethod;
|
||||
Java_java_util_zip_ZipFile_getEntryBytes;
|
||||
Java_java_util_zip_ZipFile_getEntryCrc;
|
||||
Java_java_util_zip_ZipFile_getEntryCSize;
|
||||
Java_java_util_zip_ZipFile_getEntryFlag;
|
||||
Java_java_util_zip_ZipFile_getEntryMethod;
|
||||
Java_java_util_zip_ZipFile_getEntrySize;
|
||||
Java_java_util_zip_ZipFile_getEntryTime;
|
||||
Java_java_util_zip_ZipFile_getNextEntry;
|
||||
Java_java_util_zip_ZipFile_getSize;
|
||||
Java_java_util_zip_ZipFile_getZipMessage;
|
||||
Java_java_util_zip_ZipFile_getTotal;
|
||||
Java_java_util_zip_ZipFile_initIDs;
|
||||
|
@ -20,12 +20,14 @@ text: .text%Java_java_util_zip_ZipFile_initIDs;
|
||||
text: .text%Java_java_util_zip_ZipFile_open;
|
||||
text: .text%Java_java_util_zip_ZipFile_getTotal;
|
||||
text: .text%Java_java_util_zip_ZipFile_getEntry;
|
||||
text: .text%Java_java_util_zip_ZipEntry_initIDs;
|
||||
text: .text%Java_java_util_zip_ZipEntry_initFields;
|
||||
text: .text%Java_java_util_zip_ZipFile_freeEntry;
|
||||
text: .text%Java_java_util_zip_ZipFile_getCSize;
|
||||
text: .text%Java_java_util_zip_ZipFile_getSize;
|
||||
text: .text%Java_java_util_zip_ZipFile_getMethod;
|
||||
text: .text%Java_java_util_zip_ZipFile_getEntryTime;
|
||||
text: .text%Java_java_util_zip_ZipFile_getEntryCrc;
|
||||
text: .text%Java_java_util_zip_ZipFile_getEntryCSize;
|
||||
text: .text%Java_java_util_zip_ZipFile_getEntrySize;
|
||||
text: .text%Java_java_util_zip_ZipFile_getEntryFlag;
|
||||
text: .text%Java_java_util_zip_ZipFile_getEntryMethod;
|
||||
text: .text%Java_java_util_zip_ZipFile_getEntryBytes;
|
||||
text: .text%Java_java_util_zip_Inflater_initIDs;
|
||||
text: .text%Java_java_util_zip_Inflater_init;
|
||||
text: .text%inflateInit2_;
|
||||
|
@ -19,12 +19,14 @@ text: .text%Java_java_util_zip_ZipFile_initIDs;
|
||||
text: .text%Java_java_util_zip_ZipFile_open;
|
||||
text: .text%Java_java_util_zip_ZipFile_getTotal;
|
||||
text: .text%Java_java_util_zip_ZipFile_getEntry;
|
||||
text: .text%Java_java_util_zip_ZipEntry_initIDs;
|
||||
text: .text%Java_java_util_zip_ZipEntry_initFields;
|
||||
text: .text%Java_java_util_zip_ZipFile_freeEntry;
|
||||
text: .text%Java_java_util_zip_ZipFile_getCSize;
|
||||
text: .text%Java_java_util_zip_ZipFile_getSize;
|
||||
text: .text%Java_java_util_zip_ZipFile_getMethod;
|
||||
text: .text%Java_java_util_zip_ZipFile_getEntryTime;
|
||||
text: .text%Java_java_util_zip_ZipFile_getEntryCrc;
|
||||
text: .text%Java_java_util_zip_ZipFile_getEntryCSize;
|
||||
text: .text%Java_java_util_zip_ZipFile_getEntrySize;
|
||||
text: .text%Java_java_util_zip_ZipFile_getEntryFlag;
|
||||
text: .text%Java_java_util_zip_ZipFile_getEntryMethod;
|
||||
text: .text%Java_java_util_zip_ZipFile_getEntryBytes;
|
||||
text: .text%Java_java_util_zip_Inflater_initIDs;
|
||||
text: .text%Java_java_util_zip_Inflater_init;
|
||||
text: .text%inflateInit2_;
|
||||
|
@ -20,12 +20,14 @@ text: .text%Java_java_util_zip_ZipFile_initIDs;
|
||||
text: .text%Java_java_util_zip_ZipFile_open;
|
||||
text: .text%Java_java_util_zip_ZipFile_getTotal;
|
||||
text: .text%Java_java_util_zip_ZipFile_getEntry;
|
||||
text: .text%Java_java_util_zip_ZipEntry_initIDs;
|
||||
text: .text%Java_java_util_zip_ZipEntry_initFields;
|
||||
text: .text%Java_java_util_zip_ZipFile_freeEntry;
|
||||
text: .text%Java_java_util_zip_ZipFile_getCSize;
|
||||
text: .text%Java_java_util_zip_ZipFile_getSize;
|
||||
text: .text%Java_java_util_zip_ZipFile_getMethod;
|
||||
text: .text%Java_java_util_zip_ZipFile_getEntryTime;
|
||||
text: .text%Java_java_util_zip_ZipFile_getEntryCrc;
|
||||
text: .text%Java_java_util_zip_ZipFile_getEntryCSize;
|
||||
text: .text%Java_java_util_zip_ZipFile_getEntrySize;
|
||||
text: .text%Java_java_util_zip_ZipFile_getEntryFlag;
|
||||
text: .text%Java_java_util_zip_ZipFile_getEntryMethod;
|
||||
text: .text%Java_java_util_zip_ZipFile_getEntryBytes;
|
||||
text: .text%Java_java_util_zip_Inflater_initIDs;
|
||||
text: .text%Java_java_util_zip_Inflater_init;
|
||||
text: .text%inflateInit2_;
|
||||
|
139
jdk/src/share/classes/java/util/zip/ZipCoder.java
Normal file
139
jdk/src/share/classes/java/util/zip/ZipCoder.java
Normal file
@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Sun designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Sun in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
package java.util.zip;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.CharBuffer;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.CharsetDecoder;
|
||||
import java.nio.charset.CharsetEncoder;
|
||||
import java.nio.charset.CoderResult;
|
||||
import java.nio.charset.CodingErrorAction;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Utility class for zipfile name and comment decoding and encoding
|
||||
*/
|
||||
|
||||
final class ZipCoder {
|
||||
|
||||
String toString(byte[] ba, int length) {
|
||||
CharsetDecoder cd = decoder().reset();
|
||||
int len = (int)(length * cd.maxCharsPerByte());
|
||||
char[] ca = new char[len];
|
||||
if (len == 0)
|
||||
return new String(ca);
|
||||
ByteBuffer bb = ByteBuffer.wrap(ba, 0, length);
|
||||
CharBuffer cb = CharBuffer.wrap(ca);
|
||||
CoderResult cr = cd.decode(bb, cb, true);
|
||||
if (!cr.isUnderflow())
|
||||
throw new IllegalArgumentException(cr.toString());
|
||||
cr = cd.flush(cb);
|
||||
if (!cr.isUnderflow())
|
||||
throw new IllegalArgumentException(cr.toString());
|
||||
return new String(ca, 0, cb.position());
|
||||
}
|
||||
|
||||
String toString(byte[] ba) {
|
||||
return toString(ba, ba.length);
|
||||
}
|
||||
|
||||
byte[] getBytes(String s) {
|
||||
CharsetEncoder ce = encoder().reset();
|
||||
char[] ca = s.toCharArray();
|
||||
int len = (int)(ca.length * ce.maxBytesPerChar());
|
||||
byte[] ba = new byte[len];
|
||||
if (len == 0)
|
||||
return ba;
|
||||
ByteBuffer bb = ByteBuffer.wrap(ba);
|
||||
CharBuffer cb = CharBuffer.wrap(ca);
|
||||
CoderResult cr = ce.encode(cb, bb, true);
|
||||
if (!cr.isUnderflow())
|
||||
throw new IllegalArgumentException(cr.toString());
|
||||
cr = ce.flush(bb);
|
||||
if (!cr.isUnderflow())
|
||||
throw new IllegalArgumentException(cr.toString());
|
||||
if (bb.position() == ba.length) // defensive copy?
|
||||
return ba;
|
||||
else
|
||||
return Arrays.copyOf(ba, bb.position());
|
||||
}
|
||||
|
||||
// assume invoked only if "this" is not utf8
|
||||
byte[] getBytesUTF8(String s) {
|
||||
if (isutf8)
|
||||
return getBytes(s);
|
||||
if (utf8 == null)
|
||||
utf8 = new ZipCoder(Charset.forName("UTF-8"));
|
||||
return utf8.getBytes(s);
|
||||
}
|
||||
|
||||
|
||||
String toStringUTF8(byte[] ba, int len) {
|
||||
if (isutf8)
|
||||
return toString(ba, len);
|
||||
if (utf8 == null)
|
||||
utf8 = new ZipCoder(Charset.forName("UTF-8"));
|
||||
return utf8.toString(ba, len);
|
||||
}
|
||||
|
||||
boolean isUTF8() {
|
||||
return isutf8;
|
||||
}
|
||||
|
||||
private Charset cs;
|
||||
private CharsetDecoder dec;
|
||||
private CharsetEncoder enc;
|
||||
private boolean isutf8;
|
||||
private ZipCoder utf8;
|
||||
|
||||
private ZipCoder(Charset cs) {
|
||||
this.cs = cs;
|
||||
this.isutf8 = cs.name().equals("UTF-8");
|
||||
}
|
||||
|
||||
static ZipCoder get(Charset charset) {
|
||||
return new ZipCoder(charset);
|
||||
}
|
||||
|
||||
private CharsetDecoder decoder() {
|
||||
if (dec == null) {
|
||||
dec = cs.newDecoder()
|
||||
.onMalformedInput(CodingErrorAction.REPORT)
|
||||
.onUnmappableCharacter(CodingErrorAction.REPORT);
|
||||
}
|
||||
return dec;
|
||||
}
|
||||
|
||||
private CharsetEncoder encoder() {
|
||||
if (enc == null) {
|
||||
enc = cs.newEncoder()
|
||||
.onMalformedInput(CodingErrorAction.REPORT)
|
||||
.onUnmappableCharacter(CodingErrorAction.REPORT);
|
||||
}
|
||||
return enc;
|
||||
}
|
||||
}
|
@ -73,5 +73,12 @@ class ZipConstants64 {
|
||||
static final int ZIP64_EXTSIZ = 8; // compressed size, 8-byte
|
||||
static final int ZIP64_EXTLEN = 16; // uncompressed size, 8-byte
|
||||
|
||||
/*
|
||||
* Language encoding flag EFS
|
||||
*/
|
||||
static final int EFS = 0x800; // If this bit is set the filename and
|
||||
// comment fields for this file must be
|
||||
// encoded using UTF-8.
|
||||
|
||||
private ZipConstants64() {}
|
||||
}
|
||||
|
@ -40,6 +40,7 @@ class ZipEntry implements ZipConstants, Cloneable {
|
||||
long size = -1; // uncompressed size of entry data
|
||||
long csize = -1; // compressed size of entry data
|
||||
int method = -1; // compression method
|
||||
int flag = 0; // general purpose flag
|
||||
byte[] extra; // optional extra field data for entry
|
||||
String comment; // optional comment string for entry
|
||||
|
||||
@ -53,13 +54,6 @@ class ZipEntry implements ZipConstants, Cloneable {
|
||||
*/
|
||||
public static final int DEFLATED = 8;
|
||||
|
||||
static {
|
||||
/* Zip library is loaded from System.initializeSystemClass */
|
||||
initIDs();
|
||||
}
|
||||
|
||||
private static native void initIDs();
|
||||
|
||||
/**
|
||||
* Creates a new zip entry with the specified name.
|
||||
*
|
||||
@ -90,28 +84,15 @@ class ZipEntry implements ZipConstants, Cloneable {
|
||||
size = e.size;
|
||||
csize = e.csize;
|
||||
method = e.method;
|
||||
flag = e.flag;
|
||||
extra = e.extra;
|
||||
comment = e.comment;
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates a new zip entry for the given name with fields initialized
|
||||
* from the specified jzentry data.
|
||||
* Creates a new un-initialized zip entry
|
||||
*/
|
||||
ZipEntry(String name, long jzentry) {
|
||||
this.name = name;
|
||||
initFields(jzentry);
|
||||
}
|
||||
|
||||
private native void initFields(long jzentry);
|
||||
|
||||
/*
|
||||
* Creates a new zip entry with fields initialized from the specified
|
||||
* jzentry data.
|
||||
*/
|
||||
ZipEntry(long jzentry) {
|
||||
initFields(jzentry);
|
||||
}
|
||||
ZipEntry() {}
|
||||
|
||||
/**
|
||||
* Returns the name of the entry.
|
||||
@ -258,16 +239,16 @@ class ZipEntry implements ZipConstants, Cloneable {
|
||||
|
||||
/**
|
||||
* Sets the optional comment string for the entry.
|
||||
*
|
||||
* <p>ZIP entry comments have maximum length of 0xffff. If the length of the
|
||||
* specified comment string is greater than 0xFFFF bytes after encoding, only
|
||||
* the first 0xFFFF bytes are output to the ZIP file entry.
|
||||
*
|
||||
* @param comment the comment string
|
||||
* @exception IllegalArgumentException if the length of the specified
|
||||
* comment string is greater than 0xFFFF bytes
|
||||
*
|
||||
* @see #getComment()
|
||||
*/
|
||||
public void setComment(String comment) {
|
||||
if (comment != null && comment.length() > 0xffff/3
|
||||
&& ZipOutputStream.getUTF8Length(comment) > 0xffff) {
|
||||
throw new IllegalArgumentException("invalid entry comment length");
|
||||
}
|
||||
this.comment = comment;
|
||||
}
|
||||
|
||||
|
@ -29,9 +29,11 @@ import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.EOFException;
|
||||
import java.io.File;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Vector;
|
||||
import java.util.Enumeration;
|
||||
import java.util.NoSuchElementException;
|
||||
import static java.util.zip.ZipConstants64.*;
|
||||
|
||||
/**
|
||||
* This class is used to read entries from a zip file.
|
||||
@ -76,16 +78,19 @@ class ZipFile implements ZipConstants {
|
||||
/**
|
||||
* Opens a zip file for reading.
|
||||
*
|
||||
* <p>First, if there is a security
|
||||
* manager, its <code>checkRead</code> method
|
||||
* is called with the <code>name</code> argument
|
||||
* as its argument to ensure the read is allowed.
|
||||
* <p>First, if there is a security manager, its <code>checkRead</code>
|
||||
* method is called with the <code>name</code> argument as its argument
|
||||
* to ensure the read is allowed.
|
||||
*
|
||||
* <p>The UTF-8 {@link java.nio.charset.Charset charset} is used to
|
||||
* decode the entry names and comments.
|
||||
*
|
||||
* @param name the name of the zip file
|
||||
* @throws ZipException if a ZIP format error has occurred
|
||||
* @throws IOException if an I/O error has occurred
|
||||
* @throws SecurityException if a security manager exists and its
|
||||
* <code>checkRead</code> method doesn't allow read access to the file.
|
||||
*
|
||||
* @see SecurityManager#checkRead(java.lang.String)
|
||||
*/
|
||||
public ZipFile(String name) throws IOException {
|
||||
@ -101,6 +106,9 @@ class ZipFile implements ZipConstants {
|
||||
* method is called with the <code>name</code> argument as its argument to
|
||||
* ensure the read is allowed.
|
||||
*
|
||||
* <p>The UTF-8 {@link java.nio.charset.Charset charset} is used to
|
||||
* decode the entry names and comments
|
||||
*
|
||||
* @param file the ZIP file to be opened for reading
|
||||
* @param mode the mode in which the file is to be opened
|
||||
* @throws ZipException if a ZIP format error has occurred
|
||||
@ -115,6 +123,59 @@ class ZipFile implements ZipConstants {
|
||||
* @since 1.3
|
||||
*/
|
||||
public ZipFile(File file, int mode) throws IOException {
|
||||
this(file, mode, Charset.forName("UTF-8"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a ZIP file for reading given the specified File object.
|
||||
*
|
||||
* <p>The UTF-8 {@link java.nio.charset.Charset charset} is used to
|
||||
* decode the entry names and comments.
|
||||
*
|
||||
* @param file the ZIP file to be opened for reading
|
||||
* @throws ZipException if a ZIP format error has occurred
|
||||
* @throws IOException if an I/O error has occurred
|
||||
*/
|
||||
public ZipFile(File file) throws ZipException, IOException {
|
||||
this(file, OPEN_READ);
|
||||
}
|
||||
|
||||
private ZipCoder zc;
|
||||
|
||||
/**
|
||||
* Opens a new <code>ZipFile</code> to read from the specified
|
||||
* <code>File</code> object in the specified mode. The mode argument
|
||||
* must be either <tt>OPEN_READ</tt> or <tt>OPEN_READ | OPEN_DELETE</tt>.
|
||||
*
|
||||
* <p>First, if there is a security manager, its <code>checkRead</code>
|
||||
* method is called with the <code>name</code> argument as its argument to
|
||||
* ensure the read is allowed.
|
||||
*
|
||||
* @param file the ZIP file to be opened for reading
|
||||
* @param mode the mode in which the file is to be opened
|
||||
* @param charset
|
||||
* the {@link java.nio.charset.Charset {@code charset}} to
|
||||
* be used to decode the ZIP entry name and comment that are not
|
||||
* encoded by using UTF-8 encoding (indicated by entry's general
|
||||
* purpose flag).
|
||||
*
|
||||
* @throws ZipException if a ZIP format error has occurred
|
||||
* @throws IOException if an I/O error has occurred
|
||||
*
|
||||
* @throws SecurityException
|
||||
* if a security manager exists and its <code>checkRead</code>
|
||||
* method doesn't allow read access to the file,or its
|
||||
* <code>checkDelete</code> method doesn't allow deleting the
|
||||
* file when the <tt>OPEN_DELETE</tt> flag is set
|
||||
*
|
||||
* @throws IllegalArgumentException if the <tt>mode</tt> argument is invalid
|
||||
*
|
||||
* @see SecurityManager#checkRead(java.lang.String)
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
public ZipFile(File file, int mode, Charset charset) throws IOException
|
||||
{
|
||||
if (((mode & OPEN_READ) == 0) ||
|
||||
((mode & ~(OPEN_READ | OPEN_DELETE)) != 0)) {
|
||||
throw new IllegalArgumentException("Illegal mode: 0x"+
|
||||
@ -128,24 +189,61 @@ class ZipFile implements ZipConstants {
|
||||
sm.checkDelete(name);
|
||||
}
|
||||
}
|
||||
if (charset == null)
|
||||
throw new NullPointerException("charset is null");
|
||||
this.zc = ZipCoder.get(charset);
|
||||
jzfile = open(name, mode, file.lastModified());
|
||||
|
||||
this.name = name;
|
||||
this.total = getTotal(jzfile);
|
||||
}
|
||||
|
||||
private static native long open(String name, int mode, long lastModified);
|
||||
private static native int getTotal(long jzfile);
|
||||
|
||||
/**
|
||||
* Opens a zip file for reading.
|
||||
*
|
||||
* <p>First, if there is a security manager, its <code>checkRead</code>
|
||||
* method is called with the <code>name</code> argument as its argument
|
||||
* to ensure the read is allowed.
|
||||
*
|
||||
* @param name the name of the zip file
|
||||
* @param charset
|
||||
* the {@link java.nio.charset.Charset {@code charset}} to
|
||||
* be used to decode the ZIP entry name and comment that are not
|
||||
* encoded by using UTF-8 encoding (indicated by entry's general
|
||||
* purpose flag).
|
||||
*
|
||||
* @throws ZipException if a ZIP format error has occurred
|
||||
* @throws IOException if an I/O error has occurred
|
||||
* @throws SecurityException
|
||||
* if a security manager exists and its <code>checkRead</code>
|
||||
* method doesn't allow read access to the file
|
||||
*
|
||||
* @see SecurityManager#checkRead(java.lang.String)
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
public ZipFile(String name, Charset charset) throws IOException
|
||||
{
|
||||
this(new File(name), OPEN_READ, charset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a ZIP file for reading given the specified File object.
|
||||
* @param file the ZIP file to be opened for reading
|
||||
* @throws ZipException if a ZIP error has occurred
|
||||
* @param charset
|
||||
* The {@link java.nio.charset.Charset {@code charset}} to be
|
||||
* used to decode the ZIP entry name and comment (ignored if
|
||||
* the <a href="package-summary.html#lang_encoding"> language
|
||||
* encoding bit</a> of the ZIP entry's general purpose bit
|
||||
* flag is set).
|
||||
*
|
||||
* @throws ZipException if a ZIP format error has occurred
|
||||
* @throws IOException if an I/O error has occurred
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
public ZipFile(File file) throws ZipException, IOException {
|
||||
this(file, OPEN_READ);
|
||||
public ZipFile(File file, Charset charset) throws IOException
|
||||
{
|
||||
this(file, OPEN_READ, charset);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -163,9 +261,9 @@ class ZipFile implements ZipConstants {
|
||||
long jzentry = 0;
|
||||
synchronized (this) {
|
||||
ensureOpen();
|
||||
jzentry = getEntry(jzfile, name, true);
|
||||
jzentry = getEntry(jzfile, zc.getBytes(name), true);
|
||||
if (jzentry != 0) {
|
||||
ZipEntry ze = new ZipEntry(name, jzentry);
|
||||
ZipEntry ze = getZipEntry(name, jzentry);
|
||||
freeEntry(jzfile, jzentry);
|
||||
return ze;
|
||||
}
|
||||
@ -173,7 +271,7 @@ class ZipFile implements ZipConstants {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static native long getEntry(long jzfile, String name,
|
||||
private static native long getEntry(long jzfile, byte[] name,
|
||||
boolean addSlash);
|
||||
|
||||
// freeEntry releases the C jzentry struct.
|
||||
@ -194,36 +292,30 @@ class ZipFile implements ZipConstants {
|
||||
* @throws IllegalStateException if the zip file has been closed
|
||||
*/
|
||||
public InputStream getInputStream(ZipEntry entry) throws IOException {
|
||||
return getInputStream(entry.name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an input stream for reading the contents of the specified
|
||||
* entry, or null if the entry was not found.
|
||||
*/
|
||||
private InputStream getInputStream(String name) throws IOException {
|
||||
if (name == null) {
|
||||
throw new NullPointerException("name");
|
||||
if (entry == null) {
|
||||
throw new NullPointerException("entry");
|
||||
}
|
||||
long jzentry = 0;
|
||||
ZipFileInputStream in = null;
|
||||
synchronized (this) {
|
||||
ensureOpen();
|
||||
jzentry = getEntry(jzfile, name, false);
|
||||
if (!zc.isUTF8() && (entry.flag & EFS) != 0) {
|
||||
jzentry = getEntry(jzfile, zc.getBytesUTF8(entry.name), false);
|
||||
} else {
|
||||
jzentry = getEntry(jzfile, zc.getBytes(entry.name), false);
|
||||
}
|
||||
if (jzentry == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
in = new ZipFileInputStream(jzentry);
|
||||
|
||||
}
|
||||
final ZipFileInputStream zfin = in;
|
||||
switch (getMethod(jzentry)) {
|
||||
switch (getEntryMethod(jzentry)) {
|
||||
case STORED:
|
||||
return zfin;
|
||||
case DEFLATED:
|
||||
// MORE: Compute good size for inflater stream:
|
||||
long size = getSize(jzentry) + 2; // Inflater likes a bit of slack
|
||||
long size = getEntrySize(jzentry) + 2; // Inflater likes a bit of slack
|
||||
if (size > 65536) size = 8192;
|
||||
if (size <= 0) size = 4096;
|
||||
return new InflaterInputStream(zfin, getInflater(), (int)size) {
|
||||
@ -267,8 +359,6 @@ class ZipFile implements ZipConstants {
|
||||
}
|
||||
}
|
||||
|
||||
private static native int getMethod(long jzentry);
|
||||
|
||||
/*
|
||||
* Gets an inflater from the list of available inflaters or allocates
|
||||
* a new one.
|
||||
@ -343,7 +433,7 @@ class ZipFile implements ZipConstants {
|
||||
",\n message = " + message
|
||||
);
|
||||
}
|
||||
ZipEntry ze = new ZipEntry(jzentry);
|
||||
ZipEntry ze = getZipEntry(null, jzentry);
|
||||
freeEntry(jzfile, jzentry);
|
||||
return ze;
|
||||
}
|
||||
@ -351,6 +441,38 @@ class ZipFile implements ZipConstants {
|
||||
};
|
||||
}
|
||||
|
||||
private ZipEntry getZipEntry(String name, long jzentry) {
|
||||
ZipEntry e = new ZipEntry();
|
||||
e.flag = getEntryFlag(jzentry); // get the flag first
|
||||
if (name != null) {
|
||||
e.name = name;
|
||||
} else {
|
||||
byte[] bname = getEntryBytes(jzentry, JZENTRY_NAME);
|
||||
if (!zc.isUTF8() && (e.flag & EFS) != 0) {
|
||||
e.name = zc.toStringUTF8(bname, bname.length);
|
||||
} else {
|
||||
e.name = zc.toString(bname, bname.length);
|
||||
}
|
||||
}
|
||||
e.time = getEntryTime(jzentry);
|
||||
e.crc = getEntryCrc(jzentry);
|
||||
e.size = getEntrySize(jzentry);
|
||||
e. csize = getEntryCSize(jzentry);
|
||||
e.method = getEntryMethod(jzentry);
|
||||
e.extra = getEntryBytes(jzentry, JZENTRY_EXTRA);
|
||||
byte[] bcomm = getEntryBytes(jzentry, JZENTRY_COMMENT);
|
||||
if (bcomm == null) {
|
||||
e.comment = null;
|
||||
} else {
|
||||
if (!zc.isUTF8() && (e.flag & EFS) != 0) {
|
||||
e.comment = zc.toStringUTF8(bcomm, bcomm.length);
|
||||
} else {
|
||||
e.comment = zc.toString(bcomm, bcomm.length);
|
||||
}
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
private static native long getNextEntry(long jzfile, int i);
|
||||
|
||||
/**
|
||||
@ -443,8 +565,8 @@ class ZipFile implements ZipConstants {
|
||||
|
||||
ZipFileInputStream(long jzentry) {
|
||||
pos = 0;
|
||||
rem = getCSize(jzentry);
|
||||
size = getSize(jzentry);
|
||||
rem = getEntryCSize(jzentry);
|
||||
size = getEntrySize(jzentry);
|
||||
this.jzentry = jzentry;
|
||||
}
|
||||
|
||||
@ -514,13 +636,25 @@ class ZipFile implements ZipConstants {
|
||||
|
||||
}
|
||||
|
||||
|
||||
private static native long open(String name, int mode, long lastModified)
|
||||
throws IOException;
|
||||
private static native int getTotal(long jzfile);
|
||||
private static native int read(long jzfile, long jzentry,
|
||||
long pos, byte[] b, int off, int len);
|
||||
|
||||
private static native long getCSize(long jzentry);
|
||||
// access to the native zentry object
|
||||
private static native long getEntryTime(long jzentry);
|
||||
private static native long getEntryCrc(long jzentry);
|
||||
private static native long getEntryCSize(long jzentry);
|
||||
private static native long getEntrySize(long jzentry);
|
||||
private static native int getEntryMethod(long jzentry);
|
||||
private static native int getEntryFlag(long jzentry);
|
||||
|
||||
private static native long getSize(long jzentry);
|
||||
private static final int JZENTRY_NAME = 0;
|
||||
private static final int JZENTRY_EXTRA = 1;
|
||||
private static final int JZENTRY_COMMENT = 2;
|
||||
private static native byte[] getEntryBytes(long jzentry, int type);
|
||||
|
||||
// Temporary add on for bug troubleshooting
|
||||
private static native String getZipMessage(long jzfile);
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.EOFException;
|
||||
import java.io.PushbackInputStream;
|
||||
import java.nio.charset.Charset;
|
||||
import static java.util.zip.ZipConstants64.*;
|
||||
|
||||
/**
|
||||
@ -54,6 +55,8 @@ class ZipInputStream extends InflaterInputStream implements ZipConstants {
|
||||
// one entry
|
||||
private boolean entryEOF = false;
|
||||
|
||||
private ZipCoder zc;
|
||||
|
||||
/**
|
||||
* Check to make sure that this stream has not been closed
|
||||
*/
|
||||
@ -65,14 +68,39 @@ class ZipInputStream extends InflaterInputStream implements ZipConstants {
|
||||
|
||||
/**
|
||||
* Creates a new ZIP input stream.
|
||||
*
|
||||
* <p>The UTF-8 {@link java.nio.charset.Charset charset} is used to
|
||||
* decode the entry names.
|
||||
*
|
||||
* @param in the actual input stream
|
||||
*/
|
||||
public ZipInputStream(InputStream in) {
|
||||
this(in, Charset.forName("UTF-8"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ZIP input stream.
|
||||
*
|
||||
* @param in the actual input stream
|
||||
*
|
||||
* @param charset
|
||||
* The {@link java.nio.charset.Charset {@code charset}} to be
|
||||
* used to decode the ZIP entry name (ignored if the
|
||||
* <a href="package-summary.html#lang_encoding"> language
|
||||
* encoding bit</a> of the ZIP entry's general purpose bit
|
||||
* flag is set).
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
public ZipInputStream(InputStream in, Charset charset) {
|
||||
super(new PushbackInputStream(in, 512), new Inflater(true), 512);
|
||||
usesDefaultInflater = true;
|
||||
if(in == null) {
|
||||
throw new NullPointerException("in is null");
|
||||
}
|
||||
if (charset == null)
|
||||
throw new NullPointerException("charset is null");
|
||||
this.zc = ZipCoder.get(charset);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -141,8 +169,8 @@ class ZipInputStream extends InflaterInputStream implements ZipConstants {
|
||||
* @param len the maximum number of bytes read
|
||||
* @return the actual number of bytes read, or -1 if the end of the
|
||||
* entry is reached
|
||||
* @exception NullPointerException If <code>b</code> is <code>null</code>.
|
||||
* @exception IndexOutOfBoundsException If <code>off</code> is negative,
|
||||
* @exception NullPointerException if <code>b</code> is <code>null</code>.
|
||||
* @exception IndexOutOfBoundsException if <code>off</code> is negative,
|
||||
* <code>len</code> is negative, or <code>len</code> is greater than
|
||||
* <code>b.length - off</code>
|
||||
* @exception ZipException if a ZIP file error has occurred
|
||||
@ -252,6 +280,8 @@ class ZipInputStream extends InflaterInputStream implements ZipConstants {
|
||||
if (get32(tmpbuf, 0) != LOCSIG) {
|
||||
return null;
|
||||
}
|
||||
// get flag first, we need check EFS.
|
||||
flag = get16(tmpbuf, LOCFLG);
|
||||
// get the entry name and create the ZipEntry first
|
||||
int len = get16(tmpbuf, LOCNAM);
|
||||
int blen = b.length;
|
||||
@ -262,9 +292,11 @@ class ZipInputStream extends InflaterInputStream implements ZipConstants {
|
||||
b = new byte[blen];
|
||||
}
|
||||
readFully(b, 0, len);
|
||||
ZipEntry e = createZipEntry(getUTF8String(b, 0, len));
|
||||
// Force to use UTF-8 if the EFS bit is ON, even the cs is NOT UTF-8
|
||||
ZipEntry e = createZipEntry(((flag & EFS) != 0)
|
||||
? zc.toStringUTF8(b, len)
|
||||
: zc.toString(b, len));
|
||||
// now get the remaining fields for the entry
|
||||
flag = get16(tmpbuf, LOCFLG);
|
||||
if ((flag & 1) == 1) {
|
||||
throw new ZipException("encrypted ZIP entry not supported");
|
||||
}
|
||||
@ -313,71 +345,6 @@ class ZipInputStream extends InflaterInputStream implements ZipConstants {
|
||||
return e;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fetches a UTF8-encoded String from the specified byte array.
|
||||
*/
|
||||
private static String getUTF8String(byte[] b, int off, int len) {
|
||||
// First, count the number of characters in the sequence
|
||||
int count = 0;
|
||||
int max = off + len;
|
||||
int i = off;
|
||||
while (i < max) {
|
||||
int c = b[i++] & 0xff;
|
||||
switch (c >> 4) {
|
||||
case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
|
||||
// 0xxxxxxx
|
||||
count++;
|
||||
break;
|
||||
case 12: case 13:
|
||||
// 110xxxxx 10xxxxxx
|
||||
if ((b[i++] & 0xc0) != 0x80) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
count++;
|
||||
break;
|
||||
case 14:
|
||||
// 1110xxxx 10xxxxxx 10xxxxxx
|
||||
if (((b[i++] & 0xc0) != 0x80) ||
|
||||
((b[i++] & 0xc0) != 0x80)) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
count++;
|
||||
break;
|
||||
default:
|
||||
// 10xxxxxx, 1111xxxx
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
if (i != max) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
// Now decode the characters...
|
||||
char[] cs = new char[count];
|
||||
i = 0;
|
||||
while (off < max) {
|
||||
int c = b[off++] & 0xff;
|
||||
switch (c >> 4) {
|
||||
case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
|
||||
// 0xxxxxxx
|
||||
cs[i++] = (char)c;
|
||||
break;
|
||||
case 12: case 13:
|
||||
// 110xxxxx 10xxxxxx
|
||||
cs[i++] = (char)(((c & 0x1f) << 6) | (b[off++] & 0x3f));
|
||||
break;
|
||||
case 14:
|
||||
// 1110xxxx 10xxxxxx 10xxxxxx
|
||||
int t = (b[off++] & 0x3f) << 6;
|
||||
cs[i++] = (char)(((c & 0x0f) << 12) | t | (b[off++] & 0x3f));
|
||||
break;
|
||||
default:
|
||||
// 10xxxxxx, 1111xxxx
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
return new String(cs, 0, count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new <code>ZipEntry</code> object for the specified
|
||||
* entry name.
|
||||
|
@ -27,6 +27,7 @@ package java.util.zip;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Vector;
|
||||
import java.util.HashSet;
|
||||
import static java.util.zip.ZipConstants64.*;
|
||||
@ -44,19 +45,9 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
|
||||
private static class XEntry {
|
||||
public final ZipEntry entry;
|
||||
public final long offset;
|
||||
public final int flag;
|
||||
public XEntry(ZipEntry entry, long offset) {
|
||||
this.entry = entry;
|
||||
this.offset = offset;
|
||||
this.flag = (entry.method == DEFLATED &&
|
||||
(entry.size == -1 ||
|
||||
entry.csize == -1 ||
|
||||
entry.crc == -1))
|
||||
// store size, compressed size, and crc-32 in data descriptor
|
||||
// immediately following the compressed entry data
|
||||
? 8
|
||||
// store size, compressed size, and crc-32 in LOC header
|
||||
: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,12 +57,14 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
|
||||
private CRC32 crc = new CRC32();
|
||||
private long written = 0;
|
||||
private long locoff = 0;
|
||||
private String comment;
|
||||
private byte[] comment;
|
||||
private int method = DEFLATED;
|
||||
private boolean finished;
|
||||
|
||||
private boolean closed = false;
|
||||
|
||||
private final ZipCoder zc;
|
||||
|
||||
private static int version(ZipEntry e) throws ZipException {
|
||||
switch (e.method) {
|
||||
case DEFLATED: return 20;
|
||||
@ -100,10 +93,31 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
|
||||
|
||||
/**
|
||||
* Creates a new ZIP output stream.
|
||||
*
|
||||
* <p>The UTF-8 {@link java.nio.charset.Charset charset} is used
|
||||
* to encode the entry names and comments.
|
||||
*
|
||||
* @param out the actual output stream
|
||||
*/
|
||||
public ZipOutputStream(OutputStream out) {
|
||||
this(out, Charset.forName("UTF-8"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ZIP output stream.
|
||||
*
|
||||
* @param out the actual output stream
|
||||
*
|
||||
* @param charset the {@link java.nio.charset.Charset </code>charset<code>}
|
||||
* to be used to encode the entry names and comments
|
||||
*
|
||||
* @since 1.7
|
||||
*/
|
||||
public ZipOutputStream(OutputStream out, Charset charset) {
|
||||
super(out, new Deflater(Deflater.DEFAULT_COMPRESSION, true));
|
||||
if (charset == null)
|
||||
throw new NullPointerException("charset is null");
|
||||
this.zc = ZipCoder.get(charset);
|
||||
usesDefaultDeflater = true;
|
||||
}
|
||||
|
||||
@ -114,11 +128,11 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
|
||||
* ZIP file comment is greater than 0xFFFF bytes
|
||||
*/
|
||||
public void setComment(String comment) {
|
||||
if (comment != null && comment.length() > 0xffff/3
|
||||
&& getUTF8Length(comment) > 0xffff) {
|
||||
throw new IllegalArgumentException("ZIP file comment too long.");
|
||||
if (comment != null) {
|
||||
this.comment = zc.getBytes(comment);
|
||||
if (this.comment.length > 0xffff)
|
||||
throw new IllegalArgumentException("ZIP file comment too long.");
|
||||
}
|
||||
this.comment = comment;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -167,8 +181,15 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
|
||||
if (e.method == -1) {
|
||||
e.method = method; // use default method
|
||||
}
|
||||
// store size, compressed size, and crc-32 in LOC header
|
||||
e.flag = 0;
|
||||
switch (e.method) {
|
||||
case DEFLATED:
|
||||
// store size, compressed size, and crc-32 in data descriptor
|
||||
// immediately following the compressed entry data
|
||||
if (e.size == -1 || e.csize == -1 || e.crc == -1)
|
||||
e.flag = 8;
|
||||
|
||||
break;
|
||||
case STORED:
|
||||
// compressed size, uncompressed size, and crc-32 must all be
|
||||
@ -192,6 +213,8 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
|
||||
if (! names.add(e.name)) {
|
||||
throw new ZipException("duplicate entry: " + e.name);
|
||||
}
|
||||
if (zc.isUTF8())
|
||||
e.flag |= EFS;
|
||||
current = new XEntry(e, written);
|
||||
xentries.add(current);
|
||||
writeLOC(current);
|
||||
@ -213,7 +236,7 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
|
||||
while (!def.finished()) {
|
||||
deflate();
|
||||
}
|
||||
if ((current.flag & 8) == 0) {
|
||||
if ((e.flag & 8) == 0) {
|
||||
// verify size, compressed size, and crc-32 settings
|
||||
if (e.size != def.getBytesRead()) {
|
||||
throw new ZipException(
|
||||
@ -343,11 +366,11 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
|
||||
*/
|
||||
private void writeLOC(XEntry xentry) throws IOException {
|
||||
ZipEntry e = xentry.entry;
|
||||
int flag = xentry.flag;
|
||||
int flag = e.flag;
|
||||
int elen = (e.extra != null) ? e.extra.length : 0;
|
||||
boolean hasZip64 = false;
|
||||
|
||||
writeInt(LOCSIG); // LOC header signature
|
||||
writeInt(LOCSIG); // LOC header signature
|
||||
|
||||
if ((flag & 8) == 8) {
|
||||
writeShort(version(e)); // version needed to extract
|
||||
@ -380,7 +403,7 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
|
||||
writeInt(e.size); // uncompressed size
|
||||
}
|
||||
}
|
||||
byte[] nameBytes = getUTF8Bytes(e.name);
|
||||
byte[] nameBytes = zc.getBytes(e.name);
|
||||
writeShort(nameBytes.length);
|
||||
writeShort(elen);
|
||||
writeBytes(nameBytes, 0, nameBytes.length);
|
||||
@ -417,7 +440,7 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
|
||||
*/
|
||||
private void writeCEN(XEntry xentry) throws IOException {
|
||||
ZipEntry e = xentry.entry;
|
||||
int flag = xentry.flag;
|
||||
int flag = e.flag;
|
||||
int version = version(e);
|
||||
|
||||
long csize = e.csize;
|
||||
@ -454,7 +477,7 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
|
||||
writeInt(e.crc); // crc-32
|
||||
writeInt(csize); // compressed size
|
||||
writeInt(size); // uncompressed size
|
||||
byte[] nameBytes = getUTF8Bytes(e.name);
|
||||
byte[] nameBytes = zc.getBytes(e.name);
|
||||
writeShort(nameBytes.length);
|
||||
if (hasZip64) {
|
||||
// + headid(2) + datasize(2)
|
||||
@ -464,8 +487,8 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
|
||||
}
|
||||
byte[] commentBytes;
|
||||
if (e.comment != null) {
|
||||
commentBytes = getUTF8Bytes(e.comment);
|
||||
writeShort(commentBytes.length);
|
||||
commentBytes = zc.getBytes(e.comment);
|
||||
writeShort(Math.min(commentBytes.length, 0xffff));
|
||||
} else {
|
||||
commentBytes = null;
|
||||
writeShort(0);
|
||||
@ -489,7 +512,7 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
|
||||
writeBytes(e.extra, 0, e.extra.length);
|
||||
}
|
||||
if (commentBytes != null) {
|
||||
writeBytes(commentBytes, 0, commentBytes.length);
|
||||
writeBytes(commentBytes, 0, Math.min(commentBytes.length, 0xffff));
|
||||
}
|
||||
}
|
||||
|
||||
@ -541,9 +564,8 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
|
||||
writeInt(xlen); // length of central directory
|
||||
writeInt(xoff); // offset of central directory
|
||||
if (comment != null) { // zip file comment
|
||||
byte[] b = getUTF8Bytes(comment);
|
||||
writeShort(b.length);
|
||||
writeBytes(b, 0, b.length);
|
||||
writeShort(comment.length);
|
||||
writeBytes(comment, 0, comment.length);
|
||||
} else {
|
||||
writeShort(0);
|
||||
}
|
||||
@ -594,60 +616,4 @@ class ZipOutputStream extends DeflaterOutputStream implements ZipConstants {
|
||||
super.out.write(b, off, len);
|
||||
written += len;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the length of String's UTF8 encoding.
|
||||
*/
|
||||
static int getUTF8Length(String s) {
|
||||
int count = 0;
|
||||
for (int i = 0; i < s.length(); i++) {
|
||||
char ch = s.charAt(i);
|
||||
if (ch <= 0x7f) {
|
||||
count++;
|
||||
} else if (ch <= 0x7ff) {
|
||||
count += 2;
|
||||
} else {
|
||||
count += 3;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns an array of bytes representing the UTF8 encoding
|
||||
* of the specified String.
|
||||
*/
|
||||
private static byte[] getUTF8Bytes(String s) {
|
||||
char[] c = s.toCharArray();
|
||||
int len = c.length;
|
||||
// Count the number of encoded bytes...
|
||||
int count = 0;
|
||||
for (int i = 0; i < len; i++) {
|
||||
int ch = c[i];
|
||||
if (ch <= 0x7f) {
|
||||
count++;
|
||||
} else if (ch <= 0x7ff) {
|
||||
count += 2;
|
||||
} else {
|
||||
count += 3;
|
||||
}
|
||||
}
|
||||
// Now return the encoded bytes...
|
||||
byte[] b = new byte[count];
|
||||
int off = 0;
|
||||
for (int i = 0; i < len; i++) {
|
||||
int ch = c[i];
|
||||
if (ch <= 0x7f) {
|
||||
b[off++] = (byte)ch;
|
||||
} else if (ch <= 0x7ff) {
|
||||
b[off++] = (byte)((ch >> 6) | 0xc0);
|
||||
b[off++] = (byte)((ch & 0x3f) | 0x80);
|
||||
} else {
|
||||
b[off++] = (byte)((ch >> 12) | 0xe0);
|
||||
b[off++] = (byte)(((ch >> 6) & 0x3f) | 0x80);
|
||||
b[off++] = (byte)((ch & 0x3f) | 0x80);
|
||||
}
|
||||
}
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
@ -52,6 +52,11 @@ input streams.
|
||||
<a href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">
|
||||
PKWARE ZIP File Format Specification</a>. The ZIP64(tm) format extensions
|
||||
are used to overcome the size limitations of the original ZIP format.
|
||||
<p>
|
||||
<a name="lang_encoding">
|
||||
<li>APPENDIX D of <a href="http://www.pkware.com/documents/casestudies/APPNOTE.TXT">
|
||||
PKWARE ZIP File Format Specification</a> - Language Encoding Flag (EFS) to
|
||||
encode ZIP entry filename and comment fields using UTF-8.
|
||||
<p>
|
||||
<li><a href="http://www.isi.edu/in-notes/rfc1950.txt">
|
||||
ZLIB Compressed Data Format Specification version 3.3</a>
|
||||
|
@ -1,105 +0,0 @@
|
||||
/*
|
||||
* Copyright 1998 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Sun designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Sun in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Native method support for java.util.zip.ZipEntry
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "jlong.h"
|
||||
#include "jvm.h"
|
||||
#include "jni.h"
|
||||
#include "jni_util.h"
|
||||
#include "zip_util.h"
|
||||
|
||||
#include "java_util_zip_ZipEntry.h"
|
||||
|
||||
#define DEFLATED 8
|
||||
#define STORED 0
|
||||
|
||||
static jfieldID nameID;
|
||||
static jfieldID timeID;
|
||||
static jfieldID crcID;
|
||||
static jfieldID sizeID;
|
||||
static jfieldID csizeID;
|
||||
static jfieldID methodID;
|
||||
static jfieldID extraID;
|
||||
static jfieldID commentID;
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_util_zip_ZipEntry_initIDs(JNIEnv *env, jclass cls)
|
||||
{
|
||||
nameID = (*env)->GetFieldID(env, cls, "name", "Ljava/lang/String;");
|
||||
timeID = (*env)->GetFieldID(env, cls, "time", "J");
|
||||
crcID = (*env)->GetFieldID(env, cls, "crc", "J");
|
||||
sizeID = (*env)->GetFieldID(env, cls, "size", "J");
|
||||
csizeID = (*env)->GetFieldID(env, cls, "csize", "J");
|
||||
methodID = (*env)->GetFieldID(env, cls, "method", "I");
|
||||
extraID = (*env)->GetFieldID(env, cls, "extra", "[B");
|
||||
commentID = (*env)->GetFieldID(env, cls, "comment", "Ljava/lang/String;");
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_util_zip_ZipEntry_initFields(JNIEnv *env, jobject obj, jlong zentry)
|
||||
{
|
||||
jzentry *ze = jlong_to_ptr(zentry);
|
||||
jstring name = (*env)->GetObjectField(env, obj, nameID);
|
||||
|
||||
if (name == 0) {
|
||||
name = (*env)->NewStringUTF(env, ze->name);
|
||||
if (name == 0) {
|
||||
return;
|
||||
}
|
||||
(*env)->SetObjectField(env, obj, nameID, name);
|
||||
}
|
||||
(*env)->SetLongField(env, obj, timeID, (jlong)ze->time & 0xffffffffUL);
|
||||
(*env)->SetLongField(env, obj, crcID, (jlong)ze->crc & 0xffffffffUL);
|
||||
(*env)->SetLongField(env, obj, sizeID, (jlong)ze->size);
|
||||
if (ze->csize == 0) {
|
||||
(*env)->SetLongField(env, obj, csizeID, (jlong)ze->size);
|
||||
(*env)->SetIntField(env, obj, methodID, STORED);
|
||||
} else {
|
||||
(*env)->SetLongField(env, obj, csizeID, (jlong)ze->csize);
|
||||
(*env)->SetIntField(env, obj, methodID, DEFLATED);
|
||||
}
|
||||
if (ze->extra != 0) {
|
||||
unsigned char *bp = (unsigned char *)&ze->extra[0];
|
||||
jsize len = (bp[0] | (bp[1] << 8));
|
||||
jbyteArray extra = (*env)->NewByteArray(env, len);
|
||||
if (extra == 0) {
|
||||
return;
|
||||
}
|
||||
(*env)->SetByteArrayRegion(env, extra, 0, len, &ze->extra[2]);
|
||||
(*env)->SetObjectField(env, obj, extraID, extra);
|
||||
}
|
||||
if (ze->comment != 0) {
|
||||
jstring comment = (*env)->NewStringUTF(env, ze->comment);
|
||||
if (comment == 0) {
|
||||
return;
|
||||
}
|
||||
(*env)->SetObjectField(env, obj, commentID, comment);
|
||||
}
|
||||
}
|
@ -141,12 +141,11 @@ Java_java_util_zip_ZipFile_close(JNIEnv *env, jclass cls, jlong zfile)
|
||||
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_java_util_zip_ZipFile_getEntry(JNIEnv *env, jclass cls, jlong zfile,
|
||||
jstring name, jboolean addSlash)
|
||||
jbyteArray name, jboolean addSlash)
|
||||
{
|
||||
#define MAXNAME 1024
|
||||
jzfile *zip = jlong_to_ptr(zfile);
|
||||
jsize slen = (*env)->GetStringLength(env, name);
|
||||
jsize ulen = (*env)->GetStringUTFLength(env, name);
|
||||
jsize ulen = (*env)->GetArrayLength(env, name);
|
||||
char buf[MAXNAME+2], *path;
|
||||
jzentry *ze;
|
||||
|
||||
@ -159,7 +158,7 @@ Java_java_util_zip_ZipFile_getEntry(JNIEnv *env, jclass cls, jlong zfile,
|
||||
} else {
|
||||
path = buf;
|
||||
}
|
||||
(*env)->GetStringUTFRegion(env, name, 0, slen, path);
|
||||
(*env)->GetByteArrayRegion(env, name, 0, ulen, (jbyte *)path);
|
||||
path[ulen] = '\0';
|
||||
if (addSlash == JNI_FALSE) {
|
||||
ze = ZIP_GetEntry(zip, path, 0);
|
||||
@ -186,34 +185,87 @@ Java_java_util_zip_ZipFile_getNextEntry(JNIEnv *env, jclass cls, jlong zfile,
|
||||
jint n)
|
||||
{
|
||||
jzentry *ze = ZIP_GetNextEntry(jlong_to_ptr(zfile), n);
|
||||
|
||||
return ptr_to_jlong(ze);
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_java_util_zip_ZipFile_getMethod(JNIEnv *env, jclass cls, jlong zentry)
|
||||
Java_java_util_zip_ZipFile_getEntryMethod(JNIEnv *env, jclass cls, jlong zentry)
|
||||
{
|
||||
jzentry *ze = jlong_to_ptr(zentry);
|
||||
|
||||
return ze->csize != 0 ? DEFLATED : STORED;
|
||||
}
|
||||
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_java_util_zip_ZipFile_getCSize(JNIEnv *env, jclass cls, jlong zentry)
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_java_util_zip_ZipFile_getEntryFlag(JNIEnv *env, jclass cls, jlong zentry)
|
||||
{
|
||||
jzentry *ze = jlong_to_ptr(zentry);
|
||||
return ze->flag;
|
||||
}
|
||||
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_java_util_zip_ZipFile_getEntryCSize(JNIEnv *env, jclass cls, jlong zentry)
|
||||
{
|
||||
jzentry *ze = jlong_to_ptr(zentry);
|
||||
return ze->csize != 0 ? ze->csize : ze->size;
|
||||
}
|
||||
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_java_util_zip_ZipFile_getSize(JNIEnv *env, jclass cls, jlong zentry)
|
||||
Java_java_util_zip_ZipFile_getEntrySize(JNIEnv *env, jclass cls, jlong zentry)
|
||||
{
|
||||
jzentry *ze = jlong_to_ptr(zentry);
|
||||
|
||||
return ze->size;
|
||||
}
|
||||
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_java_util_zip_ZipFile_getEntryTime(JNIEnv *env, jclass cls, jlong zentry)
|
||||
{
|
||||
jzentry *ze = jlong_to_ptr(zentry);
|
||||
return (jlong)ze->time & 0xffffffffUL;
|
||||
}
|
||||
|
||||
JNIEXPORT jlong JNICALL
|
||||
Java_java_util_zip_ZipFile_getEntryCrc(JNIEnv *env, jclass cls, jlong zentry)
|
||||
{
|
||||
jzentry *ze = jlong_to_ptr(zentry);
|
||||
return (jlong)ze->crc & 0xffffffffUL;
|
||||
}
|
||||
|
||||
JNIEXPORT jbyteArray JNICALL
|
||||
Java_java_util_zip_ZipFile_getEntryBytes(JNIEnv *env, jclass cls, jlong zentry, jint type)
|
||||
{
|
||||
jzentry *ze = jlong_to_ptr(zentry);
|
||||
int len = 0;
|
||||
jbyteArray jba = NULL;
|
||||
switch (type) {
|
||||
case java_util_zip_ZipFile_JZENTRY_NAME:
|
||||
if (ze->name != 0) {
|
||||
len = (int)strlen(ze->name);
|
||||
if (len == 0 || (jba = (*env)->NewByteArray(env, len)) == NULL)
|
||||
break;
|
||||
(*env)->SetByteArrayRegion(env, jba, 0, len, (jbyte *)ze->name);
|
||||
}
|
||||
break;
|
||||
case java_util_zip_ZipFile_JZENTRY_EXTRA:
|
||||
if (ze->extra != 0) {
|
||||
unsigned char *bp = (unsigned char *)&ze->extra[0];
|
||||
len = (bp[0] | (bp[1] << 8));
|
||||
if (len <= 0 || (jba = (*env)->NewByteArray(env, len)) == NULL)
|
||||
break;
|
||||
(*env)->SetByteArrayRegion(env, jba, 0, len, &ze->extra[2]);
|
||||
}
|
||||
break;
|
||||
case java_util_zip_ZipFile_JZENTRY_COMMENT:
|
||||
if (ze->comment != 0) {
|
||||
len = (int)strlen(ze->comment);
|
||||
if (len == 0 || (jba = (*env)->NewByteArray(env, len)) == NULL)
|
||||
break;
|
||||
(*env)->SetByteArrayRegion(env, jba, 0, len, (jbyte*)ze->comment);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return jba;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_java_util_zip_ZipFile_read(JNIEnv *env, jclass cls, jlong zfile,
|
||||
jlong zentry, jlong pos, jbyteArray bytes,
|
||||
|
@ -512,7 +512,6 @@ readCEN(jzfile *zip, jint knownTotal)
|
||||
|
||||
/* Clear previous zip error */
|
||||
zip->msg = NULL;
|
||||
|
||||
/* Get position of END header */
|
||||
if ((endpos = findEND(zip, endbuf)) == -1)
|
||||
return -1; /* no END header or system error */
|
||||
@ -520,7 +519,6 @@ readCEN(jzfile *zip, jint knownTotal)
|
||||
if (endpos == 0) return 0; /* only END header present */
|
||||
|
||||
freeCEN(zip);
|
||||
|
||||
/* Get position and length of central directory */
|
||||
cenlen = ENDSIZ(endbuf);
|
||||
cenoff = ENDOFF(endbuf);
|
||||
@ -935,6 +933,7 @@ newEntry(jzfile *zip, jzcell *zc, AccessHint accessHint)
|
||||
ze->crc = CENCRC(cen);
|
||||
locoff = CENOFF(cen);
|
||||
ze->pos = -(zip->locpos + locoff);
|
||||
ze->flag = CENFLG(cen);
|
||||
|
||||
if ((ze->name = malloc(nlen + 1)) == NULL) goto Catch;
|
||||
memcpy(ze->name, cen + CENHDR, nlen);
|
||||
|
@ -168,6 +168,7 @@ typedef struct jzentry { /* Zip file entry */
|
||||
char *comment; /* optional zip file comment */
|
||||
jbyte *extra; /* optional extra data */
|
||||
jlong pos; /* position of LOC header or entry data */
|
||||
jint flag; /* general purpose flag */
|
||||
} jzentry;
|
||||
|
||||
/*
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Portions Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* Portions Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -73,7 +73,7 @@ jmethodID setRealmMethod = 0;
|
||||
* Function prototypes for internal routines
|
||||
*
|
||||
*/
|
||||
BOOL DEBUG = 0;
|
||||
BOOL native_debug = 0;
|
||||
|
||||
BOOL PackageConnectLookup(PHANDLE,PULONG);
|
||||
|
||||
@ -130,7 +130,7 @@ JNIEXPORT jint JNICALL JNI_OnLoad(
|
||||
printf("LSA: Krb5 has no DEBUG field\n");
|
||||
return JNI_ERR;
|
||||
}
|
||||
DEBUG = (*env)->GetStaticBooleanField(env, cls, fldDEBUG);
|
||||
native_debug = (*env)->GetStaticBooleanField(env, cls, fldDEBUG);
|
||||
|
||||
cls = (*env)->FindClass(env,"sun/security/krb5/internal/Ticket");
|
||||
|
||||
@ -138,17 +138,17 @@ JNIEXPORT jint JNICALL JNI_OnLoad(
|
||||
printf("LSA: Couldn't find Ticket\n");
|
||||
return JNI_ERR;
|
||||
}
|
||||
if (DEBUG) {
|
||||
if (native_debug) {
|
||||
printf("LSA: Found Ticket\n");
|
||||
} /* DEBUG */
|
||||
}
|
||||
|
||||
ticketClass = (*env)->NewWeakGlobalRef(env,cls);
|
||||
if (ticketClass == NULL) {
|
||||
return JNI_ERR;
|
||||
}
|
||||
if (DEBUG) {
|
||||
if (native_debug) {
|
||||
printf("LSA: Made NewWeakGlobalRef\n");
|
||||
} /* DEBUG */
|
||||
}
|
||||
|
||||
cls = (*env)->FindClass(env, "sun/security/krb5/PrincipalName");
|
||||
|
||||
@ -156,17 +156,17 @@ JNIEXPORT jint JNICALL JNI_OnLoad(
|
||||
printf("LSA: Couldn't find PrincipalName\n");
|
||||
return JNI_ERR;
|
||||
}
|
||||
if (DEBUG) {
|
||||
if (native_debug) {
|
||||
printf("LSA: Found PrincipalName\n");
|
||||
} /* DEBUG */
|
||||
}
|
||||
|
||||
principalNameClass = (*env)->NewWeakGlobalRef(env,cls);
|
||||
if (principalNameClass == NULL) {
|
||||
return JNI_ERR;
|
||||
}
|
||||
if (DEBUG) {
|
||||
if (native_debug) {
|
||||
printf("LSA: Made NewWeakGlobalRef\n");
|
||||
} /* DEBUG */
|
||||
}
|
||||
|
||||
cls = (*env)->FindClass(env,"sun/security/util/DerValue");
|
||||
|
||||
@ -174,17 +174,17 @@ JNIEXPORT jint JNICALL JNI_OnLoad(
|
||||
printf("LSA: Couldn't find DerValue\n");
|
||||
return JNI_ERR;
|
||||
}
|
||||
if (DEBUG) {
|
||||
if (native_debug) {
|
||||
printf("LSA: Found DerValue\n");
|
||||
} /* DEBUG */
|
||||
}
|
||||
|
||||
derValueClass = (*env)->NewWeakGlobalRef(env,cls);
|
||||
if (derValueClass == NULL) {
|
||||
return JNI_ERR;
|
||||
}
|
||||
if (DEBUG) {
|
||||
if (native_debug) {
|
||||
printf("LSA: Made NewWeakGlobalRef\n");
|
||||
} /* DEBUG */
|
||||
}
|
||||
|
||||
cls = (*env)->FindClass(env,"sun/security/krb5/EncryptionKey");
|
||||
|
||||
@ -192,17 +192,17 @@ JNIEXPORT jint JNICALL JNI_OnLoad(
|
||||
printf("LSA: Couldn't find EncryptionKey\n");
|
||||
return JNI_ERR;
|
||||
}
|
||||
if (DEBUG) {
|
||||
if (native_debug) {
|
||||
printf("LSA: Found EncryptionKey\n");
|
||||
} /* DEBUG */
|
||||
}
|
||||
|
||||
encryptionKeyClass = (*env)->NewWeakGlobalRef(env,cls);
|
||||
if (encryptionKeyClass == NULL) {
|
||||
return JNI_ERR;
|
||||
}
|
||||
if (DEBUG) {
|
||||
if (native_debug) {
|
||||
printf("LSA: Made NewWeakGlobalRef\n");
|
||||
} /* DEBUG */
|
||||
}
|
||||
|
||||
cls = (*env)->FindClass(env,"sun/security/krb5/internal/TicketFlags");
|
||||
|
||||
@ -210,17 +210,17 @@ JNIEXPORT jint JNICALL JNI_OnLoad(
|
||||
printf("LSA: Couldn't find TicketFlags\n");
|
||||
return JNI_ERR;
|
||||
}
|
||||
if (DEBUG) {
|
||||
if (native_debug) {
|
||||
printf("LSA: Found TicketFlags\n");
|
||||
} /* DEBUG */
|
||||
}
|
||||
|
||||
ticketFlagsClass = (*env)->NewWeakGlobalRef(env,cls);
|
||||
if (ticketFlagsClass == NULL) {
|
||||
return JNI_ERR;
|
||||
}
|
||||
if (DEBUG) {
|
||||
if (native_debug) {
|
||||
printf("LSA: Made NewWeakGlobalRef\n");
|
||||
} /* DEBUG */
|
||||
}
|
||||
|
||||
cls = (*env)->FindClass(env,"sun/security/krb5/internal/KerberosTime");
|
||||
|
||||
@ -228,17 +228,17 @@ JNIEXPORT jint JNICALL JNI_OnLoad(
|
||||
printf("LSA: Couldn't find KerberosTime\n");
|
||||
return JNI_ERR;
|
||||
}
|
||||
if (DEBUG) {
|
||||
if (native_debug) {
|
||||
printf("LSA: Found KerberosTime\n");
|
||||
} /* DEBUG */
|
||||
}
|
||||
|
||||
kerberosTimeClass = (*env)->NewWeakGlobalRef(env,cls);
|
||||
if (kerberosTimeClass == NULL) {
|
||||
return JNI_ERR;
|
||||
}
|
||||
if (DEBUG) {
|
||||
if (native_debug) {
|
||||
printf("LSA: Made NewWeakGlobalRef\n");
|
||||
} /* DEBUG */
|
||||
}
|
||||
|
||||
cls = (*env)->FindClass(env,"java/lang/String");
|
||||
|
||||
@ -246,17 +246,17 @@ JNIEXPORT jint JNICALL JNI_OnLoad(
|
||||
printf("LSA: Couldn't find String\n");
|
||||
return JNI_ERR;
|
||||
}
|
||||
if (DEBUG) {
|
||||
if (native_debug) {
|
||||
printf("LSA: Found String\n");
|
||||
} /* DEBUG */
|
||||
}
|
||||
|
||||
javaLangStringClass = (*env)->NewWeakGlobalRef(env,cls);
|
||||
if (javaLangStringClass == NULL) {
|
||||
return JNI_ERR;
|
||||
}
|
||||
if (DEBUG) {
|
||||
if (native_debug) {
|
||||
printf("LSA: Made NewWeakGlobalRef\n");
|
||||
} /* DEBUG */
|
||||
}
|
||||
|
||||
derValueConstructor = (*env)->GetMethodID(env, derValueClass,
|
||||
"<init>", "([B)V");
|
||||
@ -264,9 +264,9 @@ JNIEXPORT jint JNICALL JNI_OnLoad(
|
||||
printf("LSA: Couldn't find DerValue constructor\n");
|
||||
return JNI_ERR;
|
||||
}
|
||||
if (DEBUG) {
|
||||
if (native_debug) {
|
||||
printf("LSA: Found DerValue constructor\n");
|
||||
} /* DEBUG */
|
||||
}
|
||||
|
||||
ticketConstructor = (*env)->GetMethodID(env, ticketClass,
|
||||
"<init>", "(Lsun/security/util/DerValue;)V");
|
||||
@ -274,9 +274,9 @@ JNIEXPORT jint JNICALL JNI_OnLoad(
|
||||
printf("LSA: Couldn't find Ticket constructor\n");
|
||||
return JNI_ERR;
|
||||
}
|
||||
if (DEBUG) {
|
||||
if (native_debug) {
|
||||
printf("LSA: Found Ticket constructor\n");
|
||||
} /* DEBUG */
|
||||
}
|
||||
|
||||
principalNameConstructor = (*env)->GetMethodID(env, principalNameClass,
|
||||
"<init>", "([Ljava/lang/String;)V");
|
||||
@ -284,9 +284,9 @@ JNIEXPORT jint JNICALL JNI_OnLoad(
|
||||
printf("LSA: Couldn't find PrincipalName constructor\n");
|
||||
return JNI_ERR;
|
||||
}
|
||||
if (DEBUG) {
|
||||
if (native_debug) {
|
||||
printf("LSA: Found PrincipalName constructor\n");
|
||||
} /* DEBUG */
|
||||
}
|
||||
|
||||
encryptionKeyConstructor = (*env)->GetMethodID(env, encryptionKeyClass,
|
||||
"<init>", "(I[B)V");
|
||||
@ -294,9 +294,9 @@ JNIEXPORT jint JNICALL JNI_OnLoad(
|
||||
printf("LSA: Couldn't find EncryptionKey constructor\n");
|
||||
return JNI_ERR;
|
||||
}
|
||||
if (DEBUG) {
|
||||
if (native_debug) {
|
||||
printf("LSA: Found EncryptionKey constructor\n");
|
||||
} /* DEBUG */
|
||||
}
|
||||
|
||||
ticketFlagsConstructor = (*env)->GetMethodID(env, ticketFlagsClass,
|
||||
"<init>", "(I[B)V");
|
||||
@ -304,9 +304,9 @@ JNIEXPORT jint JNICALL JNI_OnLoad(
|
||||
printf("LSA: Couldn't find TicketFlags constructor\n");
|
||||
return JNI_ERR;
|
||||
}
|
||||
if (DEBUG) {
|
||||
if (native_debug) {
|
||||
printf("LSA: Found TicketFlags constructor\n");
|
||||
} /* DEBUG */
|
||||
}
|
||||
|
||||
kerberosTimeConstructor = (*env)->GetMethodID(env, kerberosTimeClass,
|
||||
"<init>", "(Ljava/lang/String;)V");
|
||||
@ -314,9 +314,9 @@ JNIEXPORT jint JNICALL JNI_OnLoad(
|
||||
printf("LSA: Couldn't find KerberosTime constructor\n");
|
||||
return JNI_ERR;
|
||||
}
|
||||
if (DEBUG) {
|
||||
if (native_debug) {
|
||||
printf("LSA: Found KerberosTime constructor\n");
|
||||
} /* DEBUG */
|
||||
}
|
||||
|
||||
// load the setRealm method in PrincipalName
|
||||
setRealmMethod = (*env)->GetMethodID(env, principalNameClass,
|
||||
@ -326,9 +326,9 @@ JNIEXPORT jint JNICALL JNI_OnLoad(
|
||||
return JNI_ERR;
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
if (native_debug) {
|
||||
printf("LSA: Finished OnLoad processing\n");
|
||||
} /* DEBUG */
|
||||
}
|
||||
|
||||
return JNI_VERSION_1_2;
|
||||
}
|
||||
@ -419,7 +419,7 @@ JNIEXPORT jobject JNICALL Java_sun_security_krb5_Credentials_acquireDefaultNativ
|
||||
}
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
if (native_debug) {
|
||||
printf("LSA: Found KrbCreds constructor\n");
|
||||
}
|
||||
|
||||
@ -430,9 +430,9 @@ JNIEXPORT jobject JNICALL Java_sun_security_krb5_Credentials_acquireDefaultNativ
|
||||
if (!PackageConnectLookup(&LogonHandle, &PackageId))
|
||||
break;
|
||||
|
||||
if (DEBUG) {
|
||||
if (native_debug) {
|
||||
printf("LSA: Got handle to Kerberos package\n");
|
||||
} /* DEBUG */
|
||||
}
|
||||
|
||||
// Get the MS TGT from cache
|
||||
CacheRequest.MessageType = KerbRetrieveTicketMessage;
|
||||
@ -449,7 +449,7 @@ JNIEXPORT jobject JNICALL Java_sun_security_krb5_Credentials_acquireDefaultNativ
|
||||
&SubStatus
|
||||
);
|
||||
|
||||
if (DEBUG) {
|
||||
if (native_debug) {
|
||||
printf("LSA: Response size is %d\n", rspSize);
|
||||
}
|
||||
|
||||
@ -490,9 +490,9 @@ JNIEXPORT jobject JNICALL Java_sun_security_krb5_Credentials_acquireDefaultNativ
|
||||
}
|
||||
|
||||
if (ignore_cache) {
|
||||
if (DEBUG) {
|
||||
if (native_debug) {
|
||||
printf("LSA: MS TGT in cache is invalid/not supported; request new ticket\n");
|
||||
} /* DEBUG */
|
||||
}
|
||||
|
||||
// use domain to request Ticket
|
||||
Status = ConstructTicketRequest(msticket->TargetDomainName,
|
||||
@ -516,9 +516,9 @@ JNIEXPORT jobject JNICALL Java_sun_security_krb5_Credentials_acquireDefaultNativ
|
||||
&SubStatus
|
||||
);
|
||||
|
||||
if (DEBUG) {
|
||||
if (native_debug) {
|
||||
printf("LSA: Response size is %d\n", responseSize);
|
||||
} /* DEBUG */
|
||||
}
|
||||
|
||||
if (!LSA_SUCCESS(Status) || !LSA_SUCCESS(SubStatus)) {
|
||||
if (!LSA_SUCCESS(Status)) {
|
||||
@ -811,7 +811,7 @@ ShowLastError(
|
||||
static WCHAR szMsgBuf[MAX_MSG_SIZE];
|
||||
DWORD dwRes;
|
||||
|
||||
if (DEBUG) {
|
||||
if (native_debug) {
|
||||
printf("LSA: Error calling function %s: %lu\n", szAPI, dwError);
|
||||
}
|
||||
|
||||
@ -823,7 +823,7 @@ ShowLastError(
|
||||
szMsgBuf,
|
||||
MAX_MSG_SIZE,
|
||||
NULL);
|
||||
if (DEBUG) {
|
||||
if (native_debug) {
|
||||
if (0 == dwRes) {
|
||||
printf("LSA: FormatMessage failed with %d\n", GetLastError());
|
||||
// ExitProcess(EXIT_FAILURE);
|
||||
@ -923,7 +923,7 @@ jobject BuildPrincipal(JNIEnv *env, PKERB_EXTERNAL_NAME principalName,
|
||||
((domainName.Length)*sizeof(WCHAR) + sizeof(UNICODE_NULL)));
|
||||
wcsncpy(realm, domainName.Buffer, domainName.Length/sizeof(WCHAR));
|
||||
|
||||
if (DEBUG) {
|
||||
if (native_debug) {
|
||||
printf("LSA: Principal domain is %S\n", realm);
|
||||
printf("LSA: Name type is %x\n", principalName->NameType);
|
||||
printf("LSA: Name count is %x\n", principalName->NameCount);
|
||||
@ -933,7 +933,7 @@ jobject BuildPrincipal(JNIEnv *env, PKERB_EXTERNAL_NAME principalName,
|
||||
stringArray = (*env)->NewObjectArray(env, nameCount,
|
||||
javaLangStringClass, NULL);
|
||||
if (stringArray == NULL) {
|
||||
if (DEBUG) {
|
||||
if (native_debug) {
|
||||
printf("LSA: Can't allocate String array for Principal\n");
|
||||
}
|
||||
LocalFree(realm);
|
||||
@ -976,7 +976,7 @@ jobject BuildEncryptionKey(JNIEnv *env, PKERB_CRYPTO_KEY cryptoKey) {
|
||||
if (cryptoKey->Value[i]) break;
|
||||
}
|
||||
if (i == cryptoKey->Length) {
|
||||
if (DEBUG) {
|
||||
if (native_debug) {
|
||||
printf("LSA: Session key all zero. Stop.\n");
|
||||
}
|
||||
return NULL;
|
||||
@ -1045,9 +1045,9 @@ jobject BuildKerberosTime(JNIEnv *env, PLARGE_INTEGER kerbtime) {
|
||||
hour,
|
||||
minute,
|
||||
second );
|
||||
if (DEBUG) {
|
||||
if (native_debug) {
|
||||
printf("LSA: %S\n", (wchar_t *)timeString);
|
||||
} /* DEBUG */
|
||||
}
|
||||
stringTime = (*env)->NewString(env, timeString,
|
||||
(sizeof(timeString)/sizeof(WCHAR))-1);
|
||||
if (stringTime != NULL) { // everything's OK so far
|
||||
|
133
jdk/test/java/util/zip/ZipCoding.java
Normal file
133
jdk/test/java/util/zip/ZipCoding.java
Normal file
@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 4244499 4532049 4700978 4820807 4980042
|
||||
* @summary Test ZipInputStream, ZipOutputStream and ZipFile with non-UTF8 encoding
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.*;
|
||||
import java.util.*;
|
||||
import java.util.zip.*;
|
||||
|
||||
public class ZipCoding {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
test("MS932",
|
||||
"\u4e00\u4e01", "\uff67\uff68\uff69\uff6a\uff6b\uff6c");
|
||||
|
||||
test("ibm437",
|
||||
"\u00e4\u00fc", "German Umlaut \u00fc in comment");
|
||||
|
||||
test("utf-8",
|
||||
"\u4e00\u4e01", "\uff67\uff68\uff69\uff6a\uff6b\uff6c");
|
||||
|
||||
test("utf-8",
|
||||
"\u00e4\u00fc", "German Umlaut \u00fc in comment");
|
||||
|
||||
test("utf-8",
|
||||
"Surrogate\ud801\udc01", "Surrogates \ud800\udc00 in comment");
|
||||
|
||||
}
|
||||
|
||||
static void testZipInputStream(InputStream is, Charset cs,
|
||||
String name, String comment, byte[] bb)
|
||||
throws Exception
|
||||
{
|
||||
ZipInputStream zis = new ZipInputStream(is, cs);
|
||||
ZipEntry e = zis.getNextEntry();
|
||||
if (e == null || ! name.equals(e.getName()))
|
||||
throw new RuntimeException("ZipIS name doesn't match!");
|
||||
byte[] bBuf = new byte[bb.length << 1];
|
||||
int n = zis.read(bBuf, 0, bBuf.length);
|
||||
if (n != bb.length ||
|
||||
!Arrays.equals(bb, Arrays.copyOf(bBuf, n))) {
|
||||
throw new RuntimeException("ZipIS content doesn't match!");
|
||||
}
|
||||
zis.close();
|
||||
}
|
||||
|
||||
static void testZipFile(File f, Charset cs,
|
||||
String name, String comment, byte[] bb)
|
||||
throws Exception
|
||||
{
|
||||
ZipFile zf = new ZipFile(f, cs);
|
||||
Enumeration<? extends ZipEntry> zes = zf.entries();
|
||||
ZipEntry e = (ZipEntry)zes.nextElement();
|
||||
if (! name.equals(e.getName()) ||
|
||||
! comment.equals(e.getComment()))
|
||||
throw new RuntimeException("ZipFile: name/comment doesn't match!");
|
||||
InputStream is = zf.getInputStream(e);
|
||||
if (is == null)
|
||||
throw new RuntimeException("ZipFile: getIS failed!");
|
||||
byte[] bBuf = new byte[bb.length << 1];
|
||||
int n = 0;
|
||||
int nn =0;
|
||||
while ((nn = is.read(bBuf, n, bBuf.length-n)) != -1) {
|
||||
n += nn;
|
||||
}
|
||||
if (n != bb.length ||
|
||||
!Arrays.equals(bb, Arrays.copyOf(bBuf, n))) {
|
||||
throw new RuntimeException("ZipFile content doesn't match!");
|
||||
}
|
||||
zf.close();
|
||||
}
|
||||
|
||||
static void test(String csn, String name, String comment)
|
||||
throws Exception
|
||||
{
|
||||
byte[] bb = "This is the conent of the zipfile".getBytes("ISO-8859-1");
|
||||
Charset cs = Charset.forName(csn);
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
ZipOutputStream zos = new ZipOutputStream(baos, cs);
|
||||
|
||||
ZipEntry e = new ZipEntry(name);
|
||||
e.setComment(comment);
|
||||
zos.putNextEntry(e);
|
||||
zos.write(bb, 0, bb.length);
|
||||
zos.closeEntry();
|
||||
zos.close();
|
||||
ByteArrayInputStream bis = new ByteArrayInputStream(baos.toByteArray());
|
||||
testZipInputStream(bis, cs, name, comment, bb);
|
||||
|
||||
if ("utf-8".equals(csn)) {
|
||||
// EFS should be set
|
||||
bis.reset();
|
||||
testZipInputStream(bis, Charset.forName("MS932"), name, comment, bb);
|
||||
}
|
||||
|
||||
File f = new File(new File(System.getProperty("test.dir", ".")),
|
||||
"zfcoding.zip");
|
||||
FileOutputStream fos = new FileOutputStream(f);
|
||||
baos.writeTo(fos);
|
||||
fos.close();
|
||||
testZipFile(f, cs, name, comment, bb);
|
||||
if ("utf-8".equals(csn)) {
|
||||
testZipFile(f, Charset.forName("MS932"), name, comment, bb);
|
||||
}
|
||||
f.delete();
|
||||
}
|
||||
}
|
743
jdk/test/java/util/zip/zip.java
Normal file
743
jdk/test/java/util/zip/zip.java
Normal file
@ -0,0 +1,743 @@
|
||||
/*
|
||||
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Sun designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Sun in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.*;
|
||||
import java.util.zip.*;
|
||||
import java.text.MessageFormat;
|
||||
|
||||
/**
|
||||
* A stripped-down version of Jar tool with a "-encoding" option to
|
||||
* support non-UTF8 encoidng for entry name and comment.
|
||||
*/
|
||||
public class zip {
|
||||
String program;
|
||||
PrintStream out, err;
|
||||
String fname;
|
||||
String zname = "";
|
||||
String[] files;
|
||||
Charset cs = Charset.forName("UTF-8");
|
||||
|
||||
Map<String, File> entryMap = new HashMap<String, File>();
|
||||
Set<File> entries = new LinkedHashSet<File>();
|
||||
List<String> paths = new ArrayList<String>();
|
||||
|
||||
CRC32 crc32 = new CRC32();
|
||||
/*
|
||||
* cflag: create
|
||||
* uflag: update
|
||||
* xflag: xtract
|
||||
* tflag: table
|
||||
* vflag: verbose
|
||||
* flag0: no zip compression (store only)
|
||||
*/
|
||||
boolean cflag, uflag, xflag, tflag, vflag, flag0;
|
||||
|
||||
private static ResourceBundle rsrc;
|
||||
static {
|
||||
try {
|
||||
// just use the jar message
|
||||
rsrc = ResourceBundle.getBundle("sun.tools.jar.resources.jar");
|
||||
} catch (MissingResourceException e) {
|
||||
throw new Error("Fatal: Resource for jar is missing");
|
||||
}
|
||||
}
|
||||
|
||||
public zip(PrintStream out, PrintStream err, String program) {
|
||||
this.out = out;
|
||||
this.err = err;
|
||||
this.program = program;
|
||||
}
|
||||
|
||||
private boolean ok;
|
||||
|
||||
public synchronized boolean run(String args[]) {
|
||||
ok = true;
|
||||
if (!parseArgs(args)) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
if (cflag || uflag) {
|
||||
if (fname != null) {
|
||||
zname = fname.replace(File.separatorChar, '/');
|
||||
if (zname.startsWith("./")) {
|
||||
zname = zname.substring(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cflag) {
|
||||
OutputStream out;
|
||||
if (fname != null) {
|
||||
out = new FileOutputStream(fname);
|
||||
} else {
|
||||
out = new FileOutputStream(FileDescriptor.out);
|
||||
if (vflag) {
|
||||
vflag = false;
|
||||
}
|
||||
}
|
||||
expand(null, files, false);
|
||||
create(new BufferedOutputStream(out, 4096));
|
||||
out.close();
|
||||
} else if (uflag) {
|
||||
File inputFile = null, tmpFile = null;
|
||||
FileInputStream in;
|
||||
FileOutputStream out;
|
||||
if (fname != null) {
|
||||
inputFile = new File(fname);
|
||||
String path = inputFile.getParent();
|
||||
tmpFile = File.createTempFile("tmp", null,
|
||||
new File((path == null) ? "." : path));
|
||||
in = new FileInputStream(inputFile);
|
||||
out = new FileOutputStream(tmpFile);
|
||||
} else {
|
||||
in = new FileInputStream(FileDescriptor.in);
|
||||
out = new FileOutputStream(FileDescriptor.out);
|
||||
vflag = false;
|
||||
}
|
||||
expand(null, files, true);
|
||||
boolean updateOk = update(in, new BufferedOutputStream(out));
|
||||
if (ok) {
|
||||
ok = updateOk;
|
||||
}
|
||||
in.close();
|
||||
out.close();
|
||||
if (fname != null) {
|
||||
inputFile.delete();
|
||||
if (!tmpFile.renameTo(inputFile)) {
|
||||
tmpFile.delete();
|
||||
throw new IOException(getMsg("error.write.file"));
|
||||
}
|
||||
tmpFile.delete();
|
||||
}
|
||||
} else if (tflag) {
|
||||
replaceFSC(files);
|
||||
if (fname != null) {
|
||||
list(fname, files);
|
||||
} else {
|
||||
InputStream in = new FileInputStream(FileDescriptor.in);
|
||||
try{
|
||||
list(new BufferedInputStream(in), files);
|
||||
} finally {
|
||||
in.close();
|
||||
}
|
||||
}
|
||||
} else if (xflag) {
|
||||
replaceFSC(files);
|
||||
if (fname != null && files != null) {
|
||||
extract(fname, files);
|
||||
} else {
|
||||
InputStream in = (fname == null)
|
||||
? new FileInputStream(FileDescriptor.in)
|
||||
: new FileInputStream(fname);
|
||||
try {
|
||||
extract(new BufferedInputStream(in), files);
|
||||
} finally {
|
||||
in.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
fatalError(e);
|
||||
ok = false;
|
||||
} catch (Error ee) {
|
||||
ee.printStackTrace();
|
||||
ok = false;
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
ok = false;
|
||||
}
|
||||
out.flush();
|
||||
err.flush();
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
boolean parseArgs(String args[]) {
|
||||
try {
|
||||
args = parse(args);
|
||||
} catch (FileNotFoundException e) {
|
||||
fatalError(formatMsg("error.cant.open", e.getMessage()));
|
||||
return false;
|
||||
} catch (IOException e) {
|
||||
fatalError(e);
|
||||
return false;
|
||||
}
|
||||
int count = 1;
|
||||
try {
|
||||
String flags = args[0];
|
||||
if (flags.startsWith("-")) {
|
||||
flags = flags.substring(1);
|
||||
}
|
||||
for (int i = 0; i < flags.length(); i++) {
|
||||
switch (flags.charAt(i)) {
|
||||
case 'c':
|
||||
if (xflag || tflag || uflag) {
|
||||
usageError();
|
||||
return false;
|
||||
}
|
||||
cflag = true;
|
||||
break;
|
||||
case 'u':
|
||||
if (cflag || xflag || tflag) {
|
||||
usageError();
|
||||
return false;
|
||||
}
|
||||
uflag = true;
|
||||
break;
|
||||
case 'x':
|
||||
if (cflag || uflag || tflag) {
|
||||
usageError();
|
||||
return false;
|
||||
}
|
||||
xflag = true;
|
||||
break;
|
||||
case 't':
|
||||
if (cflag || uflag || xflag) {
|
||||
usageError();
|
||||
return false;
|
||||
}
|
||||
tflag = true;
|
||||
break;
|
||||
case 'v':
|
||||
vflag = true;
|
||||
break;
|
||||
case 'f':
|
||||
fname = args[count++];
|
||||
break;
|
||||
case '0':
|
||||
flag0 = true;
|
||||
break;
|
||||
default:
|
||||
error(formatMsg("error.illegal.option",
|
||||
String.valueOf(flags.charAt(i))));
|
||||
usageError();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} catch (ArrayIndexOutOfBoundsException e) {
|
||||
usageError();
|
||||
return false;
|
||||
}
|
||||
if (!cflag && !tflag && !xflag && !uflag) {
|
||||
error(getMsg("error.bad.option"));
|
||||
usageError();
|
||||
return false;
|
||||
}
|
||||
/* parse file arguments */
|
||||
int n = args.length - count;
|
||||
if (n > 0) {
|
||||
int k = 0;
|
||||
String[] nameBuf = new String[n];
|
||||
try {
|
||||
for (int i = count; i < args.length; i++) {
|
||||
if (args[i].equals("-encoding")) {
|
||||
cs = Charset.forName(args[++i]);
|
||||
} else if (args[i].equals("-C")) {
|
||||
/* change the directory */
|
||||
String dir = args[++i];
|
||||
dir = (dir.endsWith(File.separator) ?
|
||||
dir : (dir + File.separator));
|
||||
dir = dir.replace(File.separatorChar, '/');
|
||||
while (dir.indexOf("//") > -1) {
|
||||
dir = dir.replace("//", "/");
|
||||
}
|
||||
paths.add(dir.replace(File.separatorChar, '/'));
|
||||
nameBuf[k++] = dir + args[++i];
|
||||
} else {
|
||||
nameBuf[k++] = args[i];
|
||||
}
|
||||
}
|
||||
} catch (ArrayIndexOutOfBoundsException e) {
|
||||
e.printStackTrace();
|
||||
usageError();
|
||||
return false;
|
||||
}
|
||||
if (k != 0) {
|
||||
files = new String[k];
|
||||
System.arraycopy(nameBuf, 0, files, 0, k);
|
||||
}
|
||||
} else if (cflag || uflag) {
|
||||
error(getMsg("error.bad.uflag"));
|
||||
usageError();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void expand(File dir, String[] files, boolean isUpdate) {
|
||||
if (files == null) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < files.length; i++) {
|
||||
File f;
|
||||
if (dir == null) {
|
||||
f = new File(files[i]);
|
||||
} else {
|
||||
f = new File(dir, files[i]);
|
||||
}
|
||||
if (f.isFile()) {
|
||||
if (entries.add(f)) {
|
||||
if (isUpdate)
|
||||
entryMap.put(entryName(f.getPath()), f);
|
||||
}
|
||||
} else if (f.isDirectory()) {
|
||||
if (entries.add(f)) {
|
||||
if (isUpdate) {
|
||||
String dirPath = f.getPath();
|
||||
dirPath = (dirPath.endsWith(File.separator)) ? dirPath :
|
||||
(dirPath + File.separator);
|
||||
entryMap.put(entryName(dirPath), f);
|
||||
}
|
||||
expand(f, f.list(), isUpdate);
|
||||
}
|
||||
} else {
|
||||
error(formatMsg("error.nosuch.fileordir", String.valueOf(f)));
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void create(OutputStream out) throws IOException
|
||||
{
|
||||
ZipOutputStream zos = new ZipOutputStream(out, cs);
|
||||
if (flag0) {
|
||||
zos.setMethod(ZipOutputStream.STORED);
|
||||
}
|
||||
for (File file: entries) {
|
||||
addFile(zos, file);
|
||||
}
|
||||
zos.close();
|
||||
}
|
||||
|
||||
boolean update(InputStream in, OutputStream out) throws IOException
|
||||
{
|
||||
ZipInputStream zis = new ZipInputStream(in, cs);
|
||||
ZipOutputStream zos = new ZipOutputStream(out, cs);
|
||||
ZipEntry e = null;
|
||||
byte[] buf = new byte[1024];
|
||||
int n = 0;
|
||||
boolean updateOk = true;
|
||||
|
||||
// put the old entries first, replace if necessary
|
||||
while ((e = zis.getNextEntry()) != null) {
|
||||
String name = e.getName();
|
||||
if (!entryMap.containsKey(name)) { // copy the old stuff
|
||||
// do our own compression
|
||||
ZipEntry e2 = new ZipEntry(name);
|
||||
e2.setMethod(e.getMethod());
|
||||
e2.setTime(e.getTime());
|
||||
e2.setComment(e.getComment());
|
||||
e2.setExtra(e.getExtra());
|
||||
if (e.getMethod() == ZipEntry.STORED) {
|
||||
e2.setSize(e.getSize());
|
||||
e2.setCrc(e.getCrc());
|
||||
}
|
||||
zos.putNextEntry(e2);
|
||||
while ((n = zis.read(buf, 0, buf.length)) != -1) {
|
||||
zos.write(buf, 0, n);
|
||||
}
|
||||
} else { // replace with the new files
|
||||
File f = entryMap.get(name);
|
||||
addFile(zos, f);
|
||||
entryMap.remove(name);
|
||||
entries.remove(f);
|
||||
}
|
||||
}
|
||||
|
||||
// add the remaining new files
|
||||
for (File f: entries) {
|
||||
addFile(zos, f);
|
||||
}
|
||||
zis.close();
|
||||
zos.close();
|
||||
return updateOk;
|
||||
}
|
||||
|
||||
private String entryName(String name) {
|
||||
name = name.replace(File.separatorChar, '/');
|
||||
String matchPath = "";
|
||||
for (String path : paths) {
|
||||
if (name.startsWith(path) && (path.length() > matchPath.length())) {
|
||||
matchPath = path;
|
||||
}
|
||||
}
|
||||
name = name.substring(matchPath.length());
|
||||
|
||||
if (name.startsWith("/")) {
|
||||
name = name.substring(1);
|
||||
} else if (name.startsWith("./")) {
|
||||
name = name.substring(2);
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
void addFile(ZipOutputStream zos, File file) throws IOException {
|
||||
String name = file.getPath();
|
||||
boolean isDir = file.isDirectory();
|
||||
if (isDir) {
|
||||
name = name.endsWith(File.separator) ? name :
|
||||
(name + File.separator);
|
||||
}
|
||||
name = entryName(name);
|
||||
|
||||
if (name.equals("") || name.equals(".") || name.equals(zname)) {
|
||||
return;
|
||||
}
|
||||
|
||||
long size = isDir ? 0 : file.length();
|
||||
|
||||
if (vflag) {
|
||||
out.print(formatMsg("out.adding", name));
|
||||
}
|
||||
ZipEntry e = new ZipEntry(name);
|
||||
e.setTime(file.lastModified());
|
||||
if (size == 0) {
|
||||
e.setMethod(ZipEntry.STORED);
|
||||
e.setSize(0);
|
||||
e.setCrc(0);
|
||||
} else if (flag0) {
|
||||
e.setSize(size);
|
||||
e.setMethod(ZipEntry.STORED);
|
||||
crc32File(e, file);
|
||||
}
|
||||
zos.putNextEntry(e);
|
||||
if (!isDir) {
|
||||
byte[] buf = new byte[8192];
|
||||
int len;
|
||||
InputStream is = new BufferedInputStream(new FileInputStream(file));
|
||||
while ((len = is.read(buf, 0, buf.length)) != -1) {
|
||||
zos.write(buf, 0, len);
|
||||
}
|
||||
is.close();
|
||||
}
|
||||
zos.closeEntry();
|
||||
/* report how much compression occurred. */
|
||||
if (vflag) {
|
||||
size = e.getSize();
|
||||
long csize = e.getCompressedSize();
|
||||
out.print(formatMsg2("out.size", String.valueOf(size),
|
||||
String.valueOf(csize)));
|
||||
if (e.getMethod() == ZipEntry.DEFLATED) {
|
||||
long ratio = 0;
|
||||
if (size != 0) {
|
||||
ratio = ((size - csize) * 100) / size;
|
||||
}
|
||||
output(formatMsg("out.deflated", String.valueOf(ratio)));
|
||||
} else {
|
||||
output(getMsg("out.stored"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void crc32File(ZipEntry e, File f) throws IOException {
|
||||
InputStream is = new BufferedInputStream(new FileInputStream(f));
|
||||
byte[] buf = new byte[8192];
|
||||
crc32.reset();
|
||||
int r = 0;
|
||||
int nread = 0;
|
||||
long len = f.length();
|
||||
while ((r = is.read(buf)) != -1) {
|
||||
nread += r;
|
||||
crc32.update(buf, 0, r);
|
||||
}
|
||||
is.close();
|
||||
if (nread != (int) len) {
|
||||
throw new ZipException(formatMsg(
|
||||
"error.incorrect.length", f.getPath()));
|
||||
}
|
||||
e.setCrc(crc32.getValue());
|
||||
}
|
||||
|
||||
void replaceFSC(String files[]) {
|
||||
if (files != null) {
|
||||
for (String file : files) {
|
||||
file = file.replace(File.separatorChar, '/');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Set<ZipEntry> newDirSet() {
|
||||
return new HashSet<ZipEntry>() {
|
||||
public boolean add(ZipEntry e) {
|
||||
return (e == null || super.add(e));
|
||||
}};
|
||||
}
|
||||
|
||||
void updateLastModifiedTime(Set<ZipEntry> zes) throws IOException {
|
||||
for (ZipEntry ze : zes) {
|
||||
long lastModified = ze.getTime();
|
||||
if (lastModified != -1) {
|
||||
File f = new File(ze.getName().replace('/', File.separatorChar));
|
||||
f.setLastModified(lastModified);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void extract(InputStream in, String files[]) throws IOException {
|
||||
ZipInputStream zis = new ZipInputStream(in, cs);
|
||||
ZipEntry e;
|
||||
Set<ZipEntry> dirs = newDirSet();
|
||||
while ((e = zis.getNextEntry()) != null) {
|
||||
if (files == null) {
|
||||
dirs.add(extractFile(zis, e));
|
||||
} else {
|
||||
String name = e.getName();
|
||||
for (String file : files) {
|
||||
if (name.startsWith(file)) {
|
||||
dirs.add(extractFile(zis, e));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
updateLastModifiedTime(dirs);
|
||||
}
|
||||
|
||||
void extract(String fname, String files[]) throws IOException {
|
||||
ZipFile zf = new ZipFile(fname, cs);
|
||||
Set<ZipEntry> dirs = newDirSet();
|
||||
Enumeration<? extends ZipEntry> zes = zf.entries();
|
||||
while (zes.hasMoreElements()) {
|
||||
ZipEntry e = zes.nextElement();
|
||||
InputStream is;
|
||||
if (files == null) {
|
||||
dirs.add(extractFile(zf.getInputStream(e), e));
|
||||
} else {
|
||||
String name = e.getName();
|
||||
for (String file : files) {
|
||||
if (name.startsWith(file)) {
|
||||
dirs.add(extractFile(zf.getInputStream(e), e));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
zf.close();
|
||||
updateLastModifiedTime(dirs);
|
||||
}
|
||||
|
||||
ZipEntry extractFile(InputStream is, ZipEntry e) throws IOException {
|
||||
ZipEntry rc = null;
|
||||
String name = e.getName();
|
||||
File f = new File(e.getName().replace('/', File.separatorChar));
|
||||
if (e.isDirectory()) {
|
||||
if (f.exists()) {
|
||||
if (!f.isDirectory()) {
|
||||
throw new IOException(formatMsg("error.create.dir",
|
||||
f.getPath()));
|
||||
}
|
||||
} else {
|
||||
if (!f.mkdirs()) {
|
||||
throw new IOException(formatMsg("error.create.dir",
|
||||
f.getPath()));
|
||||
} else {
|
||||
rc = e;
|
||||
}
|
||||
}
|
||||
if (vflag) {
|
||||
output(formatMsg("out.create", name));
|
||||
}
|
||||
} else {
|
||||
if (f.getParent() != null) {
|
||||
File d = new File(f.getParent());
|
||||
if (!d.exists() && !d.mkdirs() || !d.isDirectory()) {
|
||||
throw new IOException(formatMsg(
|
||||
"error.create.dir", d.getPath()));
|
||||
}
|
||||
}
|
||||
OutputStream os = new FileOutputStream(f);
|
||||
byte[] b = new byte[8192];
|
||||
int len;
|
||||
try {
|
||||
while ((len = is.read(b, 0, b.length)) != -1) {
|
||||
os.write(b, 0, len);
|
||||
}
|
||||
} finally {
|
||||
if (is instanceof ZipInputStream)
|
||||
((ZipInputStream)is).closeEntry();
|
||||
else
|
||||
is.close();
|
||||
os.close();
|
||||
}
|
||||
if (vflag) {
|
||||
if (e.getMethod() == ZipEntry.DEFLATED) {
|
||||
output(formatMsg("out.inflated", name));
|
||||
} else {
|
||||
output(formatMsg("out.extracted", name));
|
||||
}
|
||||
}
|
||||
}
|
||||
long lastModified = e.getTime();
|
||||
if (lastModified != -1) {
|
||||
f.setLastModified(lastModified);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
void list(InputStream in, String files[]) throws IOException {
|
||||
ZipInputStream zis = new ZipInputStream(in, cs);
|
||||
ZipEntry e;
|
||||
while ((e = zis.getNextEntry()) != null) {
|
||||
zis.closeEntry();
|
||||
printEntry(e, files);
|
||||
}
|
||||
}
|
||||
|
||||
void list(String fname, String files[]) throws IOException {
|
||||
ZipFile zf = new ZipFile(fname, cs);
|
||||
Enumeration<? extends ZipEntry> zes = zf.entries();
|
||||
while (zes.hasMoreElements()) {
|
||||
printEntry(zes.nextElement(), files);
|
||||
}
|
||||
zf.close();
|
||||
}
|
||||
|
||||
void printEntry(ZipEntry e, String[] files) throws IOException {
|
||||
if (files == null) {
|
||||
printEntry(e);
|
||||
} else {
|
||||
String name = e.getName();
|
||||
for (String file : files) {
|
||||
if (name.startsWith(file)) {
|
||||
printEntry(e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void printEntry(ZipEntry e) throws IOException {
|
||||
if (vflag) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String s = Long.toString(e.getSize());
|
||||
for (int i = 6 - s.length(); i > 0; --i) {
|
||||
sb.append(' ');
|
||||
}
|
||||
sb.append(s).append(' ').append(new Date(e.getTime()).toString());
|
||||
sb.append(' ').append(e.getName());
|
||||
output(sb.toString());
|
||||
} else {
|
||||
output(e.getName());
|
||||
}
|
||||
}
|
||||
|
||||
void usageError() {
|
||||
error(
|
||||
"Usage: zip {ctxu}[vf0] [zip-file] [-encoding encname][-C dir] files ...\n" +
|
||||
"Options:\n" +
|
||||
" -c create new archive\n" +
|
||||
" -t list table of contents for archive\n" +
|
||||
" -x extract named (or all) files from archive\n" +
|
||||
" -u update existing archive\n" +
|
||||
" -v generate verbose output on standard output\n" +
|
||||
" -f specify archive file name\n" +
|
||||
" -0 store only; use no ZIP compression\n" +
|
||||
" -C change to the specified directory and include the following file\n" +
|
||||
"If any file is a directory then it is processed recursively.\n");
|
||||
}
|
||||
|
||||
void fatalError(Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
void fatalError(String s) {
|
||||
error(program + ": " + s);
|
||||
}
|
||||
|
||||
|
||||
protected void output(String s) {
|
||||
out.println(s);
|
||||
}
|
||||
|
||||
protected void error(String s) {
|
||||
err.println(s);
|
||||
}
|
||||
|
||||
private String getMsg(String key) {
|
||||
try {
|
||||
return (rsrc.getString(key));
|
||||
} catch (MissingResourceException e) {
|
||||
throw new Error("Error in message file");
|
||||
}
|
||||
}
|
||||
|
||||
private String formatMsg(String key, String arg) {
|
||||
String msg = getMsg(key);
|
||||
String[] args = new String[1];
|
||||
args[0] = arg;
|
||||
return MessageFormat.format(msg, (Object[]) args);
|
||||
}
|
||||
|
||||
private String formatMsg2(String key, String arg, String arg1) {
|
||||
String msg = getMsg(key);
|
||||
String[] args = new String[2];
|
||||
args[0] = arg;
|
||||
args[1] = arg1;
|
||||
return MessageFormat.format(msg, (Object[]) args);
|
||||
}
|
||||
|
||||
public static String[] parse(String[] args) throws IOException
|
||||
{
|
||||
ArrayList<String> newArgs = new ArrayList<String>(args.length);
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
String arg = args[i];
|
||||
if (arg.length() > 1 && arg.charAt(0) == '@') {
|
||||
arg = arg.substring(1);
|
||||
if (arg.charAt(0) == '@') {
|
||||
newArgs.add(arg);
|
||||
} else {
|
||||
loadCmdFile(arg, newArgs);
|
||||
}
|
||||
} else {
|
||||
newArgs.add(arg);
|
||||
}
|
||||
}
|
||||
return newArgs.toArray(new String[newArgs.size()]);
|
||||
}
|
||||
|
||||
private static void loadCmdFile(String name, List<String> args) throws IOException
|
||||
{
|
||||
Reader r = new BufferedReader(new FileReader(name));
|
||||
StreamTokenizer st = new StreamTokenizer(r);
|
||||
st.resetSyntax();
|
||||
st.wordChars(' ', 255);
|
||||
st.whitespaceChars(0, ' ');
|
||||
st.commentChar('#');
|
||||
st.quoteChar('"');
|
||||
st.quoteChar('\'');
|
||||
while (st.nextToken() != st.TT_EOF) {
|
||||
args.add(st.sval);
|
||||
}
|
||||
r.close();
|
||||
}
|
||||
|
||||
public static void main(String args[]) {
|
||||
zip z = new zip(System.out, System.err, "zip");
|
||||
System.exit(z.run(args) ? 0 : 1);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user