You've already forked lazarus-ccr
fpspreadsheet: Add writing support for xls password hashes. Add test case for it.
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@5799 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -308,6 +308,18 @@ msgstr "Diese Operation bei Index %d überschreitet den Bereich der definierten
|
||||
msgid "Palette index %d"
|
||||
msgstr "Palettenindex %d"
|
||||
|
||||
#: fpsstrings.rspasswordremoved_biff2
|
||||
msgid "Password removed (BIFF2 requires matching workbook and worksheet passwords)"
|
||||
msgstr ""
|
||||
|
||||
#: fpsstrings.rspasswordremoved_excel
|
||||
msgid "Password removed (Hashing algorithm not compatible with Excel)"
|
||||
msgstr ""
|
||||
|
||||
#: fpsstrings.rspasswordremoved_notvalid
|
||||
msgid "Password removed (Not valid)."
|
||||
msgstr ""
|
||||
|
||||
#: fpsstrings.rspurple
|
||||
msgid "purple"
|
||||
msgstr "purpur"
|
||||
@ -419,3 +431,4 @@ msgstr "Die Datei kann nicht geschrieben werden, weil der Name des Arbeitsblatte
|
||||
#: fpsstrings.rsyellow
|
||||
msgid "yellow"
|
||||
msgstr "gelb"
|
||||
|
||||
|
@ -297,6 +297,18 @@ msgstr ""
|
||||
msgid "Palette index %d"
|
||||
msgstr ""
|
||||
|
||||
#: fpsstrings.rspasswordremoved_biff2
|
||||
msgid "Password removed (BIFF2 requires matching workbook and worksheet passwords)"
|
||||
msgstr ""
|
||||
|
||||
#: fpsstrings.rspasswordremoved_excel
|
||||
msgid "Password removed (Hashing algorithm not compatible with Excel)"
|
||||
msgstr ""
|
||||
|
||||
#: fpsstrings.rspasswordremoved_notvalid
|
||||
msgid "Password removed (Not valid)."
|
||||
msgstr ""
|
||||
|
||||
#: fpsstrings.rspurple
|
||||
msgid "purple"
|
||||
msgstr ""
|
||||
|
@ -311,6 +311,18 @@ msgstr "A művelet túllépi a rács sorainak tartományát."
|
||||
msgid "Palette index %d"
|
||||
msgstr "Paletta index: %d"
|
||||
|
||||
#: fpsstrings.rspasswordremoved_biff2
|
||||
msgid "Password removed (BIFF2 requires matching workbook and worksheet passwords)"
|
||||
msgstr ""
|
||||
|
||||
#: fpsstrings.rspasswordremoved_excel
|
||||
msgid "Password removed (Hashing algorithm not compatible with Excel)"
|
||||
msgstr ""
|
||||
|
||||
#: fpsstrings.rspasswordremoved_notvalid
|
||||
msgid "Password removed (Not valid)."
|
||||
msgstr ""
|
||||
|
||||
#: fpsstrings.rspurple
|
||||
msgid "purple"
|
||||
msgstr "bíbor"
|
||||
|
@ -297,6 +297,18 @@ msgstr ""
|
||||
msgid "Palette index %d"
|
||||
msgstr ""
|
||||
|
||||
#: fpsstrings.rspasswordremoved_biff2
|
||||
msgid "Password removed (BIFF2 requires matching workbook and worksheet passwords)"
|
||||
msgstr ""
|
||||
|
||||
#: fpsstrings.rspasswordremoved_excel
|
||||
msgid "Password removed (Hashing algorithm not compatible with Excel)"
|
||||
msgstr ""
|
||||
|
||||
#: fpsstrings.rspasswordremoved_notvalid
|
||||
msgid "Password removed (Not valid)."
|
||||
msgstr ""
|
||||
|
||||
#: fpsstrings.rspurple
|
||||
msgid "purple"
|
||||
msgstr ""
|
||||
|
@ -301,6 +301,18 @@ msgstr "Эта операция превышает диапазон опреде
|
||||
msgid "Palette index %d"
|
||||
msgstr "Индекс палитры %d"
|
||||
|
||||
#: fpsstrings.rspasswordremoved_biff2
|
||||
msgid "Password removed (BIFF2 requires matching workbook and worksheet passwords)"
|
||||
msgstr ""
|
||||
|
||||
#: fpsstrings.rspasswordremoved_excel
|
||||
msgid "Password removed (Hashing algorithm not compatible with Excel)"
|
||||
msgstr ""
|
||||
|
||||
#: fpsstrings.rspasswordremoved_notvalid
|
||||
msgid "Password removed (Not valid)."
|
||||
msgstr ""
|
||||
|
||||
#: fpsstrings.rspurple
|
||||
msgid "purple"
|
||||
msgstr ""
|
||||
|
@ -4298,12 +4298,18 @@ begin
|
||||
s := GetAttrValue(styleChildNode, 'style:cell-protect');
|
||||
if s = 'none' then
|
||||
fmt.Protection := []
|
||||
else if s = 'hidden-and-protected' then
|
||||
else if (s = 'protected formula-hidden') or (s = 'formula-hidden protected') then
|
||||
fmt.Protection := [cpLockCell, cpHideFormulas]
|
||||
else if s = 'protected' then
|
||||
fmt.Protection := [cpLockCell]
|
||||
else if s = 'formula-hidden' then
|
||||
fmt.Protection := [cpHideFormulas];
|
||||
fmt.Protection := [cpHideFormulas]
|
||||
else if s = 'hidden-and-protected' then
|
||||
fmt.Protection := [cpLockCell, cpHideFormulas];
|
||||
// NOTE: This not exact... According to
|
||||
// https://docs.oasis-open.org/office/v1.2/os/OpenDocument-v1.2-os-part1.html,
|
||||
// section 20.246, this hides and locks cell content, not just
|
||||
// formulas...
|
||||
if fmt.Protection <> DEFAULT_CELL_PROTECTION then
|
||||
Include(fmt.UsedFormattingFields, uffProtection);
|
||||
end
|
||||
@ -5359,7 +5365,7 @@ begin
|
||||
else if (AFormat.Protection *[cpLockCell, cpHideFormulas] = [cpHideFormulas]) then
|
||||
Result := 'formula-hidden'
|
||||
else
|
||||
Result := 'hidden-and-protected'; // or: 'protected formula-hidden'
|
||||
Result := 'protected formula-hidden'; // or: 'hidden-and-protected'
|
||||
Result := ' style:cell-protect="' + Result + '"';
|
||||
end;
|
||||
|
||||
|
@ -177,6 +177,11 @@ resourcestring
|
||||
rsMultipleSheetsOnlyWithRestorePosition = 'Export to multiple sheets is possible '+
|
||||
'only if position is restored.';
|
||||
|
||||
// Protection
|
||||
rsPasswordRemoved_BIFF2 = 'Password removed (BIFF2 requires matching workbook '+
|
||||
'and worksheet passwords)';
|
||||
rsPasswordRemoved_NotValid = 'Password removed (Not valid).';
|
||||
rsPasswordRemoved_Excel = 'Password removed (Hashing algorithm not compatible with Excel)';
|
||||
|
||||
const
|
||||
// Color names which do not have to be translated. They will be removed.
|
||||
|
@ -63,6 +63,7 @@ type
|
||||
procedure ReadIXFE(AStream: TStream);
|
||||
procedure ReadLabel(AStream: TStream); override;
|
||||
procedure ReadNumber(AStream: TStream); override;
|
||||
procedure ReadPASSWORD(AStream: TStream);
|
||||
procedure ReadPROTECT(AStream: TStream);
|
||||
procedure ReadRowColXF(AStream: TStream; out ARow, ACol: Cardinal; out AXF: Word); override;
|
||||
procedure ReadRowInfo(AStream: TStream); override;
|
||||
@ -122,6 +123,7 @@ type
|
||||
const AValue: string; ACell: PCell); override;
|
||||
procedure WriteNumber(AStream: TStream; const ARow, ACol: Cardinal;
|
||||
const AValue: double; ACell: PCell); override;
|
||||
procedure WritePASSWORD(AStream: TStream);
|
||||
procedure WriteRow(AStream: TStream; ASheet: TsWorksheet;
|
||||
ARowIndex, AFirstColIndex, ALastColIndex: Cardinal; ARow: PRow); override;
|
||||
procedure WriteRPNFormula(AStream: TStream; const ARow, ACol: Cardinal;
|
||||
@ -621,7 +623,7 @@ begin
|
||||
INT_EXCEL_ID_NUMBER : ReadNumber(AStream);
|
||||
INT_EXCEL_ID_PANE : ReadPane(AStream);
|
||||
INT_EXCEL_ID_OBJECTPROTECT : ReadObjectProtect(AStream);
|
||||
INT_EXCEL_ID_PASSWORD : ReadPASSWORD(AStream, FWorksheet);
|
||||
INT_EXCEL_ID_PASSWORD : ReadPASSWORD(AStream);
|
||||
INT_EXCEL_ID_PRINTGRID : ReadPrintGridLines(AStream);
|
||||
INT_EXCEL_ID_PRINTHEADERS : ReadPrintHeaders(AStream);
|
||||
INT_EXCEL_ID_PROTECT : ReadPROTECT(AStream);
|
||||
@ -871,6 +873,29 @@ begin
|
||||
FPendingXFIndex := WordLEToN(AStream.ReadWord);
|
||||
end;
|
||||
|
||||
{@@ ----------------------------------------------------------------------------
|
||||
Reads a PASSWORD record. Since BIFF2 does not have multiple worksheets the
|
||||
same password is stored in the workbook and worksheet cryptoinfo records.
|
||||
-------------------------------------------------------------------------------}
|
||||
procedure TsSpreadBIFF2Reader.ReadPASSWORD(AStream: TStream);
|
||||
var
|
||||
hash: Word;
|
||||
cinfo: TsCryptoInfo;
|
||||
begin
|
||||
hash := WordLEToN(AStream.ReadWord);
|
||||
if hash = 0 then
|
||||
exit; // no password
|
||||
|
||||
InitCryptoInfo(cinfo);
|
||||
cinfo.PasswordHash := Format('%.4x', [hash]);
|
||||
cinfo.Algorithm := caExcel;
|
||||
|
||||
// Use the same password for workbook and worksheet protection because
|
||||
// BIFF2 can have only a single sheet.
|
||||
FWorkbook.CryptoInfo := cinfo;
|
||||
FWorksheet.CryptoInfo := cinfo;
|
||||
end;
|
||||
|
||||
procedure TsSpreadBIFF2Reader.ReadPROTECT(AStream: TStream);
|
||||
begin
|
||||
inherited ReadPROTECT(AStream);
|
||||
@ -1571,10 +1596,12 @@ begin
|
||||
|
||||
WriteFormatCount(AStream);
|
||||
WriteNumFormats(AStream);
|
||||
|
||||
if (bpLockStructure in Workbook.Protection) or FWorksheet.IsProtected then
|
||||
WritePROTECT(AStream, true);
|
||||
WriteWindowProtect(AStream, bpLockWindows in Workbook.Protection);
|
||||
WriteObjectProtect(AStream, FWorksheet);
|
||||
WritePASSWORD(AStream);
|
||||
|
||||
WriteXFRecords(AStream);
|
||||
WriteDefaultColWidth(AStream, FWorksheet);
|
||||
@ -2216,6 +2243,64 @@ begin
|
||||
AStream.WriteBuffer(rec, SizeOf(Rec));
|
||||
end;
|
||||
|
||||
procedure TsSpreadBIFF2Writer.WritePassword(AStream: TStream);
|
||||
var
|
||||
hash: Word;
|
||||
hb, hs: LongInt;
|
||||
begin
|
||||
hb := 0;
|
||||
if (Workbook.CryptoInfo.PasswordHash <> '') and
|
||||
not TryStrToInt('$' + Workbook.CryptoInfo.PasswordHash, hb) then
|
||||
begin
|
||||
Workbook.AddErrorMsg(rsPasswordRemoved_NotValid);
|
||||
exit;
|
||||
end;
|
||||
|
||||
hs := 0;
|
||||
if (FWorksheet.CryptoInfo.PasswordHash <> '') and
|
||||
not TryStrToInt('$' + FWorksheet.CryptoInfo.PasswordHash, hs) then
|
||||
begin
|
||||
Workbook.AddErrorMsg(rsPasswordRemoved_NotValid);
|
||||
exit;
|
||||
end;
|
||||
|
||||
// Neither workbook nor worksheet password set
|
||||
if (hb = 0) and (hs = 0) then
|
||||
exit;
|
||||
|
||||
// Only workbook password set. Check for Excel algorithm.
|
||||
if (hb <> 0) and (hs = 0) then begin
|
||||
if Workbook.CryptoInfo.Algorithm <> caExcel then begin
|
||||
Workbook.AddErrorMsg(rsPasswordRemoved_Excel);
|
||||
exit;
|
||||
end;
|
||||
hash := hb;
|
||||
end else
|
||||
// Only worksheet password set, check for Excel algorithm
|
||||
if (hs <> 0) and (hb = 0) then begin
|
||||
if FWorksheet.CryptoInfo.Algorithm <> caExcel then begin
|
||||
Workbook.AddErrorMsg(rsPasswordRemoved_Excel);
|
||||
exit;
|
||||
end;
|
||||
hash := hs;
|
||||
end else
|
||||
if (hs <> hb) then begin
|
||||
Workbook.AddErrorMsg(rsPasswordRemoved_BIFF2);
|
||||
exit;
|
||||
end else
|
||||
if (Workbook.CryptoInfo.Algorithm <> caExcel) or
|
||||
(FWorksheet.CryptoInfo.Algorithm <> caExcel) then
|
||||
begin
|
||||
Workbook.AddErrorMsg(rsPasswordRemoved_Excel);
|
||||
exit;
|
||||
end else
|
||||
hash := hs; // or hb -- they are equal here.
|
||||
|
||||
// Write out record
|
||||
WriteBIFFHeader(AStream, INT_EXCEL_ID_PASSWORD, 2);
|
||||
AStream.WriteWord(WordToLE(hash));
|
||||
end;
|
||||
|
||||
procedure TsSpreadBIFF2Writer.WriteRow(AStream: TStream; ASheet: TsWorksheet;
|
||||
ARowIndex, AFirstColIndex, ALastColIndex: Cardinal; ARow: PRow);
|
||||
var
|
||||
|
@ -1140,6 +1140,7 @@ begin
|
||||
WriteCODEPAGE(AStream, FCodePage);
|
||||
WriteWindowProtect(AStream, bpLockWindows in Workbook.Protection);
|
||||
WritePROTECT(AStream, bpLockStructure in Workbook.Protection);
|
||||
WritePASSWORD(AStream, Workbook.CryptoInfo);
|
||||
WriteEXTERNCOUNT(AStream);
|
||||
WriteEXTERNSHEET(AStream);
|
||||
WriteDefinedNames(AStream);
|
||||
@ -1187,11 +1188,15 @@ begin
|
||||
WriteMargin(AStream, 2); // 2 = top margin
|
||||
WriteMargin(AStream, 3); // 3 = bottom margin
|
||||
WritePageSetup(AStream);
|
||||
|
||||
// Protection
|
||||
if FWorksheet.IsProtected then begin
|
||||
WritePROTECT(AStream, true);
|
||||
// WriteScenarioProtect(AStream);
|
||||
WriteObjectProtect(AStream, FWorksheet);
|
||||
WritePASSWORD(AStream, FWorksheet.CryptoInfo);
|
||||
end;
|
||||
|
||||
WriteDefaultColWidth(AStream, FWorksheet);
|
||||
WriteColInfos(AStream, FWorksheet);
|
||||
WriteDimensions(AStream, FWorksheet);
|
||||
|
@ -2132,6 +2132,7 @@ begin
|
||||
WriteCodePage(AStream, 'ucs2le'); // = utf-16
|
||||
WriteWindowProtect(AStream, bpLockWindows in Workbook.Protection);
|
||||
WritePROTECT(AStream, bpLockStructure in Workbook.Protection);
|
||||
WritePASSWORD(AStream, Workbook.CryptoInfo);
|
||||
WriteWINDOW1(AStream);
|
||||
WriteFonts(AStream);
|
||||
WriteNumFormats(AStream);
|
||||
@ -2179,15 +2180,18 @@ begin
|
||||
WriteMargin(AStream, 2); // 2 = top margin
|
||||
WriteMargin(AStream, 3); // 3 = bottom margin
|
||||
WritePageSetup(AStream);
|
||||
|
||||
// Protection
|
||||
if FWorksheet.IsProtected then begin
|
||||
WritePROTECT(AStream, true);
|
||||
// WriteScenarioProtect(AStream);
|
||||
WriteObjectProtect(AStream, FWorksheet);
|
||||
WritePASSWORD(AStream, FWorksheet.CryptoInfo);
|
||||
end;
|
||||
|
||||
WriteDefaultColWidth(AStream, FWorksheet);
|
||||
WriteColInfos(AStream, FWorksheet);
|
||||
WriteDimensions(AStream, FWorksheet);
|
||||
//WriteRowAndCellBlock(AStream, sheet);
|
||||
|
||||
if (boVirtualMode in Workbook.Options) then
|
||||
WriteVirtualCells(AStream, FWorksheet)
|
||||
|
@ -596,6 +596,7 @@ type
|
||||
// Writes out a PANE record
|
||||
procedure WritePane(AStream: TStream; ASheet: TsWorksheet; IsBiff58: Boolean;
|
||||
out ActivePane: Byte);
|
||||
procedure WritePASSWORD(AStream: TStream; const ACryptoInfo: TsCryptoInfo);
|
||||
// Writes out whether grid lines are printed
|
||||
procedure WritePrintGridLines(AStream: TStream);
|
||||
procedure WritePrintHeaders(AStream: TStream);
|
||||
@ -4038,6 +4039,33 @@ begin
|
||||
{ Not used (BIFF5-BIFF8 only, not written in BIFF2-BIFF4 }
|
||||
end;
|
||||
|
||||
{@@ ----------------------------------------------------------------------------
|
||||
Writes a PASSWORD record containing the hash of a password
|
||||
-------------------------------------------------------------------------------}
|
||||
procedure TsSpreadBIFFWriter.WritePASSWORD(AStream: TStream;
|
||||
const ACryptoInfo: TsCryptoInfo);
|
||||
var
|
||||
hash: LongInt;
|
||||
begin
|
||||
if ACryptoInfo.PasswordHash = '' then
|
||||
exit;
|
||||
|
||||
// Can write only passwords that were hashed using Excel's algorithm.
|
||||
if ACryptoInfo.Algorithm <> caExcel then begin
|
||||
Workbook.AddErrorMsg(rsPasswordRemoved_Excel);
|
||||
exit;
|
||||
end;
|
||||
|
||||
// Excel's hash produces a hex number which is stored by fps as a string.
|
||||
if not TryStrToInt('$' + ACryptoInfo.PasswordHash, hash) then begin
|
||||
Workbook.AddErrorMsg(rsPasswordRemoved_NotValid);
|
||||
exit;
|
||||
end;
|
||||
|
||||
WriteBIFFHeader(AStream, INT_EXCEL_ID_PASSWORD, 2);
|
||||
AStream.WriteWord(WordToLE(hash));
|
||||
end;
|
||||
|
||||
{@@ ----------------------------------------------------------------------------
|
||||
Writes out whether grid lines are printed or not
|
||||
-------------------------------------------------------------------------------}
|
||||
|
@ -29,6 +29,7 @@ type
|
||||
procedure TestWriteRead_WorksheetProtection(AFormat: TsSpreadsheetFormat;
|
||||
ACondition: Integer);
|
||||
procedure TestWriteRead_CellProtection(AFormat: TsSpreadsheetFormat);
|
||||
procedure TestWriteRead_Passwords(AFormat: TsSpreadsheetFormat);
|
||||
published
|
||||
// Writes out protection & reads back.
|
||||
|
||||
@ -42,6 +43,7 @@ type
|
||||
procedure TestWriteRead_BIFF2_WorksheetProtection_Objects;
|
||||
|
||||
procedure TestWriteRead_BIFF2_CellProtection;
|
||||
procedure TestWriteRead_BIFF2_Passwords;
|
||||
|
||||
{ BIFF5 protection tests }
|
||||
procedure TestWriteRead_BIFF5_WorkbookProtection_None;
|
||||
@ -55,6 +57,7 @@ type
|
||||
procedure TestWriteRead_BIFF5_WorksheetProtection_Objects;
|
||||
|
||||
procedure TestWriteRead_BIFF5_CellProtection;
|
||||
procedure TestWriteRead_BIFF5_Passwords;
|
||||
|
||||
{ BIFF8 protection tests }
|
||||
procedure TestWriteRead_BIFF8_WorkbookProtection_None;
|
||||
@ -68,6 +71,7 @@ type
|
||||
procedure TestWriteRead_BIFF8_WorksheetProtection_Objects;
|
||||
|
||||
procedure TestWriteRead_BIFF8_CellProtection;
|
||||
procedure TestWriteRead_BIFF8_Passwords;
|
||||
|
||||
{ OOXML protection tests }
|
||||
procedure TestWriteRead_OOXML_WorkbookProtection_None;
|
||||
@ -91,6 +95,8 @@ type
|
||||
|
||||
procedure TestWriteRead_OOXML_CellProtection;
|
||||
|
||||
procedure TestWriteRead_OOXML_Passwords;
|
||||
|
||||
{ ODS protection tests }
|
||||
procedure TestWriteRead_ODS_WorkbookProtection_None;
|
||||
procedure TestWriteRead_ODS_WorkbookProtection_Struct;
|
||||
@ -107,6 +113,9 @@ type
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
fpsUtils;
|
||||
|
||||
const
|
||||
ProtectionSheet = 'Protection';
|
||||
|
||||
@ -339,6 +348,67 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSpreadWriteReadProtectionTests.TestWriteRead_Passwords(
|
||||
AFormat: TsSpreadsheetFormat);
|
||||
var
|
||||
MyWorkbook: TsWorkbook;
|
||||
MyWorksheet: TsWorksheet;
|
||||
cell: PCell;
|
||||
TempFile: string; //write xls/xml to this file and read back from it
|
||||
bi, si, cinfo: TsCryptoInfo;
|
||||
msg: String;
|
||||
begin
|
||||
TempFile := GetTempFileName;
|
||||
|
||||
MyWorkbook := TsWorkbook.Create;
|
||||
try
|
||||
MyWorksheet := MyWorkBook.AddWorksheet(ProtectionSheet);
|
||||
|
||||
MyWorkbook.Protection := [bpLockStructure];
|
||||
InitCryptoInfo(bi);
|
||||
bi.PasswordHash := 'ABCD';
|
||||
bi.Algorithm := caExcel;
|
||||
MyWorkbook.CryptoInfo := bi;
|
||||
|
||||
MyWorksheet.Protect(true);
|
||||
if AFormat = sfExcel2 then
|
||||
si := bi // in BIFF2: use the same crypto info for sheet and book
|
||||
else begin
|
||||
InitCryptoInfo(si);
|
||||
si.PasswordHash := 'DCBA';
|
||||
si.Algorithm := caExcel;
|
||||
end;
|
||||
MyWorksheet.CryptoInfo := si;
|
||||
|
||||
MyWorkBook.WriteToFile(TempFile, AFormat, true);
|
||||
finally
|
||||
MyWorkbook.Free;
|
||||
end;
|
||||
|
||||
// Open the spreadsheet
|
||||
MyWorkbook := TsWorkbook.Create;
|
||||
try
|
||||
MyWorkbook.ReadFromFile(TempFile, AFormat);
|
||||
MyWorksheet := MyWorkbook.GetFirstWorksheet;
|
||||
|
||||
cInfo := MyWorkbook.CryptoInfo;
|
||||
CheckEquals(
|
||||
bi.PasswordHash, cinfo.PasswordHash,
|
||||
'Workbook protection password hash mismatch'
|
||||
);
|
||||
|
||||
cInfo := MyWorksheet.CryptoInfo;
|
||||
CheckEquals(
|
||||
si.PasswordHash, cinfo.PasswordHash,
|
||||
'Worksheet protection password hash mismatch'
|
||||
);
|
||||
|
||||
finally
|
||||
MyWorkbook.Free;
|
||||
DeleteFile(TempFile);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
{------------------------------------------------------------------------------}
|
||||
{ Tests for BIFF2 file format }
|
||||
@ -380,6 +450,11 @@ begin
|
||||
TestWriteRead_CellProtection(sfExcel2);
|
||||
end;
|
||||
|
||||
procedure TSpreadWriteReadProtectionTests.TestWriteRead_BIFF2_Passwords;
|
||||
begin
|
||||
TestWriteRead_Passwords(sfExcel2);
|
||||
end;
|
||||
|
||||
|
||||
{------------------------------------------------------------------------------}
|
||||
{ Tests for BIFF5 file format }
|
||||
@ -431,6 +506,10 @@ begin
|
||||
TestWriteRead_CellProtection(sfExcel5);
|
||||
end;
|
||||
|
||||
procedure TSpreadWriteReadProtectionTests.TestWriteRead_BIFF5_Passwords;
|
||||
begin
|
||||
TestWriteRead_Passwords(sfExcel5);
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------}
|
||||
{ Tests for BIFF8 file format }
|
||||
@ -482,6 +561,10 @@ begin
|
||||
TestWriteRead_CellProtection(sfExcel8);
|
||||
end;
|
||||
|
||||
procedure TSpreadWriteReadProtectionTests.TestWriteRead_BIFF8_Passwords;
|
||||
begin
|
||||
TestWriteRead_Passwords(sfExcel8);
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------}
|
||||
{ Tests for OOXML file format }
|
||||
@ -577,6 +660,11 @@ begin
|
||||
TestWriteRead_CellProtection(sfOOXML);
|
||||
end;
|
||||
|
||||
procedure TSpreadWriteReadProtectionTests.TestWriteRead_OOXML_Passwords;
|
||||
begin
|
||||
TestWriteRead_Passwords(sfOpenDocument);
|
||||
end;
|
||||
|
||||
|
||||
{------------------------------------------------------------------------------}
|
||||
{ Tests for OpenDocument file format }
|
||||
|
Reference in New Issue
Block a user