X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2Fjavajs%2Futil%2FZipTools.java;h=deed8c895a19657b54ded9b552158d7b7a9670d9;hb=b9b7a352eee79b7764c3b09c9d19663075061d8c;hp=c7b21a29dbd5c371a93c00bef5085f53940f70d3;hpb=8ffd05b3abe52c0b6b79b011c0966361f82d5fe6;p=jalviewjs.git diff --git a/src/javajs/util/ZipTools.java b/src/javajs/util/ZipTools.java index c7b21a2..deed8c8 100644 --- a/src/javajs/util/ZipTools.java +++ b/src/javajs/util/ZipTools.java @@ -1,432 +1,432 @@ -/* $RCSfile$ - * $Author$ - * $Date$ - * $Revision$ - * - * 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 javajs.J2SIgnoreImport; -import javajs.api.GenericZipInputStream; -import javajs.api.GenericZipTools; -import javajs.api.ZInputStream; - -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; - - -/** - * Note the JSmol/HTML5 must use its own version of java.util.zip.ZipOutputStream. - * - */ -@J2SIgnoreImport({ java.util.zip.ZipOutputStream.class }) -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, - Map 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))) - 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"; - fileData.put(name0 + "|" + name, 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 v = new Lst(); - 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 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) { - /** - * @j2sNative - * - * 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 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) - cacheZipContents(bis, name, bdata, true); - } else if (Rdr.isZipS(bis)) { - cacheZipContents(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 cache, - boolean asByteArray) { - ZipInputStream zis = (ZipInputStream) newZIS(bis); - ZipEntry ze; - SB listing = new SB(); - long n = 0; - boolean oneFile = (asByteArray && fileName != null); - int pt = (oneFile ? fileName.indexOf("|") : -1); - String file0 = (pt >= 0 ? fileName : null); - if (pt >= 0) - fileName = fileName.substring(0, pt); - 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) { - readFileAsMap(Rdr.getBIS(bytes), cache, file0); - return null; - } - n += bytes.length; - Object o = (asByteArray ? new BArray(bytes) : bytes); - cache.put((oneFile ? "_DATA_" : (fileName == null ? "" : fileName + "|") + 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; - } - - - -} +/* $RCSfile$ + * $Author$ + * $Date$ + * $Revision$ + * + * 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 javajs.J2SIgnoreImport; +import javajs.api.GenericZipInputStream; +import javajs.api.GenericZipTools; +import javajs.api.ZInputStream; + +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; + + +/** + * Note the JSmol/HTML5 must use its own version of java.util.zip.ZipOutputStream. + * + */ +@J2SIgnoreImport({ java.util.zip.ZipOutputStream.class }) +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, + Map 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))) + 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"; + fileData.put(name0 + "|" + name, 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 v = new Lst(); + 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 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) { + /** + * @j2sNative + * + * 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 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) + cacheZipContents(bis, name, bdata, true); + } else if (Rdr.isZipS(bis)) { + cacheZipContents(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 cache, + boolean asByteArray) { + ZipInputStream zis = (ZipInputStream) newZIS(bis); + ZipEntry ze; + SB listing = new SB(); + long n = 0; + boolean oneFile = (asByteArray && fileName != null); + int pt = (oneFile ? fileName.indexOf("|") : -1); + String file0 = (pt >= 0 ? fileName : null); + if (pt >= 0) + fileName = fileName.substring(0, pt); + 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) { + readFileAsMap(Rdr.getBIS(bytes), cache, file0); + return null; + } + n += bytes.length; + Object o = (asByteArray ? new BArray(bytes) : bytes); + cache.put((oneFile ? "_DATA_" : (fileName == null ? "" : fileName + "|") + 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; + } + + + +}