Browse Source

Bug 50298: Fix corruption of Workbook when setting sheet order. The

boundssheets themselves were adjusted, but not the corresponding
records.

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1516313 13f79535-47bb-0310-9956-ffa450edef68
tags/REL_3_10_BETA2
Dominik Stadler 10 years ago
parent
commit
324a36e170

+ 19
- 65
src/java/org/apache/poi/hssf/model/InternalWorkbook.java View File

import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;


import org.apache.poi.ddf.EscherBSERecord;
import org.apache.poi.ddf.EscherBoolProperty;
import org.apache.poi.ddf.EscherContainerRecord;
import org.apache.poi.ddf.EscherDgRecord;
import org.apache.poi.ddf.EscherDggRecord;
import org.apache.poi.ddf.EscherOptRecord;
import org.apache.poi.ddf.EscherProperties;
import org.apache.poi.ddf.EscherRGBProperty;
import org.apache.poi.ddf.EscherRecord;
import org.apache.poi.ddf.EscherSimpleProperty;
import org.apache.poi.ddf.EscherSpRecord;
import org.apache.poi.ddf.EscherSplitMenuColorsRecord;
import org.apache.poi.hssf.record.BOFRecord;
import org.apache.poi.hssf.record.BackupRecord;
import org.apache.poi.hssf.record.BookBoolRecord;
import org.apache.poi.hssf.record.BoundSheetRecord;
import org.apache.poi.hssf.record.CodepageRecord;
import org.apache.poi.hssf.record.CountryRecord;
import org.apache.poi.hssf.record.DSFRecord;
import org.apache.poi.hssf.record.DateWindow1904Record;
import org.apache.poi.hssf.record.DrawingGroupRecord;
import org.apache.poi.hssf.record.EOFRecord;
import org.apache.poi.hssf.record.EscherAggregate;
import org.apache.poi.hssf.record.ExtSSTRecord;
import org.apache.poi.hssf.record.ExtendedFormatRecord;
import org.apache.poi.hssf.record.ExternSheetRecord;
import org.apache.poi.hssf.record.FileSharingRecord;
import org.apache.poi.hssf.record.FnGroupCountRecord;
import org.apache.poi.hssf.record.FontRecord;
import org.apache.poi.hssf.record.FormatRecord;
import org.apache.poi.hssf.record.HideObjRecord;
import org.apache.poi.hssf.record.HyperlinkRecord;
import org.apache.poi.hssf.record.InterfaceEndRecord;
import org.apache.poi.hssf.record.InterfaceHdrRecord;
import org.apache.poi.hssf.record.MMSRecord;
import org.apache.poi.hssf.record.NameCommentRecord;
import org.apache.poi.hssf.record.NameRecord;
import org.apache.poi.hssf.record.PaletteRecord;
import org.apache.poi.hssf.record.PasswordRecord;
import org.apache.poi.hssf.record.PasswordRev4Record;
import org.apache.poi.hssf.record.PrecisionRecord;
import org.apache.poi.hssf.record.ProtectRecord;
import org.apache.poi.hssf.record.ProtectionRev4Record;
import org.apache.poi.hssf.record.RecalcIdRecord;
import org.apache.poi.hssf.record.Record;
import org.apache.poi.hssf.record.RefreshAllRecord;
import org.apache.poi.hssf.record.SSTRecord;
import org.apache.poi.hssf.record.StyleRecord;
import org.apache.poi.hssf.record.SupBookRecord;
import org.apache.poi.hssf.record.TabIdRecord;
import org.apache.poi.hssf.record.UseSelFSRecord;
import org.apache.poi.hssf.record.WindowOneRecord;
import org.apache.poi.hssf.record.WindowProtectRecord;
import org.apache.poi.hssf.record.WriteAccessRecord;
import org.apache.poi.hssf.record.WriteProtectRecord;
import org.apache.poi.ddf.*;
import org.apache.poi.hssf.record.*;
import org.apache.poi.hssf.record.common.UnicodeString; import org.apache.poi.hssf.record.common.UnicodeString;
import org.apache.poi.hssf.util.HSSFColor; import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.formula.EvaluationWorkbook.ExternalName; import org.apache.poi.ss.formula.EvaluationWorkbook.ExternalName;
} }


