You've already forked lazarus-ccr
fpspreadsheet: Fix crash when reading a BIFF5 file written by Excel97 (it has data (the directory) beyound the workbook stream which is not expected by the BIFF5/8 readers).
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@3897 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -67,7 +67,7 @@
|
|||||||
<Unit1>
|
<Unit1>
|
||||||
<Filename Value="main.pas"/>
|
<Filename Value="main.pas"/>
|
||||||
<IsPartOfProject Value="True"/>
|
<IsPartOfProject Value="True"/>
|
||||||
<ComponentName Value="Form1"/>
|
<ComponentName Value="MainForm"/>
|
||||||
<HasResources Value="True"/>
|
<HasResources Value="True"/>
|
||||||
<ResourceBaseClass Value="Form"/>
|
<ResourceBaseClass Value="Form"/>
|
||||||
<UnitName Value="main"/>
|
<UnitName Value="main"/>
|
||||||
|
@ -15,7 +15,7 @@ uses
|
|||||||
begin
|
begin
|
||||||
RequireDerivedFormResource := True;
|
RequireDerivedFormResource := True;
|
||||||
Application.Initialize;
|
Application.Initialize;
|
||||||
Application.CreateForm(TForm1, Form1);
|
Application.CreateForm(TMainForm, MainForm);
|
||||||
Application.Run;
|
Application.Run;
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
object Form1: TForm1
|
object MainForm: TMainForm
|
||||||
Left = 495
|
Left = 495
|
||||||
Height = 600
|
Height = 600
|
||||||
Top = 132
|
Top = 132
|
||||||
Width = 929
|
Width = 929
|
||||||
Caption = 'Form1'
|
Caption = 'demo_ctrls'
|
||||||
ClientHeight = 580
|
ClientHeight = 580
|
||||||
ClientWidth = 929
|
ClientWidth = 929
|
||||||
Menu = MainMenu
|
Menu = MainMenu
|
||||||
|
@ -11,9 +11,9 @@ uses
|
|||||||
|
|
||||||
type
|
type
|
||||||
|
|
||||||
{ TForm1 }
|
{ TMainForm }
|
||||||
|
|
||||||
TForm1 = class(TForm)
|
TMainForm = class(TForm)
|
||||||
AcRowDelete: TAction;
|
AcRowDelete: TAction;
|
||||||
AcColDelete: TAction;
|
AcColDelete: TAction;
|
||||||
AcRowAdd: TAction;
|
AcRowAdd: TAction;
|
||||||
@ -286,21 +286,22 @@ type
|
|||||||
procedure InspectorTabControlChange(Sender: TObject);
|
procedure InspectorTabControlChange(Sender: TObject);
|
||||||
private
|
private
|
||||||
{ private declarations }
|
{ private declarations }
|
||||||
|
procedure UpdateCaption;
|
||||||
public
|
public
|
||||||
{ public declarations }
|
{ public declarations }
|
||||||
end;
|
end;
|
||||||
|
|
||||||
var
|
var
|
||||||
Form1: TForm1;
|
MainForm: TMainForm;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
{$R *.lfm}
|
{$R *.lfm}
|
||||||
|
|
||||||
{ TForm1 }
|
{ TMainForm }
|
||||||
|
|
||||||
{ Loads the spreadsheet file selected by the AcFileOpen action }
|
{ Loads the spreadsheet file selected by the AcFileOpen action }
|
||||||
procedure TForm1.AcFileOpenAccept(Sender: TObject);
|
procedure TMainForm.AcFileOpenAccept(Sender: TObject);
|
||||||
begin
|
begin
|
||||||
WorkbookSource.AutodetectFormat := false;
|
WorkbookSource.AutodetectFormat := false;
|
||||||
case AcFileOpen.Dialog.FilterIndex of
|
case AcFileOpen.Dialog.FilterIndex of
|
||||||
@ -314,10 +315,11 @@ begin
|
|||||||
8: WorkbookSource.FileFormat := sfCSV; // Text files
|
8: WorkbookSource.FileFormat := sfCSV; // Text files
|
||||||
end;
|
end;
|
||||||
WorkbookSource.FileName := AcFileOpen.Dialog.FileName; // this loads the file
|
WorkbookSource.FileName := AcFileOpen.Dialog.FileName; // this loads the file
|
||||||
|
UpdateCaption;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ Saves the spreadsheet to the file selected by the AcFileSaveAs action }
|
{ Saves the spreadsheet to the file selected by the AcFileSaveAs action }
|
||||||
procedure TForm1.AcFileSaveAsAccept(Sender: TObject);
|
procedure TMainForm.AcFileSaveAsAccept(Sender: TObject);
|
||||||
var
|
var
|
||||||
fmt: TsSpreadsheetFormat;
|
fmt: TsSpreadsheetFormat;
|
||||||
begin
|
begin
|
||||||
@ -333,20 +335,21 @@ begin
|
|||||||
7: fmt := sfWikiTable_WikiMedia;
|
7: fmt := sfWikiTable_WikiMedia;
|
||||||
end;
|
end;
|
||||||
WorkbookSource.SaveToSpreadsheetFile(AcFileSaveAs.Dialog.FileName, fmt);
|
WorkbookSource.SaveToSpreadsheetFile(AcFileSaveAs.Dialog.FileName, fmt);
|
||||||
|
UpdateCaption;
|
||||||
finally
|
finally
|
||||||
Screen.Cursor := crDefault;
|
Screen.Cursor := crDefault;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ Adds a column before the active cell }
|
{ Adds a column before the active cell }
|
||||||
procedure TForm1.AcColAddExecute(Sender: TObject);
|
procedure TMainForm.AcColAddExecute(Sender: TObject);
|
||||||
begin
|
begin
|
||||||
WorksheetGrid.InsertCol(WorksheetGrid.Col);
|
WorksheetGrid.InsertCol(WorksheetGrid.Col);
|
||||||
WorksheetGrid.Col := WorksheetGrid.Col + 1;
|
WorksheetGrid.Col := WorksheetGrid.Col + 1;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ Deletes the column with the active cell }
|
{ Deletes the column with the active cell }
|
||||||
procedure TForm1.AcColDeleteExecute(Sender: TObject);
|
procedure TMainForm.AcColDeleteExecute(Sender: TObject);
|
||||||
var
|
var
|
||||||
c: Integer;
|
c: Integer;
|
||||||
begin
|
begin
|
||||||
@ -356,14 +359,14 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
{ Adds a row before the active cell }
|
{ Adds a row before the active cell }
|
||||||
procedure TForm1.AcRowAddExecute(Sender: TObject);
|
procedure TMainForm.AcRowAddExecute(Sender: TObject);
|
||||||
begin
|
begin
|
||||||
WorksheetGrid.InsertRow(WorksheetGrid.Row);
|
WorksheetGrid.InsertRow(WorksheetGrid.Row);
|
||||||
WorksheetGrid.Row := WorksheetGrid.Row + 1;
|
WorksheetGrid.Row := WorksheetGrid.Row + 1;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ Deletes the row with the active cell }
|
{ Deletes the row with the active cell }
|
||||||
procedure TForm1.AcRowDeleteExecute(Sender: TObject);
|
procedure TMainForm.AcRowDeleteExecute(Sender: TObject);
|
||||||
var
|
var
|
||||||
r: Integer;
|
r: Integer;
|
||||||
begin
|
begin
|
||||||
@ -373,17 +376,28 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
{ Toggles the spreadsheet inspector on and off }
|
{ Toggles the spreadsheet inspector on and off }
|
||||||
procedure TForm1.AcViewInspectorExecute(Sender: TObject);
|
procedure TMainForm.AcViewInspectorExecute(Sender: TObject);
|
||||||
begin
|
begin
|
||||||
InspectorTabControl.Visible := AcViewInspector.Checked;
|
InspectorTabControl.Visible := AcViewInspector.Checked;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ Event handler to synchronize the mode of the spreadsheet inspector with the
|
{ Event handler to synchronize the mode of the spreadsheet inspector with the
|
||||||
selected tab of the TabControl }
|
selected tab of the TabControl }
|
||||||
procedure TForm1.InspectorTabControlChange(Sender: TObject);
|
procedure TMainForm.InspectorTabControlChange(Sender: TObject);
|
||||||
begin
|
begin
|
||||||
Inspector.Mode := TsInspectorMode(InspectorTabControl.TabIndex);
|
Inspector.Mode := TsInspectorMode(InspectorTabControl.TabIndex);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TMainForm.UpdateCaption;
|
||||||
|
begin
|
||||||
|
if WorkbookSource = nil then
|
||||||
|
Caption := 'demo_ctrls'
|
||||||
|
else
|
||||||
|
Caption := Format('demo_ctrls - "%s" [%s]', [
|
||||||
|
WorkbookSource.Filename,
|
||||||
|
GetFileFormatName(WorkbookSource.Workbook.FileFormat)
|
||||||
|
]);
|
||||||
|
end;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
@ -6399,8 +6399,8 @@ class function TsWorkbook.GetFormatFromFileHeader(const AFileName: TFileName;
|
|||||||
const
|
const
|
||||||
BIFF2_HEADER: array[0..15] of byte = (
|
BIFF2_HEADER: array[0..15] of byte = (
|
||||||
$09,$00, $04,$00, $00,$00, $10,$00, $31,$00, $0A,$00, $C8,$00, $00,$00);
|
$09,$00, $04,$00, $00,$00, $10,$00, $31,$00, $0A,$00, $C8,$00, $00,$00);
|
||||||
BIFF58_HEADER: array[0..15] of byte = (
|
BIFF58_HEADER: array[0..7] of byte = (
|
||||||
$D0,$CF, $11,$E0, $A1,$B1, $1A,$E1, $00,$00, $00,$00, $00,$00, $00,$00);
|
$D0,$CF, $11,$E0, $A1,$B1, $1A,$E1);
|
||||||
BIFF5_MARKER: array[0..7] of widechar = (
|
BIFF5_MARKER: array[0..7] of widechar = (
|
||||||
'B', 'o', 'o', 'k', #0, #0, #0, #0);
|
'B', 'o', 'o', 'k', #0, #0, #0, #0);
|
||||||
BIFF8_MARKER:array[0..7] of widechar = (
|
BIFF8_MARKER:array[0..7] of widechar = (
|
||||||
@ -6419,7 +6419,7 @@ begin
|
|||||||
// Read first 16 bytes
|
// Read first 16 bytes
|
||||||
stream.ReadBuffer(buf, 16);
|
stream.ReadBuffer(buf, 16);
|
||||||
|
|
||||||
// Check for Excel 2#
|
// Check for Excel 2
|
||||||
ok := true;
|
ok := true;
|
||||||
for i:=0 to 15 do
|
for i:=0 to 15 do
|
||||||
if buf[i] <> BIFF2_HEADER[i] then
|
if buf[i] <> BIFF2_HEADER[i] then
|
||||||
@ -6434,7 +6434,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
// Check for Excel 5 or 8
|
// Check for Excel 5 or 8
|
||||||
for i:=0 to 15 do
|
for i:=0 to 7 do
|
||||||
if buf[i] <> BIFF58_HEADER[i] then
|
if buf[i] <> BIFF58_HEADER[i] then
|
||||||
exit;
|
exit;
|
||||||
|
|
||||||
|
@ -387,7 +387,6 @@ begin
|
|||||||
CurStreamPos := AStream.Position;
|
CurStreamPos := AStream.Position;
|
||||||
|
|
||||||
case RecordType of
|
case RecordType of
|
||||||
|
|
||||||
INT_EXCEL_ID_BLANK : ReadBlank(AStream);
|
INT_EXCEL_ID_BLANK : ReadBlank(AStream);
|
||||||
INT_EXCEL_ID_BOOLERROR : ReadBool(AStream);
|
INT_EXCEL_ID_BOOLERROR : ReadBool(AStream);
|
||||||
INT_EXCEL_ID_MULBLANK : ReadMulBlank(AStream);
|
INT_EXCEL_ID_MULBLANK : ReadMulBlank(AStream);
|
||||||
@ -720,6 +719,7 @@ end;
|
|||||||
procedure TsSpreadBIFF5Reader.ReadFromStream(AStream: TStream; AData: TsWorkbook);
|
procedure TsSpreadBIFF5Reader.ReadFromStream(AStream: TStream; AData: TsWorkbook);
|
||||||
var
|
var
|
||||||
BIFF5EOF: Boolean;
|
BIFF5EOF: Boolean;
|
||||||
|
p,s: Int64;
|
||||||
begin
|
begin
|
||||||
{ Initializations }
|
{ Initializations }
|
||||||
|
|
||||||
@ -742,10 +742,15 @@ begin
|
|||||||
ReadWorksheet(AStream, AData);
|
ReadWorksheet(AStream, AData);
|
||||||
|
|
||||||
// Check for the end of the file
|
// Check for the end of the file
|
||||||
|
p := AStream.Position;
|
||||||
|
s := AStream.Size;
|
||||||
if AStream.Position >= AStream.Size then BIFF5EOF := True;
|
if AStream.Position >= AStream.Size then BIFF5EOF := True;
|
||||||
|
|
||||||
// Final preparations
|
// Final preparations
|
||||||
Inc(FCurrentWorksheet);
|
Inc(FCurrentWorksheet);
|
||||||
|
if FCurrentWorksheet = FWorksheetNames.Count then BIFF5EOF := True;
|
||||||
|
// It can happen in files written by Office97 that the OLE directory is
|
||||||
|
// at the end of the file.
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if not FPaletteFound then
|
if not FPaletteFound then
|
||||||
|
@ -638,6 +638,9 @@ begin
|
|||||||
|
|
||||||
// Final preparations
|
// Final preparations
|
||||||
Inc(FCurrentWorksheet);
|
Inc(FCurrentWorksheet);
|
||||||
|
if FCurrentWorksheet = FWorksheetNames.Count then BIFF8EOF := True;
|
||||||
|
// It can happen in files written by Office97 that the OLE directory is
|
||||||
|
// at the end of the file.
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if not FPaletteFound then
|
if not FPaletteFound then
|
||||||
|
Reference in New Issue
Block a user