202N/A/*
202N/A * CDDL HEADER START
202N/A *
202N/A * The contents of this file are subject to the terms of the
202N/A * Common Development and Distribution License (the "License").
202N/A * You may not use this file except in compliance with the License.
202N/A *
202N/A * See LICENSE.txt included in this distribution for the specific
202N/A * language governing permissions and limitations under the License.
202N/A *
202N/A * When distributing Covered Code, include this CDDL HEADER in each
202N/A * file and include the License file at LICENSE.txt.
202N/A * If applicable, add the following below this CDDL HEADER, with the
202N/A * fields enclosed by brackets "[]" replaced with your own identifying
202N/A * information: Portions Copyright [yyyy] [name of copyright owner]
202N/A *
202N/A * CDDL HEADER END
202N/A */
202N/A
202N/A/*
202N/A * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
202N/A * Use is subject to license terms.
202N/A */
202N/A
202N/Apackage org.opensolaris.opengrok.analysis.archive;
202N/A
257N/Aimport java.io.IOException;
257N/Aimport java.io.InputStream;
202N/Aimport org.opensolaris.opengrok.analysis.FileAnalyzer;
202N/Aimport org.opensolaris.opengrok.analysis.FileAnalyzer.Genre;
202N/Aimport org.opensolaris.opengrok.analysis.FileAnalyzerFactory;
257N/Aimport org.opensolaris.opengrok.analysis.executables.JarAnalyzerFactory;
202N/A
439N/Apublic final class ZipAnalyzerFactory extends FileAnalyzerFactory {
202N/A private static final String[] SUFFIXES = {
202N/A "ZIP"
202N/A };
202N/A
419N/A private static final byte[] MAGIC = {'P', 'K', 3, 4};
257N/A
257N/A // Derived from /usr/src/cmd/file/file.c in OpenSolaris
257N/A private static final Matcher MATCHER = new Matcher() {
257N/A
257N/A private static final int LOCHDRSIZ = 30;
257N/A
257N/A private int CH(byte[] b, int n) {
257N/A return b[n] & 0xff;
257N/A }
257N/A
257N/A private int SH(byte[] b, int n) {
257N/A return CH(b, n) | (CH(b, n+1) << 8);
257N/A }
257N/A
257N/A private int LOCNAM(byte[] b) {
257N/A return SH(b, 26);
257N/A }
257N/A
257N/A private int LOCEXT(byte[] b) {
257N/A return SH(b, 28);
257N/A }
257N/A
257N/A private static final int XFHSIZ = 4;
257N/A
257N/A public FileAnalyzerFactory isMagic(byte[] contents, InputStream in)
257N/A throws IOException {
257N/A assert in.markSupported();
395N/A if (contents.length < MAGIC.length) {
395N/A return null;
395N/A }
257N/A for (int i = 0; i < MAGIC.length; i++) {
395N/A if (contents[i] != MAGIC[i]) {
395N/A return null;
395N/A }
257N/A }
257N/A
257N/A byte[] buf = new byte[1024];
257N/A in.mark(buf.length);
257N/A int len = in.read(buf);
257N/A in.reset();
257N/A
257N/A int xoff = LOCHDRSIZ + LOCNAM(buf);
257N/A int xoff_end = Math.min(len, xoff + LOCEXT(buf));
257N/A
257N/A while ((xoff < xoff_end) && (len - xoff >= XFHSIZ)) {
257N/A int xfhid = SH(buf, xoff);
257N/A if (xfhid == 0xCAFE) {
257N/A return JarAnalyzerFactory.DEFAULT_INSTANCE;
257N/A }
257N/A int xfdatasiz = SH(buf, xoff + 2);
257N/A xoff += XFHSIZ + xfdatasiz;
257N/A }
257N/A
257N/A return ZipAnalyzerFactory.DEFAULT_INSTANCE;
257N/A }
257N/A
202N/A };
202N/A
257N/A public static final ZipAnalyzerFactory DEFAULT_INSTANCE =
257N/A new ZipAnalyzerFactory();
257N/A
257N/A private ZipAnalyzerFactory() {
483N/A super(null, SUFFIXES, null, MATCHER, null, Genre.XREFABLE);
202N/A }
202N/A
202N/A @Override
202N/A protected FileAnalyzer newAnalyzer() {
202N/A return new ZipAnalyzer(this);
202N/A }
202N/A}