WordPerfect files from version 5.0 for DOS onwards, and from WordPerfect 2 for the
Macintosh onwards, start with a 16-byte header whose bytes 1 to 3 are
WPC. It says where the document text starts, what kind of file it is and
which version wrote it. Corel’s own format documentation is not freely published; this
page follows libwpd, the open-source WordPerfect reader used by LibreOffice, and says
where something is not known.
The WPC header
Numbers in DOS and Windows files are little-endian. The table follows those files; the byte order of the Macintosh files is not described here.
| Offset | Size | Field | Meaning |
|---|---|---|---|
0 | 1 | – | 0xFF. |
1 | 3 | Signature | WPC (57 50 43). A reader checks these three bytes. |
4 | 4 | Document pointer | Offset of the start of the document area (the text and codes), after any prefix. |
8 | 1 | Product type | The program family that wrote the file: 1 for WordPerfect. |
9 | 1 | File type | 0x0A WordPerfect document; 0x2C WordPerfect for the Macintosh document. Other values are other WordPerfect Corporation files (templates, macros, dictionaries and so on), which libwpd does not read. |
10 | 1 | Major version | See versions. |
11 | 1 | Minor version | See versions. |
12 | 2 | Encryption | 0 when the file is not encrypted; otherwise a checksum of the password (see encryption). In 5.x files this field is stored high byte first. |
14 | 2 | Depends on version | 5.x: reserved. 6.x and later: offset of the index header (values below 16 mean 16). |
16 | … | Prefix | Version-specific: the 5.x packet index, the 6.x index header, or for Macintosh 2.x and 3.x an embedded resource fork. In 6.x files libwpd reads nothing at offsets 16–19 (the document size is at 20 in 6.1 and later), and no public source says what those four bytes hold. |
In 6.1 and later files the four bytes at offset 20 hold the size of the document (the offset of its end); 6.0 files do not have this field.
Versions
| File type | Major | Minor | Format |
|---|---|---|---|
0x0A | 0 | 0, 1 | WordPerfect 5.0 and 5.1 for DOS, 5.1 and 5.2 for Windows: the 5.x format. |
0x0A | 2 | 0 | WordPerfect 6.0: the 6.x format, without the document size field. |
0x0A | 2 | 1 and later | WordPerfect 6.1 and every later version up to today’s WordPerfect Office: the 6.x format with the size field. New versions add codes and packets but keep the layout, which is why .wpd files from version 6 onwards open in each other. |
0x2C | 2 | – | WordPerfect 2.x for the Macintosh. |
0x2C | 3 | – | WordPerfect 3.0 to 3.5 for the Macintosh. |
0x2C | 4 | – | WordPerfect 3.5e for the Macintosh. |
The minor version of 5.x files (0 for 5.0, 1 for 5.1) mainly changes which packets the prefix has: 5.0 lists the fonts used in packet type 2, 5.1 in packet type 15. The exact minor numbers written by every 6.x-format release (6.1, 7, 8, 9, X3 and later) are not given by libwpd, which treats them all alike.
Files without a header
WordPerfect 4.2 and earlier for DOS, and WordPerfect 1.x for the Macintosh, have no
WPC header: the file is the document stream from its first byte. Programs recognise
them by checking that the bytes are text and well-formed function codes. A 4.2 file
that starts with FE FF 61 61 is password-protected: the next two bytes
are the password checksum, and the encrypted text starts at offset 6. (A 1.x Macintosh
file is encrypted from offset 6 too.)
Encryption
Older WordPerfect versions protect a document by scrambling its bytes with the password; this is not secure and is easily reversed. libwpd handles it as follows for 5.x, 4.2, Macintosh 1.x and Macintosh 2.x/3.x files:
- The password is turned to upper case (letters a to z only).
- The checksum is built over the password’s characters: start at 0; for each character, rotate the 16-bit value right by one bit and XOR it with the character shifted left eight bits. A file is protected when its stored checksum is not 0, and the password is right when the checksums match.
- Bytes before the start offset are not encrypted: 16 for 5.x files (the whole header stays readable), 6 for 4.2 and Macintosh 1.x, and the document pointer for Macintosh 2.x and 3.x.
- The byte at position
iafter the start is XORed with the password characteri mod lengthand with the mask(length + 1 + i) mod 256.
WordPerfect 6.x and later encrypt differently. When the encryption field of a 6.x file is not 0 the file is encrypted; libwpd does not decrypt it and reports any encrypted file with major version 2 as using an unsupported encryption (a check that also catches Macintosh 2.x files, which its parser could otherwise unscramble). No description of WordPerfect’s encryption, old or new, was ever made available by WordPerfect or its later owners (WordPerfect for DOS Updated), so the 6.x method is unknown.
Example
The start of a WordPerfect 6.1-format document whose text begins at offset 0x05D4,
built from the fields above (not taken from a particular file; xx marks
bytes whose meaning is not public):
00000000 FF 57 50 43 D4 05 00 00 01 0A 02 01 00 00 00 02 .WPC............
00000010 xx xx xx xx 7A 1E 00 00 ....z...
| Bytes | Field | Value |
|---|---|---|
FF 57 50 43 | Signature | .WPC |
D4 05 00 00 | Document pointer | 0x05D4 = 1,492 |
01 | Product type | WordPerfect |
0A | File type | Document |
02 01 | Version | Major 2, minor 1: the 6.1 layout |
00 00 | Encryption | Not encrypted |
00 02 | Index header offset | 0x0200 = 512 |
xx xx xx xx | (Bytes 16–19) | Not read by libwpd; not publicly documented |
7A 1E 00 00 | Document size | 0x1E7A = 7,802 bytes |