public static final short sid = 0x002F;
private static final int ENCRYPTION_XOR = 0;
private static final int ENCRYPTION_OTHER = 1;
-
+
private final int encryptionType;
private EncryptionInfo encryptionInfo;
-
+
private FilePassRecord(FilePassRecord other) {
encryptionType = other.encryptionType;
try {
throw new EncryptedDocumentException(e);
}
}
-
+
public FilePassRecord(EncryptionMode encryptionMode) {
encryptionType = (encryptionMode == EncryptionMode.xor) ? ENCRYPTION_XOR : ENCRYPTION_OTHER;
encryptionInfo = new EncryptionInfo(encryptionMode);
}
-
+
public FilePassRecord(RecordInputStream in) {
encryptionType = in.readUShort();
-
+
EncryptionMode preferredMode;
switch (encryptionType) {
case ENCRYPTION_XOR:
default:
throw new EncryptedDocumentException("invalid encryption type");
}
-
+
try {
encryptionInfo = new EncryptionInfo(in, preferredMode);
} catch (IOException e) {
public void serialize(LittleEndianOutput out) {
out.writeShort(encryptionType);
- byte[] data = new byte[1024];
- LittleEndianByteArrayOutputStream bos = new LittleEndianByteArrayOutputStream(data, 0); // NOSONAR
+ byte data[] = new byte[1024];
+ try (LittleEndianByteArrayOutputStream bos =
+ new LittleEndianByteArrayOutputStream(data, 0)) { // NOSONAR
- switch (encryptionInfo.getEncryptionMode()) {
- case xor:
- ((XOREncryptionHeader)encryptionInfo.getHeader()).write(bos);
- ((XOREncryptionVerifier)encryptionInfo.getVerifier()).write(bos);
- break;
- case binaryRC4:
- out.writeShort(encryptionInfo.getVersionMajor());
- out.writeShort(encryptionInfo.getVersionMinor());
- ((BinaryRC4EncryptionHeader)encryptionInfo.getHeader()).write(bos);
- ((BinaryRC4EncryptionVerifier)encryptionInfo.getVerifier()).write(bos);
- break;
- case cryptoAPI:
- out.writeShort(encryptionInfo.getVersionMajor());
- out.writeShort(encryptionInfo.getVersionMinor());
- out.writeInt(encryptionInfo.getEncryptionFlags());
- ((CryptoAPIEncryptionHeader)encryptionInfo.getHeader()).write(bos);
- ((CryptoAPIEncryptionVerifier)encryptionInfo.getVerifier()).write(bos);
- break;
- default:
- throw new EncryptedDocumentException("not supported");
- }
+ switch (encryptionInfo.getEncryptionMode()) {
+ case xor:
+ ((XOREncryptionHeader)encryptionInfo.getHeader()).write(bos);
+ ((XOREncryptionVerifier)encryptionInfo.getVerifier()).write(bos);
+ break;
+ case binaryRC4:
+ out.writeShort(encryptionInfo.getVersionMajor());
+ out.writeShort(encryptionInfo.getVersionMinor());
+ ((BinaryRC4EncryptionHeader)encryptionInfo.getHeader()).write(bos);
+ ((BinaryRC4EncryptionVerifier)encryptionInfo.getVerifier()).write(bos);
+ break;
+ case cryptoAPI:
+ out.writeShort(encryptionInfo.getVersionMajor());
+ out.writeShort(encryptionInfo.getVersionMinor());
+ out.writeInt(encryptionInfo.getEncryptionFlags());
+ ((CryptoAPIEncryptionHeader)encryptionInfo.getHeader()).write(bos);
+ ((CryptoAPIEncryptionVerifier)encryptionInfo.getVerifier()).write(bos);
+ break;
+ default:
+ throw new EncryptedDocumentException("not supported");
+ }
- out.write(data, 0, bos.getWriteIndex());
+ out.write(data, 0, bos.getWriteIndex());
+ } catch (IOException ioe) {
+ // should never happen in practice
+ throw new IllegalStateException(ioe);
+ }
}
@Override
public short getSid() {
return sid;
}
-
+
@Override
public FilePassRecord clone() {
return new FilePassRecord(this);
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
-
+
package org.apache.poi.hssf.record;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* OBJRECORD (0x005D)<p>
- *
+ *
* The obj record is used to hold various graphic objects and controls.
*/
public final class ObjRecord extends Record implements Cloneable {
private static final int NORMAL_PAD_ALIGNMENT = 2;
private static int MAX_PAD_ALIGNMENT = 4;
-
+
private List<SubRecord> subrecords;
/** used when POI has no idea what is going on */
private final byte[] _uninterpretedData;
_isPaddedToQuadByteMultiple = subRecordData.length % MAX_PAD_ALIGNMENT == 0;
if (nRemainingBytes >= (_isPaddedToQuadByteMultiple ? MAX_PAD_ALIGNMENT : NORMAL_PAD_ALIGNMENT)) {
if (!canPaddingBeDiscarded(subRecordData, nRemainingBytes)) {
- String msg = "Leftover " + nRemainingBytes
+ String msg = "Leftover " + nRemainingBytes
+ " bytes in subrecord data " + HexDump.toHex(subRecordData);
throw new RecordFormatException(msg);
}
* written by a version of POI (around 3.1) which incorrectly interpreted the second short of
* the ftLbs subrecord (0x1FEE) as a length, and read that many bytes as padding (other bugs
* helped allow this to occur).
- *
+ *
* Excel reads files with this excessive padding OK, truncating the over-sized ObjRecord back
* to the its proper size. POI does the same.
*/
sb.append("[/OBJ]\n");
return sb.toString();
}
-
+
@Override
public int getRecordSize() {
if (_uninterpretedData != null) {
return size + 4;
}
- @Override
- public int serialize(int offset, byte[] data) {
- int recSize = getRecordSize();
- int dataSize = recSize - 4;
- LittleEndianByteArrayOutputStream out = new LittleEndianByteArrayOutputStream(data, offset, recSize); // NOSONAR
-
- out.writeShort(sid);
- out.writeShort(dataSize);
-
- if (_uninterpretedData == null) {
-
- for (int i = 0; i < subrecords.size(); i++) {
- SubRecord record = subrecords.get(i);
- record.serialize(out);
- }
- int expectedEndIx = offset+dataSize;
- // padding
- while (out.getWriteIndex() < expectedEndIx) {
- out.writeByte(0);
- }
- } else {
- out.write(_uninterpretedData);
- }
- return recSize;
- }
+ @Override
+ public int serialize(int offset, byte[] data) {
+ int recSize = getRecordSize();
+ int dataSize = recSize - 4;
+
+ try (LittleEndianByteArrayOutputStream out = new LittleEndianByteArrayOutputStream(data, offset, recSize)) { // NOSONAR
+ out.writeShort(sid);
+ out.writeShort(dataSize);
+
+ if (_uninterpretedData == null) {
+
+ for (int i = 0; i < subrecords.size(); i++) {
+ SubRecord record = subrecords.get(i);
+ record.serialize(out);
+ }
+ int expectedEndIx = offset + dataSize;
+ // padding
+ while (out.getWriteIndex() < expectedEndIx) {
+ out.writeByte(0);
+ }
+ } else {
+ out.write(_uninterpretedData);
+ }
+ } catch (IOException ioe) {
+ // should never happen in practice
+ throw new IllegalStateException(ioe);
+ }
+ return recSize;
+ }
@Override
public short getSid() {
package org.apache.poi.hssf.record;
+import java.io.IOException;
+
import org.apache.poi.util.LittleEndianByteArrayOutputStream;
import org.apache.poi.util.LittleEndianOutput;
/**
- * Subclasses of this class (the majority of BIFF records) are non-continuable. This allows for
- * some simplification of serialization logic
+ * Subclasses of this class (the majority of BIFF records) are non-continuable.
+ * This allows for some simplification of serialization logic
*/
public abstract class StandardRecord extends Record {
- protected abstract int getDataSize();
- public final int getRecordSize() {
- return 4 + getDataSize();
- }
+ protected abstract int getDataSize();
+
+ @Override
+ public final int getRecordSize() {
+ return 4 + getDataSize();
+ }
/**
- * Write the data content of this BIFF record including the sid and record length.
+ * Write the data content of this BIFF record including the sid and record
+ * length.
* <p>
* The subclass must write the exact number of bytes as reported by
- * {@link org.apache.poi.hssf.record.Record#getRecordSize()}}
+ * {@link org.apache.poi.hssf.record.Record#getRecordSize()}}
*/
- @Override
- public final int serialize(int offset, byte[] data) {
- int dataSize = getDataSize();
- int recSize = 4 + dataSize;
- LittleEndianByteArrayOutputStream out = new LittleEndianByteArrayOutputStream(data, offset, recSize);
- out.writeShort(getSid());
- out.writeShort(dataSize);
- serialize(out);
- if (out.getWriteIndex() - offset != recSize) {
- throw new IllegalStateException("Error in serialization of (" + getClass().getName() + "): "
- + "Incorrect number of bytes written - expected "
- + recSize + " but got " + (out.getWriteIndex() - offset));
- }
- return recSize;
- }
+ @Override
+ public final int serialize(int offset, byte[] data) {
+ int dataSize = getDataSize();
+ int recSize = 4 + dataSize;
+ try (LittleEndianByteArrayOutputStream out =
+ new LittleEndianByteArrayOutputStream(data, offset, recSize)) {
+ out.writeShort(getSid());
+ out.writeShort(dataSize);
+ serialize(out);
+ if (out.getWriteIndex() - offset != recSize) {
+ throw new IllegalStateException("Error in serialization of (" + getClass().getName() + "): "
+ + "Incorrect number of bytes written - expected " + recSize + " but got "
+ + (out.getWriteIndex() - offset));
+ }
+ } catch (IOException ioe) {
+ // should never happen in practice
+ throw new IllegalStateException(ioe);
+ }
+ return recSize;
+ }
/**
- * Write the data content of this BIFF record. The 'ushort sid' and 'ushort size' header fields
- * have already been written by the superclass.
+ * Write the data content of this BIFF record. The 'ushort sid' and 'ushort
+ * size' header fields have already been written by the superclass.
* <p>
* The number of bytes written must equal the record size reported by
- * {@link org.apache.poi.hssf.record.Record#getRecordSize()}} minus four
- * ( record header consisting of a 'ushort sid' and 'ushort reclength' has already been written
- * by their superclass).
- *
- * @param out the output object
+ * {@link org.apache.poi.hssf.record.Record#getRecordSize()}} minus four (
+ * record header consisting of a 'ushort sid' and 'ushort reclength' has
+ * already been written by their superclass).
+ *
+ * @param out
+ * the output object
*/
- protected abstract void serialize(LittleEndianOutput out);
+ protected abstract void serialize(LittleEndianOutput out);
}
package org.apache.poi.hssf.record.cont;
+import java.io.IOException;
+
import org.apache.poi.hssf.record.ContinueRecord;
import org.apache.poi.hssf.record.Record;
import org.apache.poi.util.LittleEndianByteArrayOutputStream;
* (Note - if any {@link ContinueRecord} is required, this result includes the
* size of those too)
*/
+ @Override
public final int getRecordSize() {
ContinuableRecordOutput out = ContinuableRecordOutput.createForCountingOnly();
serialize(out);
return out.getTotalSize();
}
+ @Override
public final int serialize(int offset, byte[] data) {
-
- LittleEndianOutput leo = new LittleEndianByteArrayOutputStream(data, offset);
- ContinuableRecordOutput out = new ContinuableRecordOutput(leo, getSid());
- serialize(out);
- out.terminate();
- return out.getTotalSize();
+ int totalSize = 0;
+ try (LittleEndianByteArrayOutputStream leo =
+ new LittleEndianByteArrayOutputStream(data, offset)) {
+ ContinuableRecordOutput out = new ContinuableRecordOutput(leo, getSid());
+ serialize(out);
+ out.terminate();
+ totalSize = out.getTotalSize();
+ } catch (IOException ioe) {
+ // should never happen in practice
+ throw new IllegalStateException(ioe);
+ }
+ return totalSize;
}
}
package org.apache.poi.ss.util;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
* Implementation of the cell range address lists,like is described
* in OpenOffice.org's Excel Documentation: excelfileformat.pdf sec 2.5.14 -
* 'Cell Range Address List'
- *
+ *
* In BIFF8 there is a common way to store absolute cell range address lists in
* several records (not formulas). A cell range address list consists of a field
* with the number of ranges and the list of the range addresses. Each cell
* range address (called an ADDR structure) contains 4 16-bit-values.
* </p>
- *
+ *
* @author Dragos Buleandra (dragos.buleandra@trade2b.ro)
*/
public class CellRangeAddressList {
_list = new ArrayList<>();
}
/**
- * Convenience constructor for creating a <tt>CellRangeAddressList</tt> with a single
+ * Convenience constructor for creating a <tt>CellRangeAddressList</tt> with a single
* <tt>CellRangeAddress</tt>. Other <tt>CellRangeAddress</tt>es may be added later.
*/
public CellRangeAddressList(int firstRow, int lastRow, int firstCol, int lastCol) {
* structures is automatically set when reading an Excel file and/or
* increased when you manually add a new ADDR structure . This is the reason
* there isn't a set method for this field .
- *
+ *
* @return number of ADDR structures
*/
public int countRanges() {
/**
* Add a cell range structure.
- *
+ *
* @param firstRow - the upper left hand corner's row
* @param firstCol - the upper left hand corner's col
* @param lastRow - the lower right hand corner's row
throw new RuntimeException("List is empty");
}
if (rangeIndex < 0 || rangeIndex >= _list.size()) {
- throw new RuntimeException("Range index (" + rangeIndex
+ throw new RuntimeException("Range index (" + rangeIndex
+ ") is outside allowable range (0.." + (_list.size()-1) + ")");
}
return _list.remove(rangeIndex);
public int serialize(int offset, byte[] data) {
int totalSize = getSize();
- serialize(new LittleEndianByteArrayOutputStream(data, offset, totalSize));
+ try (LittleEndianByteArrayOutputStream lebaos =
+ new LittleEndianByteArrayOutputStream(data, offset, totalSize)) {
+ serialize(lebaos);
+ }
+ catch (IOException ioe) {
+ // should never happen in practice
+ throw new IllegalStateException(ioe);
+ }
return totalSize;
}
+
public void serialize(LittleEndianOutput out) {
int nItems = _list.size();
out.writeShort(nItems);
region.serialize(out);
}
}
-
public CellRangeAddressList copy() {
CellRangeAddressList result = new CellRangeAddressList();
-
+
int nItems = _list.size();
for (int k = 0; k < nItems; k++) {
CellRangeAddress region = _list.get(k);