/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * Copyright (c) 2013, MPL CodeInside http://codeinside.ru */ package ru.codeinside.gws.core; import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream; import ru.codeinside.gws.api.CryptoProvider; import ru.codeinside.gws.api.Enclosure; import javax.xml.bind.DatatypeConverter; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.LinkedHashMap; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; final public class Zip { final static Logger LOG = Logger.getLogger(Zip.class.getName()); static Map<String, Enclosure> collectAttachments(final InputStream in) { final Map<String, Enclosure> attachments = new LinkedHashMap<String, Enclosure>(); ZipArchiveInputStream zip = null; try { zip = new ZipArchiveInputStream(in); while (true) { final ZipArchiveEntry zipEntry = zip.getNextZipEntry(); if (zipEntry == null) { break; } if (zipEntry.isDirectory()) { continue; } final long total = zipEntry.getSize(); zipEntry.getExtra(); final byte[] content; if (total >= 0) { content = readWithTOC(zip, (int) total); } else { content = readWithDynamicSize(zip); } String zipPath = zipEntry.getName(); int slash = zipPath.lastIndexOf('/'); if (slash < 0) { slash = 0; } attachments.put(zipPath, new Enclosure(zipPath, zipPath.substring(slash), content)); } } catch (IOException e) { LOG.log(Level.WARNING, "unzip fail", e); } finally { if (zip != null) { try { zip.close(); } catch (IOException e) { // } } } return attachments; } public static String toBinaryData(final Enclosure[] enclosures, CryptoProvider cryptoProvider) throws IOException { final ByteArrayOutputStream baos = new ByteArrayOutputStream(); final ZipOutputStream zos = new ZipOutputStream(baos); zos.setLevel(9); for (final Enclosure enclosure : enclosures) { { final ZipEntry entry = new ZipEntry(enclosure.zipPath); entry.setSize(enclosure.content.length); entry.setTime(System.currentTimeMillis()); zos.putNextEntry(entry); zos.write(enclosure.content); } if (enclosure.signature != null && enclosure.signature.valid) { final byte[] content = cryptoProvider.toPkcs7(enclosure.signature); final ZipEntry sig = new ZipEntry(enclosure.zipPath + ".sig"); sig.setSize(content.length); sig.setTime(System.currentTimeMillis()); zos.putNextEntry(sig); zos.write(content); } } zos.close(); return DatatypeConverter.printBase64Binary(baos.toByteArray()); } private static byte[] readWithTOC(final ZipArchiveInputStream zis, final int total) throws IOException { final byte[] content = new byte[total]; int offset = 0; int read; while (offset < total && (read = zis.read(content, offset, total - offset)) != -1) { offset += read; } return content; } private static byte[] readWithDynamicSize(final ZipArchiveInputStream zis) throws IOException { final ByteArrayOutputStream bos = new ByteArrayOutputStream(); int c; while ((c = zis.read()) != -1) { bos.write(c); } return bos.toByteArray(); } }