+++ /dev/null
-/* $RCSfile$
- * $Author$
- * $Date$
- * $Revision$
- *
- * Some portions of this file have been modified by Robert Hanson hansonr.at.stolaf.edu 2012-2017
- * for use in SwingJS via transpilation into JavaScript using Java2Script.
- *
- * Copyright (C) 2006 The Jmol Development Team
- *
- * Contact: jmol-developers@lists.sf.net
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-package javajs.util;
-
-import java.io.BufferedInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.Map;
-import java.util.zip.CRC32;
-import java.util.zip.GZIPInputStream;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipInputStream;
-import java.util.zip.ZipOutputStream;
-
-import javajs.api.GenericZipInputStream;
-import javajs.api.GenericZipTools;
-import javajs.api.Interface;
-import javajs.api.ZInputStream;
-
-import org.apache.tools.bzip2.CBZip2InputStreamFactory;
-
-
-/**
- * Note the JSmol/HTML5 must use its own version of java.util.zip.ZipOutputStream.
- *
- */
-public class ZipTools implements GenericZipTools {
-
- public ZipTools() {
- // for reflection
- }
-
- @Override
- public ZInputStream newZipInputStream(InputStream is) {
- return newZIS(is);
- }
-
- @SuppressWarnings("resource")
- private static ZInputStream newZIS(InputStream is) {
- return (is instanceof ZInputStream ? (ZInputStream) is
- : is instanceof BufferedInputStream ? new GenericZipInputStream(is)
- : new GenericZipInputStream(new BufferedInputStream(is)));
- }
-
- /**
- * reads a ZIP file and saves all data in a Hashtable so that the files may be
- * organized later in a different order. Also adds a #Directory_Listing entry.
- *
- * Files are bracketed by BEGIN Directory Entry and END Directory Entry lines,
- * similar to CompoundDocument.getAllData.
- *
- * @param is
- * @param subfileList
- * @param name0
- * prefix for entry listing
- * @param binaryFileList
- * |-separated list of files that should be saved as xx xx xx hex byte
- * strings. The directory listing is appended with ":asBinaryString"
- * @param fileData
- */
- @Override
- public void getAllZipData(InputStream is, String[] subfileList,
- String name0, String binaryFileList, String exclude,
- Map<String, String> fileData) {
- ZipInputStream zis = (ZipInputStream) newZIS(is);
- ZipEntry ze;
- SB listing = new SB();
- binaryFileList = "|" + binaryFileList + "|";
- String prefix = PT.join(subfileList, '/', 1);
- String prefixd = null;
- if (prefix != null) {
- prefixd = prefix.substring(0, prefix.indexOf("/") + 1);
- if (prefixd.length() == 0)
- prefixd = null;
- }
- try {
- while ((ze = zis.getNextEntry()) != null) {
- String name = ze.getName();
- if (prefix != null && prefixd != null
- && !(name.equals(prefix) || name.startsWith(prefixd))
- || exclude != null && name.contains(exclude))
- continue;
- //System.out.println("ziputil: " + name);
- listing.append(name).appendC('\n');
- String sname = "|" + name.substring(name.lastIndexOf("/") + 1) + "|";
- boolean asBinaryString = (binaryFileList.indexOf(sname) >= 0);
- byte[] bytes = Rdr.getLimitedStreamBytes(zis, ze.getSize());
- String str;
- if (asBinaryString) {
- str = getBinaryStringForBytes(bytes);
- name += ":asBinaryString";
- } else {
- str = Rdr.fixUTF(bytes);
- }
- str = "BEGIN Directory Entry " + name + "\n" + str
- + "\nEND Directory Entry " + name + "\n";
- String key = name0 + "|" + name;
- fileData.put(key, str);
- }
- } catch (Exception e) {
- }
- fileData.put("#Directory_Listing", listing.toString());
- }
-
- private String getBinaryStringForBytes(byte[] bytes) {
- SB ret = new SB();
- for (int i = 0; i < bytes.length; i++)
- ret.append(Integer.toHexString(bytes[i] & 0xFF)).appendC(' ');
- return ret.toString();
- }
-
- /**
- * iteratively drills into zip files of zip files to extract file content or
- * zip file directory. Also works with JAR files.
- *
- * Does not return "__MACOS" paths
- *
- * @param bis
- * @param list
- * @param listPtr
- * @param asBufferedInputStream
- * for Pmesh
- * @return directory listing or subfile contents
- */
- @Override
- public Object getZipFileDirectory(BufferedInputStream bis, String[] list,
- int listPtr, boolean asBufferedInputStream) {
- SB ret;
- if (list == null || listPtr >= list.length)
- return getZipDirectoryAsStringAndClose(bis);
- bis = Rdr.getPngZipStream(bis, true);
- String fileName = list[listPtr];
- ZipInputStream zis = new ZipInputStream(bis);
- ZipEntry ze;
- //System.out.println("fname=" + fileName);
- try {
- boolean isAll = (fileName.equals("."));
- if (isAll || fileName.lastIndexOf("/") == fileName.length() - 1) {
- ret = new SB();
- while ((ze = zis.getNextEntry()) != null) {
- String name = ze.getName();
- if (isAll || name.startsWith(fileName))
- ret.append(name).appendC('\n');
- }
- String str = ret.toString();
- return (asBufferedInputStream ? Rdr.getBIS(str.getBytes()) : str);
- }
- int pt = fileName.indexOf(":asBinaryString");
- boolean asBinaryString = (pt > 0);
- if (asBinaryString)
- fileName = fileName.substring(0, pt);
- fileName = fileName.replace('\\', '/');
- while ((ze = zis.getNextEntry()) != null
- && !fileName.equals(ze.getName())) {
- }
- byte[] bytes = (ze == null ? null : Rdr.getLimitedStreamBytes(zis,
- ze.getSize()));
- ze = null;
- zis.close();
- if (bytes == null)
- return "";
- if (Rdr.isZipB(bytes) || Rdr.isPngZipB(bytes))
- return getZipFileDirectory(Rdr.getBIS(bytes), list, ++listPtr,
- asBufferedInputStream);
- if (asBufferedInputStream)
- return Rdr.getBIS(bytes);
- if (asBinaryString) {
- ret = new SB();
- for (int i = 0; i < bytes.length; i++)
- ret.append(Integer.toHexString(bytes[i] & 0xFF)).appendC(' ');
- return ret.toString();
- }
- if (Rdr.isGzipB(bytes))
- bytes = Rdr.getLimitedStreamBytes(getUnGzippedInputStream(bytes), -1);
- return Rdr.fixUTF(bytes);
- } catch (Exception e) {
- return "";
- }
- }
-
- @Override
- public byte[] getZipFileContentsAsBytes(BufferedInputStream bis,
- String[] list, int listPtr) {
- byte[] ret = new byte[0];
- String fileName = list[listPtr];
- if (fileName.lastIndexOf("/") == fileName.length() - 1)
- return ret;
- try {
- bis = Rdr.getPngZipStream(bis, true);
- ZipInputStream zis = new ZipInputStream(bis);
- ZipEntry ze;
- while ((ze = zis.getNextEntry()) != null) {
- if (!fileName.equals(ze.getName()))
- continue;
- byte[] bytes = Rdr.getLimitedStreamBytes(zis, ze.getSize());
- return ((Rdr.isZipB(bytes) || Rdr.isPngZipB(bytes)) && ++listPtr < list.length ? getZipFileContentsAsBytes(
- Rdr.getBIS(bytes), list, listPtr) : bytes);
- }
- } catch (Exception e) {
- }
- return ret;
- }
-
- @Override
- public String getZipDirectoryAsStringAndClose(BufferedInputStream bis) {
- SB sb = new SB();
- String[] s = new String[0];
- try {
- s = getZipDirectoryOrErrorAndClose(bis, null);
- bis.close();
- } catch (Exception e) {
- System.out.println(e.toString());
- }
- for (int i = 0; i < s.length; i++)
- sb.append(s[i]).appendC('\n');
- return sb.toString();
- }
-
- @Override
- public String[] getZipDirectoryAndClose(BufferedInputStream bis,
- String manifestID) {
- String[] s = new String[0];
- try {
- s = getZipDirectoryOrErrorAndClose(bis, manifestID);
- bis.close();
- } catch (Exception e) {
- System.out.println(e.toString());
- }
- return s;
- }
-
- private String[] getZipDirectoryOrErrorAndClose(BufferedInputStream bis,
- String manifestID)
- throws IOException {
- bis = Rdr.getPngZipStream(bis, true);
- Lst<String> v = new Lst<String>();
- ZipInputStream zis = new ZipInputStream(bis);
- ZipEntry ze;
- String manifest = null;
- while ((ze = zis.getNextEntry()) != null) {
- String fileName = ze.getName();
- if (manifestID != null && fileName.startsWith(manifestID))
- manifest = getStreamAsString(zis);
- else if (!fileName.startsWith("__MACOS")) // resource fork not nec.
- v.addLast(fileName);
- }
- zis.close();
- if (manifestID != null)
- v.add(0, manifest == null ? "" : manifest + "\n############\n");
- return v.toArray(new String[v.size()]);
- }
-
- public static String getStreamAsString(InputStream is) throws IOException {
- return Rdr.fixUTF(Rdr.getLimitedStreamBytes(is, -1));
- }
-
- @Override
- public InputStream newGZIPInputStream(InputStream is) throws IOException {
- return new BufferedInputStream(new GZIPInputStream(is, 512));
- }
-
- @Override
- public InputStream newBZip2InputStream(InputStream is) throws IOException {
- return new BufferedInputStream(((CBZip2InputStreamFactory) Interface.getInterface("org.apache.tools.bzip2.CBZip2InputStreamFactory")).getStream(is));
- }
-
- @Override
- public BufferedInputStream getUnGzippedInputStream(byte[] bytes) {
- try {
- return Rdr.getUnzippedInputStream(this, Rdr.getBIS(bytes));
- } catch (Exception e) {
- return null;
- }
- }
-
- @Override
- public void addZipEntry(Object zos, String fileName) throws IOException {
- ((ZipOutputStream) zos).putNextEntry(new ZipEntry(fileName));
- }
-
- @Override
- public void closeZipEntry(Object zos) throws IOException {
- ((ZipOutputStream) zos).closeEntry();
- }
-
- @Override
- public Object getZipOutputStream(Object bos) {
-// /**
-// * xxxxj2sNative
-// *
-// * return javajs.api.Interface.getInterface(
-// * "java.util.zip.ZipOutputStream").setZOS(bos);
-// *
-// */
-// {
- return new ZipOutputStream((OutputStream) bos);
-// }
- }
-
- @Override
- public int getCrcValue(byte[] bytes) {
- CRC32 crc = new CRC32();
- crc.update(bytes, 0, bytes.length);
- return (int) crc.getValue();
- }
-
- @Override
- public void readFileAsMap(BufferedInputStream bis, Map<String, Object> bdata, String name) {
- readFileAsMapStatic(bis, bdata, name);
- }
-
- public static void readFileAsMapStatic(BufferedInputStream bis,
- Map<String, Object> bdata, String name) {
- int pt = (name == null ? -1 : name.indexOf("|"));
- name = (pt >= 0 ? name.substring(pt + 1) : null);
- try {
- if (Rdr.isPngZipStream(bis)) {
- boolean isImage = "_IMAGE_".equals(name);
- if (name == null || isImage)
- bdata.put((isImage ? "_DATA_" : "_IMAGE_"), new BArray(getPngImageBytes(bis)));
- if (!isImage)
- cacheZipContentsStatic(bis, name, bdata, true);
- } else if (Rdr.isZipS(bis)) {
- cacheZipContentsStatic(bis, name, bdata, true);
- } else if (name == null){
- bdata.put("_DATA_", new BArray(Rdr.getLimitedStreamBytes(bis, -1)));
- } else {
- throw new IOException("ZIP file " + name + " not found");
- }
- bdata.put("$_BINARY_$", Boolean.TRUE);
- } catch (IOException e) {
- bdata.clear();
- bdata.put("_ERROR_", e.getMessage());
- }
- }
-
- @Override
- public String cacheZipContents(BufferedInputStream bis,
- String fileName,
- Map<String, Object> cache,
- boolean asByteArray) {
- return cacheZipContentsStatic(bis, fileName, cache, asByteArray);
- }
-
- /**
- *
- * @param bis
- * @param fileName may end with "/" for a prefix or contain "|xxxx.xxx" for a specific file or be null
- * @param cache
- * @param asByteArray
- * @return
- */
- public static String cacheZipContentsStatic(BufferedInputStream bis,
- String fileName, Map<String, Object> cache, boolean asByteArray) {
- ZipInputStream zis = (ZipInputStream) newZIS(bis);
- ZipEntry ze;
- SB listing = new SB();
- long n = 0;
- boolean isPath = (fileName != null && fileName.endsWith("/"));
- boolean oneFile = (asByteArray && !isPath && fileName != null);
- int pt = (oneFile ? fileName.indexOf("|") : -1);
- String file0 = (pt >= 0 ? fileName : null);
- if (pt >= 0)
- fileName = fileName.substring(0, pt);
- String prefix = (fileName == null ? "" : isPath ? fileName : fileName + "|");
- try {
- while ((ze = zis.getNextEntry()) != null) {
- String name = ze.getName();
- if (fileName != null) {
- if (oneFile) {
- if (!name.equalsIgnoreCase(fileName))
- continue;
- } else {
- listing.append(name).appendC('\n');
- }
- }
- long nBytes = ze.getSize();
- byte[] bytes = Rdr.getLimitedStreamBytes(zis, nBytes);
- if (file0 != null) {
- readFileAsMapStatic(Rdr.getBIS(bytes), cache, file0);
- return null;
- }
- n += bytes.length;
- Object o = (asByteArray ? new BArray(bytes) : bytes);
- cache.put((oneFile ? "_DATA_" : prefix + name), o);
- if (oneFile)
- break;
- }
- zis.close();
- } catch (Exception e) {
- try {
- zis.close();
- } catch (IOException e1) {
- }
- return null;
- }
- if (n == 0 || fileName == null)
- return null;
- System.out.println("ZipTools cached " + n + " bytes from " + fileName);
- return listing.toString();
- }
-
- private static byte[] getPngImageBytes(BufferedInputStream bis) {
- try {
- if (Rdr.isPngZipStream(bis)) {
- int pt_count[] = new int[2];
- Rdr.getPngZipPointAndCount(bis, pt_count);
- if (pt_count[1] != 0)
- return deActivatePngZipB(Rdr.getLimitedStreamBytes(bis, pt_count[0]));
- }
- return Rdr.getLimitedStreamBytes(bis, -1);
- } catch (IOException e) {
- return null;
- }
- }
-
- /**
- * Once a PNGJ image has been extracted, we want to red-line its
- * iTXt "Jmol Type PNGJ" tag, since it is no longer associated with
- * ZIP data.
- *
- * @param bytes
- * @return disfigured bytes
- *
- */
- private static byte[] deActivatePngZipB(byte[] bytes) {
- // \0PNGJ starting at byte 50 changed to \0 NGJ
- if (Rdr.isPngZipB(bytes))
- bytes[51] = 32;
- return bytes;
- }
-
-
-
-}