X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=unused%2Fjavajs%2Futil%2FZipTools.java;fp=unused%2Fjavajs%2Futil%2FZipTools.java;h=5c6e4ec6195ffaeb12bf5907c8d49b95f898b7c9;hb=65740880573a48adc758bec3939ece9d9ae104dd;hp=0000000000000000000000000000000000000000;hpb=71aa78b8a7d54e5aeb6b278310dfd735efb77477;p=jalview.git diff --git a/unused/javajs/util/ZipTools.java b/unused/javajs/util/ZipTools.java new file mode 100644 index 0000000..5c6e4ec --- /dev/null +++ b/unused/javajs/util/ZipTools.java @@ -0,0 +1,462 @@ +/* $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 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 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 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 bdata, String name) { + readFileAsMapStatic(bis, bdata, name); + } + + public static void readFileAsMapStatic(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) + 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 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 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; + } + + + +}