for (int k = 0; k < 21; k++) { for (int k = 0; k < 21; k++) {
records.add(retval.createExtendedFormat(k));
records.add(InternalWorkbook.createExtendedFormat(k));
retval.numxfs++; retval.numxfs++;
} }
retval.records.setXfpos( records.size() - 1 ); retval.records.setXfpos( records.size() - 1 );
for (int k = 0; k < 6; k++) { for (int k = 0; k < 6; k++) {
records.add(retval.createStyle(k));
records.add(InternalWorkbook.createStyle(k));
} }
records.add(retval.createUseSelFS());
records.add(InternalWorkbook.createUseSelFS());


int nBoundSheets = 1; // now just do 1 int nBoundSheets = 1; // now just do 1
for (int k = 0; k < nBoundSheets; k++) { for (int k = 0; k < nBoundSheets; k++) {
retval.boundsheets.add(bsr); retval.boundsheets.add(bsr);
retval.records.setBspos(records.size() - 1); retval.records.setBspos(records.size() - 1);
} }
records.add( retval.createCountry() );
records.add( InternalWorkbook.createCountry() );
for ( int k = 0; k < nBoundSheets; k++ ) { for ( int k = 0; k < nBoundSheets; k++ ) {
retval.getOrCreateLinkTable().checkExternSheet(k); retval.getOrCreateLinkTable().checkExternSheet(k);
} }
retval.sst = new SSTRecord(); retval.sst = new SSTRecord();
records.add(retval.sst); records.add(retval.sst);
records.add(retval.createExtendedSST());
records.add(InternalWorkbook.createExtendedSST());


records.add(EOFRecord.instance); records.add(EOFRecord.instance);
if (log.check( POILogger.DEBUG )) if (log.check( POILogger.DEBUG ))
*/ */


public void setSheetOrder(String sheetname, int pos ) { public void setSheetOrder(String sheetname, int pos ) {
int sheetNumber = getSheetIndex(sheetname);
//remove the sheet that needs to be reordered and place it in the spot we want
boundsheets.add(pos, boundsheets.remove(sheetNumber));
int sheetNumber = getSheetIndex(sheetname);
//remove the sheet that needs to be reordered and place it in the spot we want
boundsheets.add(pos, boundsheets.remove(sheetNumber));
// also adjust order of Records, calculate the position of the Boundsheets via getBspos()...
int pos0 = records.getBspos() - (boundsheets.size() - 1);
Record removed = records.get(pos0 + sheetNumber);
records.remove(pos0 + sheetNumber);
records.add(pos0 + pos, removed);
} }


