feat: Add Sheet Protection for XLS (BIFF8) #3202
No reviewers
Labels
No Label
DBF
Dates
Defined Names
Features
Formula
HTML
Images
Infrastructure
Integration
International
ODS
Operations
Performance
PivotTables
Pro
Protection
Read Bug
SSF
SYLK
Style
Write Bug
good first issue
No Milestone
No Assignees
2 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: sheetjs/sheetjs#3202
Loading…
Reference in New Issue
Block a user
No description provided.
Delete Branch "lpicchi/sheetjs:biff8-protection"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Fixes #3201
There are a few issues but good first start :)
At a high level, it is better to reference the primary source
MS-XLS
since the provenance of OpenOffice's documentation is murky. In case you are wondering why provenance is important,CONTRIBUTING.md
is a good starting point.The record you are trying to write in
write_ws_biff8_protection
is[MS-XLS] 2.4.112 FeatHdr
BIFF5 uses a different record (0x12) so the write should be guarded with a
b8
test (look at howwrite_ws_cols_biff8
is guarded)Try to make the write operations aligned with the spec. For example, since the record starts with a future record header (12 bytes), write the
FrtHeader
first:After that is SharedFeatureType (2.5.237):
After that is one byte that much be 1:
After that is
cbHdrData
which should be0xFFFFFFFF
:Finally we have the
rgbHdrData
bit flag of type EnhancedProtection 2.5.104:a1a14fe069
to1cc81cd477
Hi @sheetjs thank you for your feedback. I made a quick reasearch (two days) into the documentation I could find in the web and how sheetjs handled CFB files creation to address an urgent requirement we had in a project (I had no previous knowledge on CFB files or BIFF8 format 😅). After implementing the solution at work I have the intention to contribute my findings to this project (I've been using it for a long time to handle Excel files an had no clue about what was happening under the hood 🙃). Given the urgency of my situation I ended up in the OpenOffice's documentation that helped me to solve the issue. Thank you for pointing me in the direction of future headers docs, now I understand each byte been written by the code.
Updated the branch with the fixes you mentioned. I didn't realize the function
write_ws_biff8
was being used to write biff5 files too, that's the reason I didn't use theb8
test, added it.Thanks for following up! In the future, please raise an issue first and we can give some pointers.
Are the generated files valid? We'll have to take a closer look and test against older versions of Excel, but a cursory glance at the BNF suggests some of the records are in the wrong place. Look for the
WORKSHEETCONTENT
production in2.1.7.20.5 Worksheet Substream
. The relevant parts and line numbers against the current HEAD version are listed below:(The
PAGESETUP
,PROTECTION
, andCELLTABLE
productions are defined in2.1.7.20.6 Common Productions
)Based on the production rules, it would seem that the
Protect
andPassword
records must be written just before the column metadata and theFeatHdr
record must be written in theFEAT
block. It's probably better to put the record in thewrite_FEAT
function since it is only invoked when exporting to BIFF8. The spec does not say anything about relative order of features, but it makes sense to add the newFeatHdr
record at the start of the function (given that the existing shared feature has a larger SharedFeatureType value).Some more background about the BIFF formats:
BIFF2/BIFF3/BIFF4 sheets are raw byte streams.
BIFF5/BIFF8 use the "OLE container format" (the code refers to it as CFB -- container file blobs -- to align with the
MS-CFB
terminology). The Worksheet substreams are structurally similar to the BIFF2/3/4 raw byte streams.The XLS writer has a single entry point (
write_biff_buf
https://git.sheetjs.com/sheetjs/sheetjs/src/branch/master/bits/78_writebiff.js#L695). BIFF2/3/4 writers share a common code path.1cc81cd477
to9c406b1dec
After reading
2.1.7.20.5 Worksheet Substream
and your clarification aboutFEAT
block I think now the Records are written in the correct places9c406b1dec
to58fe461d34