Changes

Jump to: navigation, search

ZIM file format

4,457 bytes added, 10:12, 16 July 2019
correction, see ZIM File Example
[[Image:Schema File Format.png|500px|right]]
The '''ZIM file format''' is based on the old and deprecated [[Zeno File Format]].See also a walk through an example at [[ZIM File Example]].
It starts with a header, which is described here:
A ZIM file starts with a header. This is offset 0.
Length in bytebytes, all types are littlendianlittle-endian.
All integers are unsigned integers (uint_16, uint_32, uint_64). {|class="sortable" style="border-width:1px; border-style:solid; border-color:#888888; background-color:#eeeeee; border-collapse:collapse; empty-cells:show" cellspacing="0" cellpadding="4" {{Prettytable}}! Field Name !! Type !!Offset!!Length!! Description |-| magicNumber || integer || 0 || 4 || Magic number to recognise the file format, must be 72173914 (0x44D495A)
|-
| magicNumber |majorVersion| integer || 0 || 4 |2| Magic number to recognise Major version of the ZIM file format, must be 72173914 (5 or 6)
|-
| version minorVersion || integer || 4 6 || 4 2 || ZIM=5, bytes 1-2: major, bytes 3-4: minor Minor version of the ZIM file format
|-
| uuid || integer || 8 || 16 || unique id of this zim file
| clusterCount || integer || 28 || 4 || total number of clusters
|-
| urlPtrPos || integer || 32 || 8 || position of the directory pointerlist orderes ordered by URL
|-
| titlePtrPos || integer || 40 || 8 || position of the directory pointerlist ordered by Title
| checksumPos || integer || 72 || 8 || pointer to the md5checksum of this file without the checksum itself. This points always 16 bytes before the end of the file.
|}
 
Major version is updated when an incompatible change is integrated in the format (a lib made for a version N will probably not be able to read a version N+1)
 
Minor version is updated when an compatible change is integrated (a lib made for a minor version n will be able to read a version n+1)
 