/** /**
Record record = records.get( k ); Record record = records.get( k );
if (record instanceof SSTRecord) if (record instanceof SSTRecord)
sst = (SSTRecord)record; sst = (SSTRecord)record;

if (record.getSid() == ExtSSTRecord.sid && sst != null) if (record.getSid() == ExtSSTRecord.sid && sst != null)
retval += sst.calcExtSSTRecordSize(); retval += sst.calcExtSSTRecordSize();
else else
retval += record.getRecordSize(); retval += record.getRecordSize();
} }

return retval; return retval;
} }


* @param password to set * @param password to set
*/ */
public void writeProtectWorkbook( String password, String username ) { public void writeProtectWorkbook( String password, String username ) {
int protIdx = -1;
FileSharingRecord frec = getFileSharing(); FileSharingRecord frec = getFileSharing();
WriteAccessRecord waccess = getWriteAccess(); WriteAccessRecord waccess = getWriteAccess();
WriteProtectRecord wprotect = getWriteProtect();
/* WriteProtectRecord wprotect =*/ getWriteProtect();
frec.setReadOnly((short)1); frec.setReadOnly((short)1);
frec.setPassword(FileSharingRecord.hashPassword(password)); frec.setPassword(FileSharingRecord.hashPassword(password));
frec.setUsername(username); frec.setUsername(username);

+ 60
- 17
src/testcases/org/apache/poi/hssf/usermodel/TestHSSFWorkbook.java View File



package org.apache.poi.hssf.usermodel; package org.apache.poi.hssf.usermodel;


import java.io.*;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List; import java.util.List;


import junit.framework.AssertionFailedError; import junit.framework.AssertionFailedError;


import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.POIDataSamples;
import org.apache.poi.ddf.EscherBSERecord;
import org.apache.poi.hpsf.ClassID;
import org.apache.poi.hssf.HSSFITestDataProvider; import org.apache.poi.hssf.HSSFITestDataProvider;
import org.apache.poi.hssf.HSSFTestDataSamples;
import org.apache.poi.hssf.model.HSSFFormulaParser; import org.apache.poi.hssf.model.HSSFFormulaParser;
import org.apache.poi.hssf.model.InternalWorkbook;
import org.apache.poi.hssf.model.InternalSheet; import org.apache.poi.hssf.model.InternalSheet;
import org.apache.poi.hssf.record.*;
import org.apache.poi.ss.formula.ptg.Area3DPtg;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.TempFile;
import org.apache.poi.ss.usermodel.BaseTestWorkbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.hssf.model.InternalWorkbook;
import org.apache.poi.hssf.record.CFRuleRecord;
import org.apache.poi.hssf.record.NameRecord;
import org.apache.poi.hssf.record.Record;
import org.apache.poi.hssf.record.RecordBase;
import org.apache.poi.hssf.record.RecordFormatException;
import org.apache.poi.hssf.record.WindowOneRecord;
import org.apache.poi.poifs.filesystem.DirectoryEntry; import org.apache.poi.poifs.filesystem.DirectoryEntry;
import org.apache.poi.poifs.filesystem.DirectoryNode; import org.apache.poi.poifs.filesystem.DirectoryNode;
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.POIDataSamples;
import org.apache.poi.ddf.EscherBSERecord;
import org.apache.poi.hpsf.ClassID;
import org.apache.poi.ss.formula.ptg.Area3DPtg;
import org.apache.poi.ss.usermodel.BaseTestWorkbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.TempFile;


/** /**
* Tests for {@link HSSFWorkbook} * Tests for {@link HSSFWorkbook}
public BadlyBehavedRecord() { public BadlyBehavedRecord() {
// //
} }
public short getSid() {
@Override
public short getSid() {
return 0x777; return 0x777;
} }
public int serialize(int offset, byte[] data) {
@Override
public int serialize(int offset, byte[] data) {
return 4; return 4;
} }
public int getRecordSize() {
@Override
public int getRecordSize() {
return 8; return 8;
} }
} }
wb = HSSFTestDataSamples.writeOutAndReadBack(wb); wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
assertEquals(3, wb.getNumberOfSheets()); assertEquals(3, wb.getNumberOfSheets());
assertEquals("Root xls", wb.getSheetAt(0).getRow(0).getCell(0).getStringCellValue()); assertEquals("Root xls", wb.getSheetAt(0).getRow(0).getCell(0).getStringCellValue());
fs.close();
} }
public void testCellStylesLimit() { public void testCellStylesLimit() {
int MAX_STYLES = 4030; int MAX_STYLES = 4030;
int limit = MAX_STYLES - numBuiltInStyles; int limit = MAX_STYLES - numBuiltInStyles;
for(int i=0; i < limit; i++){ for(int i=0; i < limit; i++){
HSSFCellStyle style = wb.createCellStyle();
/* HSSFCellStyle style =*/ wb.createCellStyle();
} }


assertEquals(MAX_STYLES, wb.getNumCellStyles()); assertEquals(MAX_STYLES, wb.getNumCellStyles());
try { try {
HSSFCellStyle style = wb.createCellStyle();
/*HSSFCellStyle style =*/ wb.createCellStyle();
fail("expected exception"); fail("expected exception");
} catch (IllegalStateException e){ } catch (IllegalStateException e){
assertEquals("The maximum number of cell styles was exceeded. " + assertEquals("The maximum number of cell styles was exceeded. " +
wb.unwriteProtectWorkbook(); wb.unwriteProtectWorkbook();
assertFalse(wb.isWriteProtected()); assertFalse(wb.isWriteProtected());
} }

public void testBug50298() throws Exception {
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("50298.xls");

HSSFSheet sheet = wb.cloneSheet(0);

wb.setSheetName(wb.getSheetIndex(sheet), "copy");

wb.setSheetOrder("copy", 0);

wb.removeSheetAt(0);
// check that the overall workbook serializes with its correct size
int expected = wb.getWorkbook().getSize();
int written = wb.getWorkbook().serialize(0, new byte[expected*2]);
assertEquals("Did not have the expected size when writing the workbook: written: " + written + ", but expected: " + expected,
expected, written);
FileOutputStream fileOut = new FileOutputStream("/tmp/workbook.xls");
try {
wb.write(fileOut);
} finally {
fileOut.close();
}
}
} }

BIN
test-data/spreadsheet/50298.xls View File


Loading…
Cancel
Save