fpspreadsheet: Add reading of cell/sheet/workbook protection for xls biff8.

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@5789 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2017-03-05 16:52:17 +00:00
parent 6126788bec
commit 2f54a9bfca
2 changed files with 174 additions and 87 deletions

View File

@@ -368,6 +368,9 @@ const
{ XF CELL BACKGROUND PATTERN } { XF CELL BACKGROUND PATTERN }
MASK_XF_BACKGROUND_PATTERN = $FC000000; MASK_XF_BACKGROUND_PATTERN = $FC000000;
{ XP CELL PROTECTION }
MASK_XF_PROTECTION = $0007;
{ HLINK FLAGS } { HLINK FLAGS }
MASK_HLINK_LINK = $00000001; MASK_HLINK_LINK = $00000001;
MASK_HLINK_ABSOLUTE = $00000002; MASK_HLINK_ABSOLUTE = $00000002;
@@ -799,16 +802,19 @@ begin
case RecordType of case RecordType of
INT_EXCEL_ID_BOF : ; INT_EXCEL_ID_BOF : ;
INT_EXCEL_ID_BOUNDSHEET : ReadBoundSheet(AStream); INT_EXCEL_ID_BOUNDSHEET : ReadBoundSheet(AStream);
INT_EXCEL_ID_CODEPAGE : ReadCodepage(AStream);
INT_EXCEL_ID_DATEMODE : ReadDateMode(AStream);
INT_EXCEL_ID_DEFINEDNAME : ReadDEFINEDNAME(AStream); INT_EXCEL_ID_DEFINEDNAME : ReadDEFINEDNAME(AStream);
INT_EXCEL_ID_EOF : SectionEOF := True; INT_EXCEL_ID_EOF : SectionEOF := True;
INT_EXCEL_ID_EXTERNSHEET : ReadEXTERNSHEET(AStream); INT_EXCEL_ID_EXTERNSHEET : ReadEXTERNSHEET(AStream);
INT_EXCEL_ID_SST : ReadSST(AStream);
INT_EXCEL_ID_CODEPAGE : ReadCodepage(AStream);
INT_EXCEL_ID_FONT : ReadFont(AStream); INT_EXCEL_ID_FONT : ReadFont(AStream);
INT_EXCEL_ID_FORMAT : ReadFormat(AStream); INT_EXCEL_ID_FORMAT : ReadFormat(AStream);
INT_EXCEL_ID_XF : ReadXF(AStream);
INT_EXCEL_ID_DATEMODE : ReadDateMode(AStream);
INT_EXCEL_ID_PALETTE : ReadPalette(AStream); INT_EXCEL_ID_PALETTE : ReadPalette(AStream);
INT_EXCEL_ID_PASSWORD : ReadPASSWORD(AStream);
INT_EXCEL_ID_PROTECT : ReadPROTECT(AStream);
INT_EXCEL_ID_SST : ReadSST(AStream);
INT_EXCEL_ID_WINDOWPROTECT : ReadWindowProtect(AStream);
INT_EXCEL_ID_XF : ReadXF(AStream);
else else
// nothing // nothing
end; end;
@@ -874,6 +880,8 @@ begin
INT_EXCEL_ID_OBJ : ReadOBJ(AStream); INT_EXCEL_ID_OBJ : ReadOBJ(AStream);
INT_EXCEL_ID_PAGESETUP : ReadPageSetup(AStream); INT_EXCEL_ID_PAGESETUP : ReadPageSetup(AStream);
INT_EXCEL_ID_PANE : ReadPane(AStream); INT_EXCEL_ID_PANE : ReadPane(AStream);
INT_EXCEL_ID_PASSWORD : ReadPASSWORD(AStream, FWorksheet);
INT_EXCEL_ID_PROTECT : ReadPROTECT(AStream, FWorksheet);
INT_EXCEL_ID_PRINTGRID : ReadPrintGridLines(AStream); INT_EXCEL_ID_PRINTGRID : ReadPrintGridLines(AStream);
INT_EXCEL_ID_PRINTHEADERS : ReadPrintHeaders(AStream); INT_EXCEL_ID_PRINTHEADERS : ReadPrintHeaders(AStream);
INT_EXCEL_ID_RIGHTMARGIN : ReadMargin(AStream, 1); INT_EXCEL_ID_RIGHTMARGIN : ReadMargin(AStream, 1);
@@ -1678,6 +1686,14 @@ begin
end; end;
end; end;
// Protection
case WordLEToN(rec.XFType_Prot_ParentXF) and MASK_XF_PROTECTION of
0: fmt.Protection := [];
1: fmt.Protection := [cpLockCell];
2: fmt.Protection := [cpHideFormulas];
3: fmt.Protection := [cpLockCell, cpHideFormulas];
end;
// Add the XF to the internal cell format list // Add the XF to the internal cell format list
FCellFormatList.Add(fmt); FCellFormatList.Add(fmt);
end; end;

View File

