An HWP 5.0 file is a Microsoft compound file (the container of old Office files) holding streams. Apart from the file header, the streams are sequences of tagged records, usually compressed. This page follows Hancom’s published HWP 5.0 specification, revision 1.3 (8 November 2018), sections 2 to 4.1, with pyhwp, the open-source reader, where they differ; numbers are little-endian.
Data types
| Type | Bytes | Meaning (table 1) |
|---|---|---|
| BYTE, UINT8 | 1 | Unsigned, 0–255 |
| INT8 | 1 | Signed |
| WORD, UINT16 | 2 | Unsigned |
| INT16, HWPUNIT16 | 2 | Signed |
| DWORD, UINT32 (UINT) | 4 | Unsigned |
| INT32 | 4 | Signed |
| WCHAR | 2 | One character in Hangul’s internal code, based on Unicode (UTF-16LE) |
| HWPUNIT | 4 | Unsigned length in 1/7200 inch; a 2 × 1 inch picture is 14400 × 7200 |
| SHWPUNIT | 4 | Signed length in 1/7200 inch |
| COLORREF | 4 | A colour 0x00BBGGRR: red in the low byte |
| BYTE stream | – | A run of bytes holding another structure |
An array is written type array[count]. A string is a WORD count followed by that many WCHARs.
Streams
| Stream or storage | Contents | Compressed |
|---|---|---|
FileHeader | The file header, 256 bytes. | Never |
DocInfo | Records shared by the whole document: properties, fonts, character and paragraph shapes, styles, numbering, bullets, borders. | If flagged |
BodyText/Section0, Section1, … | One stream per section of the document, each a tree of paragraph records. | If flagged |
ViewText/Section0, … | For distribution documents (copy- and print-restricted): the sections, encrypted, in place of BodyText. | If flagged |
BinData/ | Embedded pictures and objects, in streams such as BIN0001.png, referred to by the HWPTAG_BIN_DATA records. | Depends on each record’s flag |
\005HwpSummaryInformation | Summary information (title, author and so on) in the standard OLE property set format; the name starts with byte 5. | No |
PrvText | Preview text, a Unicode string. | No |
PrvImage | Preview image, in BMP or GIF format. | No |
DocOptions/ | Linked document path, DRM licence and certificate data, digital signature, public key. | No |
Scripts/ | Scripts (JScript) and their version. | No |
XMLTemplate/ | XML template: schema name, schema and instance. | No |
DocHistory/ | Version history of the document (VersionLog0, … and HistoryLastDoc). | Yes, and encrypted |
Bibliography/ | Bibliography information as an XML file. | – |
The specification’s table 2 marks DocInfo, BodyText and
DocHistory as compressed and encryptable, and BinData as
compressed. Hangul uses zlib; compressed streams are raw Deflate (RFC 1951): no zlib
or gzip header, the data starts directly with Deflate blocks (as pyhwp reads them).
The contents of the other streams are on the
other streams page.
FileHeader
| Offset | Size | Field | Meaning |
|---|---|---|---|
0 | 32 | Signature | HWP Document File (17 bytes) followed by 15 zero bytes. |
32 | 4 | Version | A 32-bit number 0xMMnnPPrr: major, minor, build and revision. 5.0.3.0 is 0x05000300, stored 00 03 00 05. Some record layouts depend on it. |
36 | 4 | Flags | See below. |
40 | 4 | Licence flags | Bit 0 CCL or KOGL licence information; bit 1 copying restricted; bit 2 copying allowed under the same conditions (ignored when copying is restricted); bits 3–31 reserved. |
44 | 4 | EncryptVersion | 0 none; 1 Hangul 2.5 and older; 2 Hangul 3.0 Enhanced; 3 Hangul 3.0 Old; 4 Hangul 7.0 and later. |
48 | 1 | KOGL country | Country of the Korea Open Government Licence: 6 KOR, 15 US. |
49 | 207 | Reserved | – |
| Bit | Meaning when set |
|---|---|
| 0 | The streams are compressed. |
| 1 | The document is protected by a password (its streams are encrypted). |
| 2 | Distribution document: the text is in encrypted ViewText streams (see distribution documents). |
| 3 | Scripts are stored. |
| 4 | DRM-protected document. |
| 5 | XML template storage is present. |
| 6 | Document history is stored. |
| 7 | Digital signature information is present. |
| 8 | Encrypted with a public (accredited) certificate. |
| 9 | A spare copy of the digital signature is stored. |
| 10 | Certificate DRM document. |
| 11 | CCL (Creative Commons licence) document. |
| 12 | Optimised for mobile. |
| 13 | Personal information security document. |
| 14 | Change tracking document. |
| 15 | KOGL (Korea Open Government Licence) document. |
| 16 | Contains video controls. |
| 17 | Contains a table of contents field control. |
| 18–31 | Reserved. |
00000000 48 57 50 20 44 6F 63 75 6D 65 6E 74 20 46 69 6C HWP Document Fil
00000010 65 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 e...............
00000020 00 03 00 05 01 00 00 00 ........
Signature, version 5.0.3.0, flags 1: compressed, nothing else.
Records
Every stream except FileHeader, the previews, the summary and the
binary data is, once decompressed, a run of records. Each starts with a 32-bit
header:
| Bits | Field | Meaning |
|---|---|---|
| 0–9 | Tag ID | What the record is (0 to 1,023): see tags. |
| 10–19 | Level | Depth in the record tree: a record is a child of the nearest earlier record whose level is one lower. |
| 20–31 | Size | Length of the data that follows, 0 to 4,094. The value 4,095 (0xFFF) means a further 32-bit size follows the header. |
Tag ranges: 0x000–0x00F special uses, not ordinary
records; 0x010–0x1FF reserved for Hangul
(HWPTAG_BEGIN = 0x010); 0x200–0x3FF
free for other applications. Because the size is in the header, a reader can skip any
record it does not know, which is how older versions read newer files.
For example the header 42 00 60 01 (0x01600042) is tag
0x42 (a paragraph header), level 0, size 22.
DocInfo records
DocInfo starts with the document properties and the ID mappings record,
whose counts say how many of each following record there are, in the order of its
fields. Shapes and styles are referred to elsewhere by their position (from 0) in
these lists. Every DocInfo record is described field by field on the
DocInfo records page.