public StreamEncryptionInfo(RecordInputStream rs, List<Record> outputRecs) { Record rec; rs.nextRecord(); int recSize = 4 + rs.remaining(); rec = RecordFactory.createSingleRecord(rs); outputRecs.add(rec); FilePassRecord fpr = null; if (rec instanceof BOFRecord) { _hasBOFRecord = true; // Fetch the next record, and see if it indicates whether // the document is encrypted or not if (rs.hasNextRecord()) { rs.nextRecord(); rec = RecordFactory.createSingleRecord(rs); recSize += rec.getRecordSize(); outputRecs.add(rec); // Encrypted is normally BOF then FILEPASS // May sometimes be BOF, WRITEPROTECT, FILEPASS if (rec instanceof WriteProtectRecord && rs.hasNextRecord()) { rs.nextRecord(); rec = RecordFactory.createSingleRecord(rs); recSize += rec.getRecordSize(); outputRecs.add(rec); } // If it's a FILEPASS, track it specifically but // don't include it in the main stream if (rec instanceof FilePassRecord) { fpr = (FilePassRecord) rec; outputRecs.remove(outputRecs.size() - 1); // TODO - add fpr not added to outputRecs rec = outputRecs.get(0); } else { // workbook not encrypted (typical case) if (rec instanceof EOFRecord) { // A workbook stream is never empty, so crash instead // of trying to keep track of nesting level throw new IllegalStateException("Nothing between BOF and EOF"); } } } } else { // Invalid in a normal workbook stream. // However, some test cases work on sub-sections of // the workbook stream that do not begin with BOF _hasBOFRecord = false; } _initialRecordsSize = recSize; _filePassRec = fpr; _lastRecord = rec; }
/** Returns the next (complete) record from the stream, or null if there are no more. */ public Record nextRecord() { Record r; r = getNextUnreadRecord(); if (r != null) { // found an unread record return r; } while (true) { if (!_recStream.hasNextRecord()) { // recStream is exhausted; return null; } if (_lastRecordWasEOFLevelZero) { // Potential place for ending the workbook stream // Check that the next record is not BOFRecord(0x0809) // Normally the input stream contains only zero padding after the last EOFRecord, // but bug 46987 and 48068 suggests that the padding may be garbage. // This code relies on the padding bytes not starting with BOFRecord.sid if (_recStream.getNextSid() != BOFRecord.sid) { return null; } // else - another sheet substream starting here } // step underlying RecordInputStream to the next record _recStream.nextRecord(); r = readNextRecord(); if (r == null) { // some record types may get skipped (e.g. DBCellRecord and ContinueRecord) continue; } return r; } }