There are currently 2 major versions :
* The version 5
* The version 6 (the same that version 5 + potential extended cluster)
== MIME Type List (mimeListPos) ==
The MIME types in this list are zero terminated strings. An empty string marks the end of the MIME type list.
{|class="sortable" style="border-width:1px; border-style:solid; border-color:#888888; background-color:#eeeeee; border-collapse:collapse; empty-cells:show" cellspacing="0" cellpadding="4" {{Prettytable}}
! Field Name !! Type !!Offset!!Length!! Description
|-
Since directory entries have variable sizes this is needed for random access.
{|class="sortable" style="border-width:1px; border-style:solid; border-color:#888888; background-color:#eeeeee; border-collapse:collapse; empty-cells:show" cellspacing="0" cellpadding="4" {{Prettytable}}
! Field Name !! Type !!Offset!!Length!! Description
|-
To get the offset of an article from the title pointer list, you have to look it up in the URL pointer list.
{|class="sortable" style="border-width:1px; border-style:solid; border-color:#888888; background-color:#eeeeee; border-collapse:collapse; empty-cells:show" cellspacing="0" cellpadding="4" {{Prettytable}}
! Field Name !! Type !!Offset!!Length!! Description
|-
Directory entries hold the meta information about all articles, images and other objects in a ZIM file.
There are two many types of directory entries: article entries and redirect entries. If the first two bytes are 0xffff the directory entry is a redirect.
=== Article Entry ===
{|class="sortable" style="border-width:1px; border-style:solid; border-color:#888888; background-color:#eeeeee; border-collapse:collapse; empty-cells:show" cellspacing="0" cellpadding="4" {{Prettytable}}
! Field Name !! Type !!Offset!!Length!! Description
|-
=== Redirect Entry ===
{|class="sortable" style="border-width:1px; border-style:solid; border-color:#888888; background-color:#eeeeee; border-collapse:collapse; empty-cells:show" cellspacing="0" cellpadding="4" {{Prettytable}}
! Field Name !! Type !!Offset!!Length!! Description
|-
|-
| url || string || 12 ||zero terminated|| string with the URL as refered in the URL pointer list
|-
| title || string || n/a ||zero terminated|| string with an title as refered in the Title pointer list or empty; in case it is empty, the URL is used as title
|-
| parameter || data || ||see parameter len|| (not used) extra parameters
|}
 
=== Linktarget or deleted Entry ===
{| class="sortable" style="border-width:1px; border-style:solid; border-color:#888888; background-color:#eeeeee; border-collapse:collapse; empty-cells:show" cellspacing="0" cellpadding="4" {{Prettytable}}
! Field Name !! Type !!Offset!!Length!! Description
|-
| mimetype || integer || 0 || 2 || 0xfffe for linktarget, 0xfffd for deleted entry
|-
| parameter len || byte || 2 || 1 || (not used) length of extra paramters
|-
| namespace || char || 3 || 1 || defines to which namespace this directory entry belongs
|-
| revision || integer || 4 || 4 || (optional) identifies a revision of the contents of this directory entry, needed to identify updates or revisions in the original history
|-
| url || string || 16 ||zero terminated|| string with the URL as refered in the URL pointer list
|-
| title || string || n/a ||zero terminated|| string with an title as refered in the Title pointer list or empty; in case it is empty, the URL is used as title
The cluster pointer list is a list of 8 byte offsets which point to all data clusters in a ZIM file.
{|class="sortable" style="border-width:1px; border-style:solid; border-color:#888888; background-color:#eeeeee; border-collapse:collapse; empty-cells:show" cellspacing="0" cellpadding="4" {{Prettytable}}
! Field Name !! Type !!Offset!!Length!! Description
|-
The clusters contain the actual data of the directory entries. Clusters can be compressed or uncompressed. The purpose of the clusters are that data of more than one directory entry can be compressed inside one cluster, making the compression much more efficient. Typically clusters have a size of about 1 MB.
The first byte of the cluster identifies some information about the cluster. The first fourth low bits identifies if it the cluster is compressed (4) or not (0). The default is uncompressed indicated by a value of 0 or 1 (obsoleted, inherited by Zeno) while compressed clusters are indicated by a value of 4 which indicates [[LZMA2 compression ]] (or more precisely XZ, since there is a XZ header). There have been other compression algorithms used before (2: zlib, 3: bzip2) which have been removed. The zimlib uses [http://tukaani.org/xz/ xz-utils] as a C++ implementation of lzma2, for Java see [http://tukaani.org/xz/java.html XZ-Java]. The firth bit identifies if the cluster is extended or not :* By default (5th bit == 0) the cluster is not extended. It means that the offsets are stored in a 4 bytes length integer. Thus contents stored in the cluster cannot exceed 4Go.* If the cluster is extended (5th bit == 1), the offsets are stored in 8 bytes length integer. Thus contents stored in the cluster can exceed 4Go.A cluster can be extended only if the zim major version is 6. Else (major version == 5) cluster will always be not extended.
To find the data of a specific directory entry within a cluster the uncompressed cluster has a list of pointers to blobs within the uncompressed cluster after the first byte.
{|class="sortable" style="border-width:1px; border-style:solid; border-color:#888888; background-color:#eeeeee; border-collapse:collapse; empty-cells:show" cellspacing="0" cellpadding="4" {{Prettytable}}
! Field Name !! Type !!Offset!!Length!! Description
|-
| compression type cluster information || integer || 0 || 1 || Fourth low bits : 0: default (no compression), 1: none (inherited from Zeno), 4: LZMA2 compressed Firth bits : 0: normal (OFFSET_SIZE=4) 1: extended (OFFSET_SIZE=8)
|-
|colspan="5" | The following data bytes have to be uncompressed!
|-
| <1st Blob> || integer || 1 || 4 OFFSET_SIZE || offset to the <1st Blob>
|-
| <2nd Blob> || integer || 5 1+OFFSET_SIZE || 4 OFFSET_SIZE || offset to the <2nd Blob>
|-
| <nth Blob> || integer ||(n-1)*4OFFSET_SIZE+1|| 4 OFFSET_SIZE || offset to the <nth Blob>
|-
| ... || integer || ... || 4 OFFSET_SIZE || ...
|-
| <last blob / end> || integer || n/a || 4 OFFSET_SIZE || offset to the end of the cluster
|-
| <1st Blob> || data || n/a || n/a || data of the <1st Blob>
|}
The offset addresses uncompressed data. The last pointer points to the end of the data area. So there is always one more offset than blobs. Since the first offset points to the start of the first data, the number of offsets can be determined by dividing this offset by 4OFFSET_SIZE. The size of one blob is calculated by the difference of two consecutive offsets.
== Namespaces ==
They can be distinguished by prepending the article namespace before the article name in the URL path, eg. ''http://localhost/A/Articlename''.
{|class="sortable" style="border-width:1px; border-style:solid; border-color:#888888; background-color:#eeeeee; border-collapse:collapse; empty-cells:show" cellspacing="0" cellpadding="4" {{Prettytable}}
! Namespace !! Description
|-
ZIM contents are addressed using URLs fitting the following pattern: <namespace>/<article_url>. The references in articles HTML code (''<a href=""></a>'', ''<img src="">'', etc.) are URL-encoded following the [http://www.ietf.org/rfc/rfc1738.txt RFC 1738] rules.
Absolute URLs, ie. with a leading slash (''/'') are forbidden, because this avoid including the ZIM contents in any HTTP sub-hierachy. ZIM contents URLs must consequently be relative. Be careful, <article_url> may itself contain slashes (for example "BMW_501/502").
The URLs in the UrlPointerlist are not encoded. Some readers process the requests that already do the decoding internally whereas most readers will handle the URLs directly. In this case you have to do the decoding before you pass the parameter to zimlib, but zimlib already provides a method to do so.
<pre>
<a href="../A/foo#headline1">jump to article foo, headline 1</a>
</pre>
The browser handles these local anchors by itself. It will determine if another article has to be loaded (local anchor inside another article than the currently shown) and will send a request only with the article URL without the local anchor - in our example "../A/foo". After the article has been loaded the browser will then search for the local anchor tag and jump to the right location.
If you use a common rendering engine or HTML widget you don't have to care for this cases, you can just use the requests as they are submitted by the engine / widget.
Old Zeno files used the QUnicode library instead. By switching to UTF-8 the new format is more standard-adherent and easier to understand.
 
== Split ZIM files ==
ZIM files can be split in multiple chunks. This is necessary to be able to store big (over 4GB for example) ZIM files to limited file systems (like FAT32). That said, the chunks can be of any size, but the naming is really important. The ZIM file chunks should be named like following (the file name extensions matter): ''foobar.zimaa, foobar.zimab, foobar.zimac''...
== See also ==
* [[Zeno file format]] (deprecated)
* [[ZIM File Format/4]] (deprecated)
* [[ZIM File Example]]
14
edits

Navigation menu