@@ -17,9 +17,12 @@ uses
const const
{ RECORD IDs which didn't change across versions 2-8 } { RECORD IDs which didn't change across versions 2-8 }
INT_EXCEL_ID_EOF = $000A; INT_EXCEL_ID_EOF = $000A;
INT_EXCEL_ID_PROTECT = $0012;
INT_EXCEL_ID_PASSWORD = $0013;
INT_EXCEL_ID_HEADER = $0014; INT_EXCEL_ID_HEADER = $0014;
INT_EXCEL_ID_FOOTER = $0015; INT_EXCEL_ID_FOOTER = $0015;
INT_EXCEL_ID_EXTERNSHEET = $0017; INT_EXCEL_ID_EXTERNSHEET = $0017;
INT_EXCEL_ID_WINDOWPROTECT = $0019;
INT_EXCEL_ID_NOTE = $001C; INT_EXCEL_ID_NOTE = $001C;
INT_EXCEL_ID_SELECTION = $001D; INT_EXCEL_ID_SELECTION = $001D;
INT_EXCEL_ID_DATEMODE = $0022; INT_EXCEL_ID_DATEMODE = $0022;
@@ -451,8 +454,12 @@ type
procedure ReadPageSetup(AStream: TStream); procedure ReadPageSetup(AStream: TStream);
// Read PANE record // Read PANE record
procedure ReadPane(AStream: TStream); procedure ReadPane(AStream: TStream);
// Read PASSWORD record
procedure ReadPASSWORD(AStream: TStream; AWorksheet: TsWorksheet = nil);
procedure ReadPrintGridLines(AStream: TStream); procedure ReadPrintGridLines(AStream: TStream);
procedure ReadPrintHeaders(AStream: TStream); procedure ReadPrintHeaders(AStream: TStream);
// Reads whether the workbook or worksheet is protected
procedure ReadPROTECT(AStream: TStream; AWorksheet: TsWorksheet = nil);
// Read an RK value cell // Read an RK value cell
procedure ReadRKValue(AStream: TStream); procedure ReadRKValue(AStream: TStream);
// Read the row, column, and XF index at the current stream position // Read the row, column, and XF index at the current stream position
@@ -491,6 +498,8 @@ type
procedure ReadVCENTER(AStream: TStream); procedure ReadVCENTER(AStream: TStream);
// Read WINDOW2 record (gridlines, sheet headers) // Read WINDOW2 record (gridlines, sheet headers)
procedure ReadWindow2(AStream: TStream); virtual; procedure ReadWindow2(AStream: TStream); virtual;
// Read WINDOWPROTECT record
procedure ReadWindowProtect(AStream: TStream);
procedure ReadWorkbookGlobals(AStream: TStream); virtual; procedure ReadWorkbookGlobals(AStream: TStream); virtual;
procedure ReadWorksheet(AStream: TStream); virtual; procedure ReadWorksheet(AStream: TStream); virtual;
@@ -2017,6 +2026,35 @@ begin
// If BIFF5-BIFF8 there is 1 more byte which is not used here. // If BIFF5-BIFF8 there is 1 more byte which is not used here.
end; end;
{@@ ----------------------------------------------------------------------------
Reads the PASSWORD record containing the encrypted password
-------------------------------------------------------------------------------}
procedure TsSpreadBIFFReader.ReadPASSWORD(AStream: TStream;
AWorksheet: TsWorksheet = nil);
var
hash: Word;
cinfo: TsCryptoInfo;
begin
hash := WordLEToN(AStream.ReadWord);
if hash = 0 then
exit; // no password
if AWorksheet = nil then begin
// Password for workbook protection
cinfo := FWorkbook.CryptoInfo;
cinfo.PasswordHash := Format('%.4x', [hash]);
cinfo.Algorithm := caExcel;
FWorkbook.CryptoInfo := cinfo;
end else
begin
// Password for worksheet protection
cinfo := AWorksheet.CryptoInfo;
cinfo.PasswordHash := Format('%.4x', [hash]);
cinfo.Algorithm := caExcel;
AWorksheet.CryptoInfo := cinfo;
end;
end;
{@@ ---------------------------------------------------------------------------- {@@ ----------------------------------------------------------------------------
Reads whether the gridlines are printed or not Reads whether the gridlines are printed or not
-------------------------------------------------------------------------------} -------------------------------------------------------------------------------}
@@ -2043,6 +2081,28 @@ begin
Options := Options + [poPrintHeaders]; Options := Options + [poPrintHeaders];
end; end;
{@@ ----------------------------------------------------------------------------
Determines whether the workbook or worksheet is protected
-------------------------------------------------------------------------------}
procedure TsSpreadBIFFReader.ReadPROTECT(AStream: TStream;
AWorksheet: TsWorksheet = nil);
var
p: Word;
begin
p := WordLEToN(AStream.ReadWord);
if p = 0 then // not protected
exit;
if AWorksheet = nil then
// Workbook protection
FWorkbook.Protection := FWorkbook.Protection + [bpLockStructure]
else begin
// Worksheet protection
AWorksheet.Protection := FWorksheet.Protection + [spCells];
AWorksheet.Protect(true);
end;
end;
{@@ ---------------------------------------------------------------------------- {@@ ----------------------------------------------------------------------------
Reads the row, column and xf index Reads the row, column and xf index
NOT VALID for BIFF2 NOT VALID for BIFF2
@@ -2875,6 +2935,17 @@ begin
Unused(AStream); Unused(AStream);
end; end;
procedure TsSpreadBIFFReader.ReadWindowProtect(AStream: TStream);
var
p: Word;
begin
p := WordLEToN(AStream.ReadWord);
if p = 0 then // Workbook not protected
FWorkbook.Protection := FWorkbook.Protection - [bpLockWindows]
else // Workbook protection
FWorkbook.Protection := FWorkbook.Protection + [bpLockWindows];
end;
procedure TsSpreadBIFFReader.ReadWorksheet(AStream: TStream); procedure TsSpreadBIFFReader.ReadWorksheet(AStream: TStream);
begin begin
// To be overridden by BIFF5 and BIFF8 // To be overridden by BIFF5 and BIFF8