001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied.  See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019package org.apache.commons.compress.archivers;
020
021import java.io.IOException;
022import java.nio.file.Path;
023import java.util.Date;
024
025/**
026 * An entry of an archive.
027 */
028public interface ArchiveEntry {
029
030    /**
031     * Special value ({@value}) indicating that the size is unknown.
032     */
033    long SIZE_UNKNOWN = -1;
034
035    /**
036     * Gets the last modified date of this entry.
037     *
038     * @return the last modified date of this entry.
039     * @since 1.1
040     */
041    Date getLastModifiedDate();
042
043    /**
044     * Gets the name of the entry in this archive. May refer to a file or directory or other item.
045     * <p>
046     * This method returns the raw name as it is stored inside of the archive.
047     * </p>
048     *
049     * @return The name of this entry in the archive.
050     */
051    String getName();
052
053    /**
054     * Gets the uncompressed size of this entry. May be -1 (SIZE_UNKNOWN) if the size is unknown
055     *
056     * @return the uncompressed size of this entry.
057     */
058    long getSize();
059
060    /**
061     * Tests whether this entry refers to a directory (true).
062     *
063     * @return true if this entry refers to a directory.
064     */
065    boolean isDirectory();
066
067    /**
068     * Resolves this entry in the given parent Path.
069     *
070     * @param parentPath the {@link Path#resolve(Path)} receiver.
071     * @return a resolved and normalized Path.
072     * @throws IOException if this method detects a Zip slip.
073     * @since 1.26.0
074     */
075    default Path resolveIn(final Path parentPath) throws IOException {
076        final String name = getName();
077        final Path outputFile = parentPath.resolve(name).normalize();
078        if (!outputFile.startsWith(parentPath)) {
079            throw new IOException(String.format("Zip slip '%s' + '%s' -> '%s'", parentPath, name, outputFile));
080        }
081        return outputFile;
082    }
083
084}