org.archive.format.gzip.GZIPHeader Maven / Gradle / Ivy
package org.archive.format.gzip;
import java.io.IOException;
import java.io.OutputStream;
import org.archive.util.ByteOp;
import org.archive.util.io.CRCOutputStream;
public class GZIPHeader implements GZIPConstants {
GZIPStaticHeader staticHeader = null;
GZIPFExtraRecords records = null;
byte fileName[] = null;
int fileNameLength = -1;
byte comment[] = null;
int commentLength = -1;
int crc = -1;
/*
* +----+----+----+----+----+----+----+----+----+----+----+----+
* |ID1 |ID2 | CM |FLG | MTIME |XFL | OS | (more-->)
* +----+----+----+----+----+----+----+----+----+----+----+----+
* (if FLG.FEXTRA set)
* +---+---+=================================+
* | XLEN |...XLEN bytes of "extra field"...| (more-->)
* +---+---+=================================+
* ("extra field" is then composed of a series of)
* +---+---+---+---+==================================+
* |SI1|SI2| LEN |... LEN bytes of subfield data ...|
* +---+---+---+---+==================================+
* (if FLG.FNAME set)
* +=========================================+
* |...original file name, zero-terminated...| (more-->)
* +=========================================+
* (if FLG.FCOMMENT set)
* +===================================+
* |...file comment, zero-terminated...| (more-->)
* +===================================+
* (if FLG.FHCRC set)
* +---+---+
* | CRC16 |
* +---+---+
*/
public GZIPHeader() {
staticHeader = new GZIPStaticHeader();
records = null;
fileName = null;
fileNameLength = 0;
comment = null;
commentLength = 0;
crc = -1;
}
public GZIPHeader(GZIPStaticHeader staticHeader) {
this.staticHeader = staticHeader;
records = null;
fileName = null;
fileNameLength = 0;
comment = null;
commentLength = 0;
crc = -1;
}
public GZIPStaticHeader getStaticHeader() {
return staticHeader;
}
public byte[] getFileName() {
return fileName;
}
public byte[] getComment() {
return comment;
}
public long getFNameLength() {
return fileNameLength;
}
public int getHeaderCRC() {
return crc;
}
public void setFName(byte fileName[]) {
if(fileName != null) {
this.fileName = ByteOp.copy(fileName);
staticHeader.setFNameFlag(true);
fileNameLength = fileName.length;
} else {
this.fileName = null;
staticHeader.setFNameFlag(false);
fileNameLength = 0;
}
crc = -1;
}
public long getCommentLength() {
return commentLength;
}
public void setFComment(byte comment[]) {
if(comment != null) {
this.comment = ByteOp.copy(comment);
staticHeader.setFCommentFlag(true);
commentLength = comment.length;
} else {
this.comment = null;
staticHeader.setFCommentFlag(false);
commentLength = 0;
}
crc = -1;
}
public void replaceRecord(byte name[], byte value[])
throws GZIPFormatException {
if(records != null) {
removeAllRecords(name);
}
addRecord(name,value);
}
public void removeAllRecords(byte name[]) {
int removed = 0;
if(records != null) {
int kept = 0;
for(int i = 0; i < records.size(); i++) {
if(records.get(i).matchesName(name)) {
records.remove(i);
removed++;
i--;
} else {
kept++;
}
}
if(kept == 0) {
records = null;
staticHeader.setFExtraFlag(false);
}
}
if(removed > 0) {
crc = -1;
}
}
public void addRecord(byte name[], long intVal) throws GZIPFormatException {
if(records == null) {
records = new GZIPFExtraRecords();
}
records.add(new GZIPFExtraRecord(name,intVal));
staticHeader.setFExtraFlag(true);
crc = -1;
}
public void addRecord(byte name[], byte value[]) throws GZIPFormatException {
if(records == null) {
records = new GZIPFExtraRecords();
}
records.add(new GZIPFExtraRecord(name,value));
staticHeader.setFExtraFlag(true);
crc = -1;
}
public GZIPFExtraRecord getRecord(int i) {
if(records == null || records.isEmpty()) {
throw new IndexOutOfBoundsException();
}
return records.get(i);
}
public int getRecordCount() {
return (records == null) ? 0 : records.size();
}
public GZIPFExtraRecord getRecord(byte[] name) {
if(records != null) {
for(GZIPFExtraRecord rec : records) {
if(rec.matchesName(name)) {
return rec;
}
}
}
return null;
}
public long getIntRecord(byte[] name) {
if(records != null) {
for(GZIPFExtraRecord rec : records) {
if(rec.matchesName(name)) {
return ByteOp.bytesToInt(rec.getValue());
}
}
}
return -1;
}
public int getLength() {
int size = staticHeader.getLength();
if(records != null) {
size += records.getByteLength();
}
size += fileNameLength;
size += commentLength;
if(staticHeader.isFHCRCSet()) {
size += 2;
}
return size;
}
public void writeBytes(OutputStream os) throws IOException {
OutputStream origOS = os;
if(staticHeader.isFHCRCSet()) {
if(crc == -1) {
os = new CRCOutputStream(origOS);
}
}
staticHeader.writeTo(os);
if(staticHeader.isFExtraSet()) {
records.writeTo(os);
}
if(staticHeader.isFNameSet()) {
os.write(fileName);
}
if(staticHeader.isFCommentSet()) {
os.write(comment);
}
if(staticHeader.isFHCRCSet()) {
if(crc == -1) {
crc = (int) ((CRCOutputStream) os).getCRCValue() & 0xffff;
}
ByteOp.writeShort(origOS, crc);
}
}
public static boolean isValidCompressionMethod(int cm) {
return cm == GZIP_COMPRESSION_METHOD_DEFLATE;
}
}