gzipEntry.xfl = (short)(headerBytes[8] & 255);
gzipEntry.os = (short)(headerBytes[9] & 255);
crc.update(headerBytes);
if (gzipEntry.magic != GzipConstants.GZIP_MAGIC) {
gzipEntry.diagnostics.addError(
new Diagnosis(
DiagnosisType.INVALID_EXPECTED,
"Magic Value",
Integer.toHexString(gzipEntry.magic),
Integer.toHexString(GzipConstants.GZIP_MAGIC)
)
);
}
if (gzipEntry.cm != GzipConstants.CM_DEFLATE) {
// Currently only the deflate compression method is supported in GZip.
gzipEntry.diagnostics.addError(
new Diagnosis(
DiagnosisType.INVALID_EXPECTED,
"Compression Method",
Integer.toHexString(gzipEntry.cm),
Integer.toHexString(GzipConstants.CM_DEFLATE)
)
);
} else {
// Currently only the deflate compression method is supported in GZip.
// Check to see whether some xfl reserved bits have been used.
if ((gzipEntry.xfl & GzipConstants.DEFLATE_XLF_RESERVED) != 0) {
gzipEntry.diagnostics.addWarning(
new Diagnosis(
DiagnosisType.RESERVED,
"eXtra FLags",
Integer.toHexString(gzipEntry.xfl & GzipConstants.DEFLATE_XLF_RESERVED)
)
);
}
if ((gzipEntry.xfl & GzipConstants.DEFLATE_XFL_COMPRESSION_MASK) == GzipConstants.DEFLATE_XFL_COMPRESSION_MASK) {
gzipEntry.diagnostics.addError(
new Diagnosis(
DiagnosisType.INVALID_DATA,
"eXtra FLags",
Integer.toHexString(gzipEntry.xfl & GzipConstants.DEFLATE_XFL_COMPRESSION_MASK)
)
);
}
}
if ((gzipEntry.flg & GzipConstants.FLG_FRESERVED) != 0) {
gzipEntry.diagnostics.addWarning(
new Diagnosis(
DiagnosisType.RESERVED,
"FLaGs",
Integer.toHexString(gzipEntry.flg & GzipConstants.FLG_FRESERVED)
)
);
}
if (!GzipConstants.osIdxStr.containsKey((int)gzipEntry.os)) {
gzipEntry.diagnostics.addWarning(
new Diagnosis(
DiagnosisType.UNKNOWN,
"Operating System",
Integer.toString(gzipEntry.os)
)
);
}
/*
* FTEXT.
*/
if ((gzipEntry.flg & GzipConstants.FLG_FTEXT) == GzipConstants.FLG_FTEXT) {
gzipEntry.bFText = true;
}
/*
* FEXTRA.
*/
if ((gzipEntry.flg & GzipConstants.FLG_FEXTRA) == GzipConstants.FLG_FEXTRA) {
read = pbin.read(xlenBytes);
if (read == 2) {
gzipEntry.xlen = ((xlenBytes[1] & 255) << 8) | (xlenBytes[0] & 255);
if (gzipEntry.xlen > 0) {
gzipEntry.extraBytes = new byte[gzipEntry.xlen];
read = pbin.readFully(gzipEntry.extraBytes);
if (read != gzipEntry.xlen) {
throw new EOFException("Unexpected EOF!");
}
int idx = 0;
boolean b = true;
GzipExtraData extraData;
int len;
while (b) {
if (idx <= gzipEntry.extraBytes.length - 4) {
extraData = new GzipExtraData();
extraData.si1 = (byte)(gzipEntry.extraBytes[idx++] & 255);
extraData.si2 = (byte)(gzipEntry.extraBytes[idx++] & 255);
len = ((gzipEntry.extraBytes[idx+1] & 255) << 8) | (gzipEntry.extraBytes[idx] & 255);
idx += 2;
if (idx + len <= gzipEntry.extraBytes.length) {
extraData.data = new byte[len];
System.arraycopy(gzipEntry.extraBytes, idx, extraData.data, 0, len);
idx += len;
gzipEntry.extraData.add(extraData);
} else {
b = false;
}
} else {
b = false;
}
}
if (idx != gzipEntry.extraBytes.length) {
gzipEntry.diagnostics.addError(
new Diagnosis(
DiagnosisType.INVALID_DATA,
"FEXTRA",
"Invalid structure",
"Data truncated"
)
);
}
} else {
gzipEntry.extraBytes = new byte[0];
}
} else {
throw new EOFException("Unexpected EOF!");
}
crc.update(xlenBytes);
crc.update(gzipEntry.extraBytes);
}
/*
* FNAME.
*/
if ((gzipEntry.flg & GzipConstants.FLG_FNAME) == GzipConstants.FLG_FNAME) {
fnameBytes = readZeroTerminated();
if (fnameBytes == null) {
throw new EOFException("Unexpected EOF!");
}
if (!iso8859_1.decode(fnameBytes, "")) {
gzipEntry.diagnostics.addWarning(
new Diagnosis(
DiagnosisType.INVALID_ENCODING,
"FName",
iso8859_1.decoded,
"ISO-8859-1"
)
);
}
gzipEntry.fname = iso8859_1.decoded;
crc.update(fnameBytes);
crc.update(0);
}
/*
* FCOMMENT.
*/
if ((gzipEntry.flg & GzipConstants.FLG_FCOMMENT) == GzipConstants.FLG_FCOMMENT) {
fcommentBytes = readZeroTerminated();
if (fcommentBytes == null) {
throw new EOFException("Unexpected EOF!");
}
if (!iso8859_1.decode(fcommentBytes, "\n")) {
gzipEntry.diagnostics.addWarning(
new Diagnosis(
DiagnosisType.INVALID_ENCODING,
"FComment",
iso8859_1.decoded,
"ISO-8859-1"
)
);
}
gzipEntry.fcomment = iso8859_1.decoded;
crc.update(fcommentBytes);
crc.update(0);
}
/*
* FHCRC.
*/
if ((gzipEntry.flg & GzipConstants.FLG_FHCRC) == GzipConstants.FLG_FHCRC) {
read = pbin.read(crc16Bytes);
if (read == 2) {
gzipEntry.bFhCrc = true;
gzipEntry.crc16 = ((crc16Bytes[1] & 255) << 8) | (crc16Bytes[0] & 255);
} else {
throw new EOFException("Unexpected EOF!");
}
}
/*
* Computed crc16.
*/
gzipEntry.comp_crc16 = ((int)crc.getValue()) & 0x0000ffff;
crc.reset();
if (gzipEntry.crc16 != null && gzipEntry.crc16 != gzipEntry.comp_crc16) {
gzipEntry.diagnostics.addError(
new Diagnosis(
DiagnosisType.INVALID_EXPECTED,
"CRC16",
Integer.toHexString(gzipEntry.crc16),
Integer.toHexString(gzipEntry.comp_crc16)
)
);
}
/*
* Prepare Entry InputStream.
*/
lastInput = 0;
gzipEntry.in = new GzipEntryInputStream(this, gzipEntry);
// Compliance
if (gzipEntry.diagnostics.hasErrors() || gzipEntry.diagnostics.hasWarnings()) {
gzipEntry.bIsCompliant = false;
} else {
gzipEntry.bIsCompliant = true;
}
bIsCompliant &= gzipEntry.bIsCompliant;
++entries;
} catch (EOFException e) {
partialEntry = gzipEntry;
diagnostics.addError(new Diagnosis(DiagnosisType.INVALID_DATA, "GZip file", "Unexpected EOF!"));
bIsCompliant = false;
gzipEntry = null;
}
} else {
// Require one or more entries to be present.
if (entries == 0) {
diagnostics.addError(new Diagnosis(DiagnosisType.ERROR_EXPECTED, "GZip file", "One or more records"));
bIsCompliant = false;
}
if (pbin.read() != -1) {
diagnostics.addError(new Diagnosis(DiagnosisType.INVALID_DATA, "GZip file", "Unexpected trailing data!"));
bIsCompliant = false;
}
}
return gzipEntry;
}