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
This commit is contained in:
Dominik Stadler 2013-08-21 22:08:20 +00:00
parent d415bf5d06
commit 324a36e170
3 changed files with 79 additions and 82 deletions

View File

@ -26,61 +26,8 @@ import java.util.Locale;
import java.util.Map;
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.util.HSSFColor;
import org.apache.poi.ss.formula.EvaluationWorkbook.ExternalName;
@ -405,14 +352,14 @@ public final class InternalWorkbook {
}
for (int k = 0; k < 21; k++) {
records.add(retval.createExtendedFormat(k));
records.add(InternalWorkbook.createExtendedFormat(k));
retval.numxfs++;
}
retval.records.setXfpos( records.size() - 1 );
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
for (int k = 0; k < nBoundSheets; k++) {
@ -422,13 +369,13 @@ public final class InternalWorkbook {
retval.boundsheets.add(bsr);
retval.records.setBspos(records.size() - 1);
}
records.add( retval.createCountry() );
records.add( InternalWorkbook.createCountry() );
for ( int k = 0; k < nBoundSheets; k++ ) {
retval.getOrCreateLinkTable().checkExternSheet(k);
}
retval.sst = new SSTRecord();
records.add(retval.sst);
records.add(retval.createExtendedSST());
records.add(InternalWorkbook.createExtendedSST());
records.add(EOFRecord.instance);
if (log.check( POILogger.DEBUG ))
@ -631,6 +578,12 @@ public final class InternalWorkbook {
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);
}
/**
@ -1087,11 +1040,13 @@ public final class InternalWorkbook {
Record record = records.get( k );
if (record instanceof SSTRecord)
sst = (SSTRecord)record;
if (record.getSid() == ExtSSTRecord.sid && sst != null)
retval += sst.calcExtSSTRecordSize();
else
retval += record.getRecordSize();
}
return retval;
}
@ -2320,10 +2275,9 @@ public final class InternalWorkbook {
* @param password to set
*/
public void writeProtectWorkbook( String password, String username ) {
int protIdx = -1;
FileSharingRecord frec = getFileSharing();
WriteAccessRecord waccess = getWriteAccess();
WriteProtectRecord wprotect = getWriteProtect();
/* WriteProtectRecord wprotect =*/ getWriteProtect();
frec.setReadOnly((short)1);
frec.setPassword(FileSharingRecord.hashPassword(password));
frec.setUsername(username);

View File

@ -17,29 +17,40 @@
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 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.HSSFTestDataSamples;
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.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.DirectoryNode;
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
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}
@ -455,12 +466,15 @@ public final class TestHSSFWorkbook extends BaseTestWorkbook {
public BadlyBehavedRecord() {
//
}
@Override
public short getSid() {
return 0x777;
}
@Override
public int serialize(int offset, byte[] data) {
return 4;
}
@Override
public int getRecordSize() {
return 8;
}
@ -598,6 +612,8 @@ public final class TestHSSFWorkbook extends BaseTestWorkbook {
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
assertEquals(3, wb.getNumberOfSheets());
assertEquals("Root xls", wb.getSheetAt(0).getRow(0).getCell(0).getStringCellValue());
fs.close();
}
public void testCellStylesLimit() {
@ -606,12 +622,12 @@ public final class TestHSSFWorkbook extends BaseTestWorkbook {
int MAX_STYLES = 4030;
int limit = MAX_STYLES - numBuiltInStyles;
for(int i=0; i < limit; i++){
HSSFCellStyle style = wb.createCellStyle();
/* HSSFCellStyle style =*/ wb.createCellStyle();
}
assertEquals(MAX_STYLES, wb.getNumCellStyles());
try {
HSSFCellStyle style = wb.createCellStyle();
/*HSSFCellStyle style =*/ wb.createCellStyle();
fail("expected exception");
} catch (IllegalStateException e){
assertEquals("The maximum number of cell styles was exceeded. " +
@ -877,4 +893,31 @@ public final class TestHSSFWorkbook extends BaseTestWorkbook {
wb.unwriteProtectWorkbook();
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();
}
}
}

Binary file not shown.