You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by da...@apache.org on 2013/05/19 11:36:18 UTC
svn commit: r1484246 - in /commons/proper/compress/trunk: ./
src/main/java/org/apache/commons/compress/archivers/
src/main/java/org/apache/commons/compress/archivers/arj/
src/main/java/org/apache/commons/compress/archivers/sevenz/
src/main/java/org/apa...
Author: damjan
Date: Sun May 19 09:36:17 2013
New Revision: 1484246
URL: http://svn.apache.org/r1484246
Log:
Add initial support for ARJ archives.
Document it.
We only support reading at the moment,
and only support the STORED (absense of) compression
with no encryption or multi-volume support.
Jira issue key: COMPRESS-226
Added:
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/arj/
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/arj/ArjArchiveEntry.java (with props)
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/arj/ArjArchiveInputStream.java (with props)
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/arj/LocalFileHeader.java (with props)
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/arj/MainHeader.java (with props)
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/arj/package.html (with props)
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/utils/BoundedInputStream.java (with props)
Modified:
commons/proper/compress/trunk/pom.xml
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/ArchiveStreamFactory.java
commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZFile.java
commons/proper/compress/trunk/src/site/xdoc/examples.xml
commons/proper/compress/trunk/src/site/xdoc/index.xml
Modified: commons/proper/compress/trunk/pom.xml
URL: http://svn.apache.org/viewvc/commons/proper/compress/trunk/pom.xml?rev=1484246&r1=1484245&r2=1484246&view=diff
==============================================================================
--- commons/proper/compress/trunk/pom.xml (original)
+++ commons/proper/compress/trunk/pom.xml Sun May 19 09:36:17 2013
@@ -31,7 +31,7 @@
<!-- The description is not indented to make it look better in the release notes -->
<description>
Apache Commons Compress software defines an API for working with compression and archive formats.
-These include: bzip2, gzip, pack200, xz and ar, cpio, jar, tar, zip, dump, 7z.
+These include: bzip2, gzip, pack200, xz and ar, cpio, jar, tar, zip, dump, 7z, arj.
</description>
<properties>
Modified: commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/ArchiveStreamFactory.java
URL: http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/ArchiveStreamFactory.java?rev=1484246&r1=1484245&r2=1484246&view=diff
==============================================================================
--- commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/ArchiveStreamFactory.java (original)
+++ commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/ArchiveStreamFactory.java Sun May 19 09:36:17 2013
@@ -25,6 +25,7 @@ import java.io.OutputStream;
import org.apache.commons.compress.archivers.ar.ArArchiveInputStream;
import org.apache.commons.compress.archivers.ar.ArArchiveOutputStream;
+import org.apache.commons.compress.archivers.arj.ArjArchiveInputStream;
import org.apache.commons.compress.archivers.cpio.CpioArchiveInputStream;
import org.apache.commons.compress.archivers.cpio.CpioArchiveOutputStream;
import org.apache.commons.compress.archivers.dump.DumpArchiveInputStream;
@@ -79,6 +80,11 @@ public class ArchiveStreamFactory {
*/
public static final String AR = "ar";
/**
+ * Constant used to identify the ARJ archive format.
+ * @since 1.6
+ */
+ public static final String ARJ = "arj";
+ /**
* Constant used to identify the CPIO archive format.
* @since 1.1
*/
@@ -110,8 +116,8 @@ public class ArchiveStreamFactory {
private String entryEncoding = null;
/**
- * Returns the encoding to use for zip and tar files, or null for
- * the default.
+ * Returns the encoding to use for arj, zip and tar files,
+ * or null for the default.
*
* @return entry encoding, or null
* @since 1.5
@@ -121,8 +127,8 @@ public class ArchiveStreamFactory {
}
/**
- * Sets the encoding to use for zip and tar files. Use null for
- * the default.
+ * Sets the encoding to use for arj, zip and tar files.
+ * Use null for the default.
*
* @since 1.5
*/
@@ -133,7 +139,7 @@ public class ArchiveStreamFactory {
/**
* Create an archive input stream from an archiver name and an input stream.
*
- * @param archiverName the archive name, i.e. "ar", "zip", "tar", "jar", "dump" or "cpio"
+ * @param archiverName the archive name, i.e. "ar", "arj", "zip", "tar", "jar", "dump" or "cpio"
* @param in the input stream
* @return the archive input stream
* @throws ArchiveException if the archiver name is not known
@@ -154,6 +160,13 @@ public class ArchiveStreamFactory {
if (AR.equalsIgnoreCase(archiverName)) {
return new ArArchiveInputStream(in);
}
+ if (ARJ.equalsIgnoreCase(archiverName)) {
+ if (entryEncoding != null) {
+ return new ArjArchiveInputStream(in, entryEncoding);
+ } else {
+ return new ArjArchiveInputStream(in);
+ }
+ }
if (ZIP.equalsIgnoreCase(archiverName)) {
if (entryEncoding != null) {
return new ZipArchiveInputStream(in, entryEncoding);
@@ -263,6 +276,8 @@ public class ArchiveStreamFactory {
return new ArArchiveInputStream(in);
} else if (CpioArchiveInputStream.matches(signature, signatureLength)) {
return new CpioArchiveInputStream(in);
+ } else if (ArjArchiveInputStream.matches(signature, signatureLength)) {
+ return new ArjArchiveInputStream(in);
}
// Dump needs a bigger buffer to check the signature;
Added: commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/arj/ArjArchiveEntry.java
URL: http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/arj/ArjArchiveEntry.java?rev=1484246&view=auto
==============================================================================
--- commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/arj/ArjArchiveEntry.java (added)
+++ commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/arj/ArjArchiveEntry.java Sun May 19 09:36:17 2013
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.commons.compress.archivers.arj;
+
+import java.io.File;
+import java.util.Date;
+import java.util.regex.Matcher;
+
+import org.apache.commons.compress.archivers.ArchiveEntry;
+import org.apache.commons.compress.archivers.zip.ZipUtil;
+
+/**
+ * An entry in an ARJ archive.
+ *
+ * @NotThreadSafe
+ */
+public class ArjArchiveEntry implements ArchiveEntry {
+ private final LocalFileHeader localFileHeader;
+
+ public ArjArchiveEntry() {
+ localFileHeader = new LocalFileHeader();
+ }
+
+ ArjArchiveEntry(final LocalFileHeader localFileHeader) {
+ this.localFileHeader = localFileHeader;
+ }
+
+ public String getName() {
+ if ((localFileHeader.arjFlags & LocalFileHeader.Flags.PATHSYM) != 0) {
+ return localFileHeader.name.replaceAll("/",
+ Matcher.quoteReplacement(File.separator));
+ } else {
+ return localFileHeader.name;
+ }
+ }
+
+ public long getSize() {
+ return localFileHeader.originalSize;
+ }
+
+ public boolean isDirectory() {
+ return localFileHeader.fileType == LocalFileHeader.FileTypes.DIRECTORY;
+ }
+
+ public Date getLastModifiedDate() {
+ return new Date(ZipUtil.dosToJavaTime(
+ 0xffffFFFFL & localFileHeader.dateTimeModified));
+ }
+}
Propchange: commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/arj/ArjArchiveEntry.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/arj/ArjArchiveInputStream.java
URL: http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/arj/ArjArchiveInputStream.java?rev=1484246&view=auto
==============================================================================
--- commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/arj/ArjArchiveInputStream.java (added)
+++ commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/arj/ArjArchiveInputStream.java Sun May 19 09:36:17 2013
@@ -0,0 +1,321 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.commons.compress.archivers.arj;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.EOFException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.zip.CRC32;
+
+import org.apache.commons.compress.archivers.ArchiveEntry;
+import org.apache.commons.compress.archivers.ArchiveException;
+import org.apache.commons.compress.archivers.ArchiveInputStream;
+import org.apache.commons.compress.utils.BoundedInputStream;
+import org.apache.commons.compress.utils.CRC32VerifyingInputStream;
+
+/**
+ * Implements the "arj" archive format as an InputStream.
+ * <p>
+ * <a href="http://farmanager.com/svn/trunk/plugins/multiarc/arc.doc/arj.txt">Reference</a>
+ * @NotThreadSafe
+ */
+public class ArjArchiveInputStream extends ArchiveInputStream {
+ private static final boolean DEBUG = false;
+ private static final int ARJ_MAGIC_1 = 0x60;
+ private static final int ARJ_MAGIC_2 = 0xEA;
+ private final DataInputStream in;
+ private final String charset;
+ private final MainHeader mainHeader;
+ private LocalFileHeader currentLocalFileHeader = null;
+ private InputStream currentInputStream = null;
+
+ /**
+ * Constructs the ArjInputStream, taking ownership of the inputStream that is passed in.
+ * @param inputStream the underlying stream, whose ownership is taken
+ * @param charset the charset used for file names and comments
+ * in the archive
+ * @throws IOException
+ */
+ public ArjArchiveInputStream(final InputStream inputStream,
+ final String charset) throws ArchiveException {
+ in = new DataInputStream(inputStream);
+ this.charset = charset;
+ try {
+ mainHeader = readMainHeader();
+ if ((mainHeader.arjFlags & MainHeader.Flags.GARBLED) != 0) {
+ throw new ArchiveException("Encrypted ARJ files are unsupported");
+ }
+ if ((mainHeader.arjFlags & MainHeader.Flags.VOLUME) != 0) {
+ throw new ArchiveException("Multi-volume ARJ files are unsupported");
+ }
+ } catch (IOException ioException) {
+ throw new ArchiveException(ioException.getMessage(), ioException);
+ }
+ }
+
+ /**
+ * Constructs the ArjInputStream, taking ownership of the inputStream that is passed in,
+ * and using the CP437 character encoding.
+ * @param inputStream the underlying stream, whose ownership is taken
+ * @throws IOException
+ */
+ public ArjArchiveInputStream(final InputStream inputStream)
+ throws ArchiveException {
+ this(inputStream, "CP437");
+ }
+
+ @Override
+ public void close() {
+ try {
+ in.close();
+ } catch (IOException ignored) {
+ }
+ }
+
+ private static final void debug(final String message) {
+ if (DEBUG) {
+ System.out.println(message);
+ }
+ }
+
+ private static final int read16(final DataInputStream in) throws IOException {
+ final int value = in.readUnsignedShort();
+ return Integer.reverseBytes(value) >>> 16;
+ }
+
+ private final String readString(final DataInputStream in) throws IOException {
+ final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+ int nextByte;
+ while ((nextByte = in.readUnsignedByte()) != 0) {
+ buffer.write(nextByte);
+ }
+ return new String(buffer.toByteArray(), charset);
+ }
+
+ private byte[] readHeader() throws IOException {
+ boolean found = false;
+ byte[] basicHeaderBytes = null;
+ do {
+ int first = 0;
+ int second = in.readUnsignedByte();
+ do {
+ first = second;
+ second = in.readUnsignedByte();
+ } while (first != ARJ_MAGIC_1 && second != ARJ_MAGIC_2);
+ final int basicHeaderSize = read16(in);
+ if (basicHeaderSize == 0) {
+ // end of archive
+ return null;
+ }
+ if (basicHeaderSize <= 2600) {
+ basicHeaderBytes = new byte[basicHeaderSize];
+ in.readFully(basicHeaderBytes);
+ final int basicHeaderCrc32 = Integer.reverseBytes(in.readInt());
+ final CRC32 crc32 = new CRC32();
+ crc32.update(basicHeaderBytes);
+ if (basicHeaderCrc32 == (int)crc32.getValue()) {
+ found = true;
+ }
+ }
+ } while (!found);
+ return basicHeaderBytes;
+ }
+
+ private MainHeader readMainHeader() throws IOException {
+ final byte[] basicHeaderBytes = readHeader();
+ if (basicHeaderBytes == null) {
+ throw new IOException("Archive ends without any headers");
+ }
+ final DataInputStream basicHeader = new DataInputStream(
+ new ByteArrayInputStream(basicHeaderBytes));
+
+ final int firstHeaderSize = basicHeader.readUnsignedByte();
+ final byte[] firstHeaderBytes = new byte[firstHeaderSize - 1];
+ basicHeader.readFully(firstHeaderBytes);
+ final DataInputStream firstHeader = new DataInputStream(
+ new ByteArrayInputStream(firstHeaderBytes));
+
+ final MainHeader mainHeader = new MainHeader();
+ mainHeader.archiverVersionNumber = firstHeader.readUnsignedByte();
+ mainHeader.minVersionToExtract = firstHeader.readUnsignedByte();
+ mainHeader.hostOS = firstHeader.readUnsignedByte();
+ mainHeader.arjFlags = firstHeader.readUnsignedByte();
+ mainHeader.securityVersion = firstHeader.readUnsignedByte();
+ mainHeader.fileType = firstHeader.readUnsignedByte();
+ mainHeader.reserved = firstHeader.readUnsignedByte();
+ mainHeader.dateTimeCreated = Integer.reverseBytes(firstHeader.readInt());
+ mainHeader.dateTimeModified = Integer.reverseBytes(firstHeader.readInt());
+ mainHeader.archiveSize = 0xffffFFFFL & Integer.reverseBytes(firstHeader.readInt());
+ mainHeader.securityEnvelopeFilePosition = Integer.reverseBytes(firstHeader.readInt());
+ mainHeader.fileSpecPosition = read16(firstHeader);
+ mainHeader.securityEnvelopeLength = read16(firstHeader);
+ mainHeader.encryptionVersion = firstHeader.readUnsignedByte();
+ mainHeader.lastChapter = firstHeader.readUnsignedByte();
+
+ try {
+ mainHeader.arjProtectionFactor = firstHeader.readUnsignedByte();
+ mainHeader.arjFlags2 = firstHeader.readUnsignedByte();
+ firstHeader.readUnsignedByte();
+ firstHeader.readUnsignedByte();
+ } catch (EOFException eof) {
+ }
+
+ mainHeader.name = readString(basicHeader);
+ mainHeader.comment = readString(basicHeader);
+
+ final int extendedHeaderSize = read16(in);
+ if (extendedHeaderSize > 0) {
+ mainHeader.extendedHeaderBytes = new byte[extendedHeaderSize];
+ in.readFully(mainHeader.extendedHeaderBytes);
+ final int extendedHeaderCrc32 = Integer.reverseBytes(in.readInt());
+ final CRC32 crc32 = new CRC32();
+ crc32.update(mainHeader.extendedHeaderBytes);
+ if (extendedHeaderCrc32 != (int)crc32.getValue()) {
+ throw new IOException("Extended header CRC32 verification failure");
+ }
+ }
+
+ debug(mainHeader.toString());
+
+ return mainHeader;
+ }
+
+ private LocalFileHeader readLocalFileHeader() throws IOException {
+ final byte[] basicHeaderBytes = readHeader();
+ if (basicHeaderBytes == null) {
+ return null;
+ }
+ final DataInputStream basicHeader = new DataInputStream(
+ new ByteArrayInputStream(basicHeaderBytes));
+
+ final int firstHeaderSize = basicHeader.readUnsignedByte();
+ final byte[] firstHeaderBytes = new byte[firstHeaderSize - 1];
+ basicHeader.readFully(firstHeaderBytes);
+ final DataInputStream firstHeader = new DataInputStream(
+ new ByteArrayInputStream(firstHeaderBytes));
+
+ final LocalFileHeader localFileHeader = new LocalFileHeader();
+ localFileHeader.archiverVersionNumber = firstHeader.readUnsignedByte();
+ localFileHeader.minVersionToExtract = firstHeader.readUnsignedByte();
+ localFileHeader.hostOS = firstHeader.readUnsignedByte();
+ localFileHeader.arjFlags = firstHeader.readUnsignedByte();
+ localFileHeader.method = firstHeader.readUnsignedByte();
+ localFileHeader.fileType = firstHeader.readUnsignedByte();
+ localFileHeader.reserved = firstHeader.readUnsignedByte();
+ localFileHeader.dateTimeModified = Integer.reverseBytes(firstHeader.readInt());
+ localFileHeader.compressedSize = 0xffffFFFFL & Integer.reverseBytes(firstHeader.readInt());
+ localFileHeader.originalSize = 0xffffFFFFL & Integer.reverseBytes(firstHeader.readInt());
+ localFileHeader.originalCrc32 = Integer.reverseBytes(firstHeader.readInt());
+ localFileHeader.fileSpecPosition = read16(firstHeader);
+ localFileHeader.fileAccessMode = read16(firstHeader);
+ localFileHeader.firstChapter = firstHeader.readUnsignedByte();
+ localFileHeader.lastChapter = firstHeader.readUnsignedByte();
+
+ try {
+ localFileHeader.extendedFilePosition = Integer.reverseBytes(firstHeader.readInt());
+ localFileHeader.dateTimeAccessed = Integer.reverseBytes(firstHeader.readInt());
+ localFileHeader.dateTimeCreated = Integer.reverseBytes(firstHeader.readInt());
+ localFileHeader.originalSizeEvenForVolumes = Integer.reverseBytes(firstHeader.readInt());
+ } catch (EOFException eof) {
+ }
+
+ localFileHeader.name = readString(basicHeader);
+ localFileHeader.comment = readString(basicHeader);
+
+ ArrayList<byte[]> extendedHeaders = new ArrayList<byte[]>();
+ int extendedHeaderSize;
+ while ((extendedHeaderSize = read16(in)) > 0) {
+ final byte[] extendedHeaderBytes = new byte[extendedHeaderSize];
+ in.readFully(extendedHeaderBytes);
+ final int extendedHeaderCrc32 = Integer.reverseBytes(in.readInt());
+ final CRC32 crc32 = new CRC32();
+ crc32.update(extendedHeaderBytes);
+ if (extendedHeaderCrc32 != (int)crc32.getValue()) {
+ throw new IOException("Extended header CRC32 verification failure");
+ }
+ extendedHeaders.add(extendedHeaderBytes);
+ }
+ localFileHeader.extendedHeaders = extendedHeaders.toArray(new byte[extendedHeaders.size()][]);
+
+ debug(localFileHeader.toString());
+
+ return localFileHeader;
+ }
+
+ public static boolean matches(final byte[] signature, final int length) {
+ return length >= 2 &&
+ (0xff & signature[0]) == ARJ_MAGIC_1 &&
+ (0xff & signature[1]) == ARJ_MAGIC_2;
+ }
+
+ public String getArchiveName() {
+ return mainHeader.name;
+ }
+
+ public String getArchiveComment() {
+ return mainHeader.comment;
+ }
+
+ @Override
+ public ArjArchiveEntry getNextEntry() throws IOException {
+ if (currentInputStream != null) {
+ while (currentInputStream.read() >= 0) {
+ }
+ currentLocalFileHeader = null;
+ currentInputStream = null;
+ }
+
+ currentLocalFileHeader = readLocalFileHeader();
+ if (currentLocalFileHeader != null) {
+ currentInputStream = new BoundedInputStream(in, currentLocalFileHeader.compressedSize);
+ if (currentLocalFileHeader.method == LocalFileHeader.Methods.STORED) {
+ currentInputStream = new CRC32VerifyingInputStream(currentInputStream,
+ currentLocalFileHeader.originalSize, currentLocalFileHeader.originalCrc32);
+ }
+ return new ArjArchiveEntry(currentLocalFileHeader);
+ } else {
+ currentInputStream = null;
+ return null;
+ }
+ }
+
+ @Override
+ public boolean canReadEntryData(ArchiveEntry ae) {
+ return currentLocalFileHeader.method == LocalFileHeader.Methods.STORED;
+ }
+
+ @Override
+ public int read() throws IOException {
+ if (currentLocalFileHeader.method != LocalFileHeader.Methods.STORED) {
+ throw new IOException("Unsupported compression method " + currentLocalFileHeader.method);
+ }
+ return currentInputStream.read();
+ }
+
+ @Override
+ public int read(final byte[] b, final int off, final int len) throws IOException {
+ if (currentLocalFileHeader.method != LocalFileHeader.Methods.STORED) {
+ throw new IOException("Unsupported compression method " + currentLocalFileHeader.method);
+ }
+ return currentInputStream.read(b, off, len);
+ }
+}
Propchange: commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/arj/ArjArchiveInputStream.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/arj/LocalFileHeader.java
URL: http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/arj/LocalFileHeader.java?rev=1484246&view=auto
==============================================================================
--- commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/arj/LocalFileHeader.java (added)
+++ commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/arj/LocalFileHeader.java Sun May 19 09:36:17 2013
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.commons.compress.archivers.arj;
+
+import java.util.Arrays;
+
+class LocalFileHeader {
+ int archiverVersionNumber;
+ int minVersionToExtract;
+ int hostOS;
+ int arjFlags;
+ int method;
+ int fileType;
+ int reserved;
+ int dateTimeModified;
+ long compressedSize;
+ long originalSize;
+ int originalCrc32;
+ int fileSpecPosition;
+ int fileAccessMode;
+ int firstChapter;
+ int lastChapter;
+
+ int extendedFilePosition;
+ int dateTimeAccessed;
+ int dateTimeCreated;
+ int originalSizeEvenForVolumes;
+
+ String name;
+ String comment;
+
+ byte[][] extendedHeaders = null;
+
+ static class Flags {
+ static final int GARBLED = 0x01;
+ static final int VOLUME = 0x04;
+ static final int EXTFILE = 0x08;
+ static final int PATHSYM = 0x10;
+ static final int BACKUP = 0x20;
+ }
+
+ static class FileTypes {
+ static final int BINARY = 0;
+ static final int SEVEN_BIT_TEXT = 1;
+ static final int DIRECTORY = 3;
+ static final int VOLUME_LABEL = 4;
+ static final int CHAPTER_LABEL = 5;
+ }
+
+ static class Methods {
+ static final int STORED = 0;
+ static final int COMPRESSED_MOST = 1;
+ static final int COMPRESSED_FASTEST = 4;
+ static final int NO_DATA_NO_CRC = 8;
+ static final int NO_DATA = 9;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("LocalFileHeader [archiverVersionNumber=");
+ builder.append(archiverVersionNumber);
+ builder.append(", minVersionToExtract=");
+ builder.append(minVersionToExtract);
+ builder.append(", hostOS=");
+ builder.append(hostOS);
+ builder.append(", arjFlags=");
+ builder.append(arjFlags);
+ builder.append(", method=");
+ builder.append(method);
+ builder.append(", fileType=");
+ builder.append(fileType);
+ builder.append(", reserved=");
+ builder.append(reserved);
+ builder.append(", dateTimeModified=");
+ builder.append(dateTimeModified);
+ builder.append(", compressedSize=");
+ builder.append(compressedSize);
+ builder.append(", originalSize=");
+ builder.append(originalSize);
+ builder.append(", originalCrc32=");
+ builder.append(originalCrc32);
+ builder.append(", fileSpecPosition=");
+ builder.append(fileSpecPosition);
+ builder.append(", fileAccessMode=");
+ builder.append(fileAccessMode);
+ builder.append(", firstChapter=");
+ builder.append(firstChapter);
+ builder.append(", lastChapter=");
+ builder.append(lastChapter);
+ builder.append(", extendedFilePosition=");
+ builder.append(extendedFilePosition);
+ builder.append(", dateTimeAccessed=");
+ builder.append(dateTimeAccessed);
+ builder.append(", dateTimeCreated=");
+ builder.append(dateTimeCreated);
+ builder.append(", originalSizeEvenForVolumes=");
+ builder.append(originalSizeEvenForVolumes);
+ builder.append(", name=");
+ builder.append(name);
+ builder.append(", comment=");
+ builder.append(comment);
+ builder.append(", extendedHeaders=");
+ builder.append(Arrays.toString(extendedHeaders));
+ builder.append("]");
+ return builder.toString();
+ }
+}
Propchange: commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/arj/LocalFileHeader.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/arj/MainHeader.java
URL: http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/arj/MainHeader.java?rev=1484246&view=auto
==============================================================================
--- commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/arj/MainHeader.java (added)
+++ commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/arj/MainHeader.java Sun May 19 09:36:17 2013
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.commons.compress.archivers.arj;
+
+import java.util.Arrays;
+
+class MainHeader {
+ int archiverVersionNumber;
+ int minVersionToExtract;
+ int hostOS;
+ int arjFlags;
+ int securityVersion;
+ int fileType;
+ int reserved;
+ int dateTimeCreated;
+ int dateTimeModified;
+ long archiveSize;
+ int securityEnvelopeFilePosition;
+ int fileSpecPosition;
+ int securityEnvelopeLength;
+ int encryptionVersion;
+ int lastChapter;
+ int arjProtectionFactor;
+ int arjFlags2;
+ String name;
+ String comment;
+ byte[] extendedHeaderBytes = null;
+
+ static class Flags {
+ static final int GARBLED = 0x01;
+ static final int OLD_SECURED_NEW_ANSI_PAGE = 0x02;
+ static final int VOLUME = 0x04;
+ static final int ARJPROT = 0x08;
+ static final int PATHSYM = 0x10;
+ static final int BACKUP = 0x20;
+ static final int SECURED = 0x40;
+ static final int ALTNAME = 0x80;
+ }
+
+
+ @Override
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("MainHeader [archiverVersionNumber=");
+ builder.append(archiverVersionNumber);
+ builder.append(", minVersionToExtract=");
+ builder.append(minVersionToExtract);
+ builder.append(", hostOS=");
+ builder.append(hostOS);
+ builder.append(", arjFlags=");
+ builder.append(arjFlags);
+ builder.append(", securityVersion=");
+ builder.append(securityVersion);
+ builder.append(", fileType=");
+ builder.append(fileType);
+ builder.append(", reserved=");
+ builder.append(reserved);
+ builder.append(", dateTimeCreated=");
+ builder.append(dateTimeCreated);
+ builder.append(", dateTimeModified=");
+ builder.append(dateTimeModified);
+ builder.append(", archiveSize=");
+ builder.append(archiveSize);
+ builder.append(", securityEnvelopeFilePosition=");
+ builder.append(securityEnvelopeFilePosition);
+ builder.append(", fileSpecPosition=");
+ builder.append(fileSpecPosition);
+ builder.append(", securityEnvelopeLength=");
+ builder.append(securityEnvelopeLength);
+ builder.append(", encryptionVersion=");
+ builder.append(encryptionVersion);
+ builder.append(", lastChapter=");
+ builder.append(lastChapter);
+ builder.append(", arjProtectionFactor=");
+ builder.append(arjProtectionFactor);
+ builder.append(", arjFlags2=");
+ builder.append(arjFlags2);
+ builder.append(", name=");
+ builder.append(name);
+ builder.append(", comment=");
+ builder.append(comment);
+ builder.append(", extendedHeaderBytes=");
+ builder.append(Arrays.toString(extendedHeaderBytes));
+ builder.append("]");
+ return builder.toString();
+ }
+}
Propchange: commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/arj/MainHeader.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/arj/package.html
URL: http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/arj/package.html?rev=1484246&view=auto
==============================================================================
--- commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/arj/package.html (added)
+++ commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/arj/package.html Sun May 19 09:36:17 2013
@@ -0,0 +1,24 @@
+<html>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+ <body>
+ <p>Provides stream classes for reading archives using
+ the ARJ format.</p>
+ </body>
+</html>
Propchange: commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/arj/package.html
------------------------------------------------------------------------------
svn:eol-style = native
Modified: commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZFile.java
URL: http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZFile.java?rev=1484246&r1=1484245&r2=1484246&view=diff
==============================================================================
--- commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZFile.java (original)
+++ commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/archivers/sevenz/SevenZFile.java Sun May 19 09:36:17 2013
@@ -28,6 +28,7 @@ import java.util.Arrays;
import java.util.BitSet;
import java.util.zip.CRC32;
+import org.apache.commons.compress.utils.BoundedInputStream;
import org.apache.commons.compress.utils.CRC32VerifyingInputStream;
/**
@@ -925,44 +926,4 @@ public class SevenZFile {
}
return value;
}
-
- private static class BoundedInputStream extends InputStream {
- private final InputStream in;
- private long bytesRemaining;
-
- public BoundedInputStream(final InputStream in, final long size) {
- this.in = in;
- bytesRemaining = size;
- }
-
- @Override
- public int read() throws IOException {
- if (bytesRemaining > 0) {
- --bytesRemaining;
- return in.read();
- } else {
- return -1;
- }
- }
-
- @Override
- public int read(byte[] b, int off, int len) throws IOException {
- if (bytesRemaining == 0) {
- return -1;
- }
- int bytesToRead = len;
- if (bytesToRead > bytesRemaining) {
- bytesToRead = (int) bytesRemaining;
- }
- final int bytesRead = in.read(b, off, bytesToRead);
- if (bytesRead >= 0) {
- bytesRemaining -= bytesRead;
- }
- return bytesRead;
- }
-
- @Override
- public void close() {
- }
- }
}
Added: commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/utils/BoundedInputStream.java
URL: http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/utils/BoundedInputStream.java?rev=1484246&view=auto
==============================================================================
--- commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/utils/BoundedInputStream.java (added)
+++ commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/utils/BoundedInputStream.java Sun May 19 09:36:17 2013
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.commons.compress.utils;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+public class BoundedInputStream extends InputStream {
+ private final InputStream in;
+ private long bytesRemaining;
+
+ public BoundedInputStream(final InputStream in, final long size) {
+ this.in = in;
+ bytesRemaining = size;
+ }
+
+ @Override
+ public int read() throws IOException {
+ if (bytesRemaining > 0) {
+ --bytesRemaining;
+ return in.read();
+ } else {
+ return -1;
+ }
+ }
+
+ @Override
+ public int read(byte[] b, int off, int len) throws IOException {
+ if (bytesRemaining == 0) {
+ return -1;
+ }
+ int bytesToRead = len;
+ if (bytesToRead > bytesRemaining) {
+ bytesToRead = (int) bytesRemaining;
+ }
+ final int bytesRead = in.read(b, off, bytesToRead);
+ if (bytesRead >= 0) {
+ bytesRemaining -= bytesRead;
+ }
+ return bytesRead;
+ }
+
+ @Override
+ public void close() {
+ }
+}
\ No newline at end of file
Propchange: commons/proper/compress/trunk/src/main/java/org/apache/commons/compress/utils/BoundedInputStream.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: commons/proper/compress/trunk/src/site/xdoc/examples.xml
URL: http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/site/xdoc/examples.xml?rev=1484246&r1=1484245&r2=1484246&view=diff
==============================================================================
--- commons/proper/compress/trunk/src/site/xdoc/examples.xml (original)
+++ commons/proper/compress/trunk/src/site/xdoc/examples.xml Sun May 19 09:36:17 2013
@@ -33,7 +33,7 @@
<p>The compressor formats supported are gzip, bzip2, xz and
Pack200, the archiver formats are ar, cpio, dump (read-only),
- tar, zip and 7z. Pack200 is a special case as it can only
+ tar, zip, 7z and arj. Pack200 is a special case as it can only
compress JAR files.</p>
</subsection>
@@ -439,6 +439,20 @@ LOOP UNTIL entry.getSize() HAS BEEN READ
]]></source>
</subsection>
+ <subsection name="arj">
+
+ <p>Uncompressing a given arj archive (you would
+ certainly add exception handling and make sure all streams
+ get closed properly):</p>
+<source><![CDATA[
+ArjArchiveEntry entry = arjInput.getNextEntry();
+byte[] content = new byte[entry.getSize()];
+LOOP UNTIL entry.getSize() HAS BEEN READ {
+ arjInput.read(content, offset, content.length - offset);
+}
+]]></source>
+ </subsection>
+
</section>
</body>
</document>
Modified: commons/proper/compress/trunk/src/site/xdoc/index.xml
URL: http://svn.apache.org/viewvc/commons/proper/compress/trunk/src/site/xdoc/index.xml?rev=1484246&r1=1484245&r2=1484246&view=diff
==============================================================================
--- commons/proper/compress/trunk/src/site/xdoc/index.xml (original)
+++ commons/proper/compress/trunk/src/site/xdoc/index.xml Sun May 19 09:36:17 2013
@@ -27,7 +27,7 @@
<p>
The Apache Commons Compress library defines an API for
working with ar, cpio, Unix dump, tar, zip, gzip, XZ, Pack200,
- bzip2 and 7z files.
+ bzip2, 7z and arj files.
</p>
<p>
The code in this component has many origins:
@@ -72,11 +72,11 @@
domain <a href="http://tukaani.org/xz/java.html">XZ for
Java</a> library.</p>
- <p>The ar, cpio, dump, tar, 7z and zip formats are supported as
+ <p>The ar, arj, cpio, dump, tar, 7z and zip formats are supported as
archivers where the <a href="zip.html">zip</a>
implementation provides capabilities that go beyond the
features found in java.util.zip. As of Commons Compress
- 1.3 support for the dump format is read-only.</p>
+ 1.3 support for the dump, 7z and arj formats is read-only.</p>
<p>The compress component provides abstract base classes for
compressors and archivers together with factories that can