<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision$ -->
<chapter xml:id="phar.fileformat" xmlns="http://docbook.org/ns/docbook">
 <title>What makes a phar a phar and not a tar or a zip?</title>
 <section xml:id="phar.fileformat.ingredients" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
  <title>Ingredients of all Phar archives, independent of file format</title>
  <para>
   All Phar archives contain three to four sections:
   <orderedlist>
    <listitem>
     <para>a stub</para>
    </listitem>
    <listitem>
     <para>a manifest describing the contents</para>
    </listitem>
    <listitem>
     <para>the file contents</para>
    </listitem>
    <listitem>
     <para>[optional] a signature for verifying Phar integrity (phar file format only)</para>
    </listitem>
   </orderedlist>
  </para>
 </section>
<section xml:id="phar.fileformat.stub" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
 <title>Phar file stub</title>
 <para>
  A Phar's stub is a simple PHP file.  The smallest possible stub follows:
 </para>
 <para>
  <programlisting role="php">
   <![CDATA[<?php __HALT_COMPILER();]]>
  </programlisting>
 </para>
 <para>
  A stub must contain as a minimum, the <literal>__HALT_COMPILER();</literal> token
  at its conclusion.  Typically, a stub will contain loader functionality
  like so:
 </para>
 <para>
  <programlisting role="php">
   <![CDATA[
<?php
Phar::mapPhar();
include 'phar://myphar.phar/index.php';
__HALT_COMPILER();
   ]]>
  </programlisting>
 </para>
 <para>
  There are no restrictions on the contents of a Phar stub, except for the requirement
  that it conclude with <literal>__HALT_COMPILER();</literal>.  The closing PHP tag
  <literal><![CDATA[?>]]></literal> may be included or omitted, but there can be
  no more than 1 space between the <literal>;</literal> and the close tag
  <literal><![CDATA[?>]]></literal> or the phar extension will be unable
  to process the Phar archive's manifest.
 </para>
 <para>
  In a tar or zip-based phar archive, the stub is stored in the
  <literal>.phar/stub.php</literal> file.  The default stub for phar-based
  Phar archives contains approximately 7k of code to extract the contents
  of the phar and execute them.  See <function>Phar::createDefaultStub</function>
  for more detail.
 </para>
 <para>
  The phar alias is stored in a tar or zip-based phar archive in the
  <literal>.phar/alias.txt</literal> file as plain text.
 </para>
 </section>
 <section xml:id="phar.fileformat.comparison" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
  <title>Head-to-head comparison of Phar, Tar and Zip</title>
  <para>
   What are the good and the bad things about the three supported file formats in
   the phar extension?  This table attempts to address that question.
  <table>
   <title>Feature matrix: Phar vs. Tar vs. Zip</title>
   <tgroup cols="4">
    <thead>
     <row>
      <entry>Feature</entry>
      <entry>Phar</entry>
      <entry>Tar</entry>
      <entry>Zip</entry>
     </row>
    </thead>
    <tbody>
     <row>
      <entry>Standard File Format</entry>
      <entry>No</entry>
      <entry>Yes</entry>
      <entry>Yes</entry>
     </row>
     <row>
      <entry>Can be executed without the Phar Extension
       <link linkend="phar.fileformat.phartip">[1]</link>
      </entry>
      <entry>Yes</entry>
      <entry>No</entry>
      <entry>No</entry>
     </row>
     <row>
      <entry>Per-file compression</entry>
      <entry>Yes</entry>
      <entry>No</entry>
      <entry>Yes</entry>
     </row>
     <row>
      <entry>Whole-archive compression</entry>
      <entry>Yes</entry>
      <entry>Yes</entry>
      <entry>No</entry>
     </row>
     <row>
      <entry>Whole-archive signature validation</entry>
      <entry>Yes</entry>
      <entry>Yes</entry>
      <entry>Yes</entry>
     </row>
     <row>
      <entry>Web-specific application support</entry>
      <entry>Yes</entry>
      <entry>Yes</entry>
      <entry>Yes</entry>
     </row>
     <row>
      <entry>Per-file Meta-data</entry>
      <entry>Yes</entry>
      <entry>Yes</entry>
      <entry>Yes</entry>
     </row>
     <row>
      <entry>Whole-Archive Meta-data</entry>
      <entry>Yes</entry>
      <entry>Yes</entry>
      <entry>Yes</entry>
     </row>
     <row>
      <entry>Archive creation/modification
       <link linkend="phar.fileformat.phartip2">[2]</link>
      </entry>
      <entry>Yes</entry>
      <entry>Yes</entry>
      <entry>Yes</entry>
     </row>
     <row>
      <entry>Full support for all stream wrapper functions</entry>
      <entry>Yes</entry>
      <entry>Yes</entry>
      <entry>Yes</entry>
     </row>
     <row>
      <entry>Can be created/modified even if phar.readonly=1
       <link linkend="phar.fileformat.phartip3">[3]</link>
      </entry>
      <entry>No</entry>
      <entry>Yes</entry>
      <entry>Yes</entry>
     </row>
    </tbody>
   </tgroup>
  </table>
  </para>
  <para xml:id="phar.fileformat.phartip">
   <tip>
    <para>
    [1] PHP can only directly access the contents of a Phar archive
    without the Phar extension if it is using a <literal>stub</literal>
    that extracts the contents of the phar archive.  The stub
    created by <function>Phar::createDefaultStub</function> extracts
    the phar archive and runs its contents from a temporary directory
    if no phar extension is found.
    </para>
   </tip>
  </para>
  <para xml:id="phar.fileformat.phartip2">
   <tip>
    <para>
    [2] All write access requires <literal>phar.readonly</literal> to
    be disabled in php.ini or on the command-line directly.
    </para>
   </tip>
  </para>
  <para xml:id="phar.fileformat.phartip3">
   <tip>
    <para>
    [3] Only tar and zip archives without <literal>.phar</literal> in their
    filename and without an executable stub <literal>.phar/stub.php</literal>
    can be created if phar.readonly=1.
    </para>
   </tip>
  </para>
 </section>
 <section xml:id="phar.fileformat.tar" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
  <title>Tar-based phars</title>
  <para>
   Archives based on the tar file format follow the more modern USTAR
   file format.  The design of the tar file header makes them more efficient
   to access than the zip file format, and almost as efficient as the phar
   file format.  File names are limited to 255 bytes, including
   full path within the phar archive.  There is no limit on the number of files
   within a tar-based phar archive.  These archives can fully compressed in
   gzip or bzip2 format and still be executed by the Phar extension.
  </para>
  <para>
   There is limited support for reading tarballs in pax interchange format,
   but all recognized pax headers (currently, typeflag <literal>x</literal> and
   <literal>g</literal>) are silently ignored.
   There is also limited support for GNU Tar Archives;
   currently, <literal>././@LongLink</literal> headers are resolved.
  </para>
  <para>
   To compress an entire archive, use <function>Phar::compress</function>.
   To decompress an entire archive, use <function>Phar::decompress</function>.
  </para>
 </section>
 <section xml:id="phar.fileformat.zip" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
  <title>Zip-based phars</title>
  <para>
   Archives based on the zip file format support several features built into
   the zip file format.  Per-file and whole-archive metadata is stored in
   the zip file comment and zip archive comment as a serialized string.  Pre-existing
   zip comments will be successfully read as a string.  Per-file compression
   read/write is supported with zlib DEFLATE compression, and read access is supported
   with bzip2 compression.  There is no limit on the number of files
   within a zip-based phar archive.  Empty directories are stored in the zip archive
   as files with a trailing slash like <literal>my/directory/</literal>
  </para>
 </section>
 <section xml:id="phar.fileformat.phar" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
 <title>Phar File Format</title>
 <para>
  The phar file format is literally laid out as stub/manifest/contents/signature, and
  stores the crucial information of what is included in the phar archive in its
  <literal>manifest</literal>.
 </para>
 <para>
  The Phar manifest is a highly optimized format that allows per-file
  specification of file compression, file permissions, and even user-defined
  meta-data such as file user or group.  All values greater than 1 byte are stored
  in little-endian byte order, with the exception of the API version, which
  for historical reasons is stored as 3 nibbles in big-endian order.
 </para>
 <para>
  All unused flags are reserved for future use, and must not be used
  to store custom information.  Use the per-file meta-data facility
  to store customized information about particular files.
 </para>
 <para>
  The basic file format of a Phar archive manifest is as follows:
 </para>
 <para>
 <table>
  <title>Global Phar manifest format</title>
  <tgroup cols="2">
   <thead>
    <row>
     <entry>Size in bytes</entry>
     <entry>Description</entry>
    </row>
   </thead>
   <tbody>
    <row>
     <entry>4 bytes</entry>
     <entry>Length of manifest in bytes (1 MB limit)</entry>
    </row>
    <row>
     <entry>4 bytes</entry>
     <entry>Number of files in the Phar</entry>
    </row>
    <row>
     <entry>2 bytes</entry>
     <entry>API version of the Phar manifest (currently 1.0.0)</entry>
    </row>
    <row>
     <entry>4 bytes</entry>
     <entry>Global Phar bitmapped flags</entry>
    </row>
    <row>
     <entry>4 bytes</entry>
     <entry>Length of Phar alias</entry>
    </row>
    <row>
     <entry>??</entry>
     <entry>Phar alias (length based on previous)</entry>
    </row>
    <row>
     <entry>4 bytes</entry>
     <entry>Length of Phar metadata (<literal>0</literal> for none)</entry>
    </row>
    <row>
     <entry>??</entry>
     <entry>Serialized Phar Meta-data, stored in <function>serialize</function> format</entry>
    </row>
    <row>
     <entry>at least 24 * number of entries bytes</entry>
     <entry>entries for each file</entry>
    </row>
   </tbody>
  </tgroup>
 </table>
 </para>
</section>
<section xml:id="phar.fileformat.flags" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
 <title>Global Phar bitmapped flags</title>
 <para>
  Here are the bitmapped flags currently recognized by the Phar extension
  for the global Phar flat bitmap:
 </para>
 <para>
  <table>
   <title>Bitmap values recognized</title>
   <tgroup cols="2">
   <thead>
    <row>
     <entry>Value</entry>
     <entry>Description</entry>
    </row>
    </thead>
    <tbody>
    <row>
     <entry><literal>0x00010000</literal></entry>
      <entry>If set, this Phar contains a verification signature</entry>
     </row>
     <row>
      <entry><literal>0x00001000</literal></entry>
      <entry>
       If set, this Phar contains at least 1 file that
       is compressed with zlib DEFLATE compression
      </entry>
     </row>
     <row>
      <entry><literal>0x00002000</literal></entry>
      <entry>
       If set, this Phar contains at least 1 file that
       is compressed with bzip2 compression
      </entry>
     </row>
    </tbody>
   </tgroup>
  </table>
 </para>
</section>
<section xml:id="phar.fileformat.manifestfile" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
 <title>Phar manifest file entry definition</title>
 <para>
  Each file in the manifest contains the following information:
 </para>
 <para>
  <table>
   <title>Phar Manifest file entry</title>
   <tgroup cols="2">
    <thead>
     <row>
      <entry>Size in bytes</entry>
      <entry>Description</entry>
     </row>
    </thead>
    <tbody>
     <row>
      <entry>4 bytes</entry>
      <entry>Filename length in bytes</entry>
     </row>
     <row>
      <entry>??</entry>
      <entry>Filename (length specified in previous)</entry>
     </row>
     <row>
      <entry>4 bytes</entry>
      <entry>Un-compressed file size in bytes</entry>
     </row>
     <row>
      <entry>4 bytes</entry>
      <entry>Unix timestamp of file</entry>
     </row>
     <row>
      <entry>4 bytes</entry>
      <entry>Compressed file size in bytes</entry>
     </row>
     <row>
      <entry>4 bytes</entry>
      <entry>CRC32 checksum of un-compressed file contents</entry>
     </row>
     <row>
      <entry>4 bytes</entry>
      <entry>Bit-mapped File-specific flags</entry>
     </row>
     <row>
      <entry>4 bytes</entry>
      <entry>Serialized File Meta-data length (<literal>0</literal> for none)</entry>
     </row>
     <row>
      <entry>??</entry>
      <entry>Serialized File Meta-data, stored in <function>serialize</function> format</entry>
     </row>
    </tbody>
   </tgroup>
  </table>
 </para>
 <para>
  Note that as of API version 1.1.1, empty directories are stored as filenames
  with a trailing slash like <literal>my/directory/</literal>
 </para>
 <para>
  The File-specific bitmap values recognized are:
 </para>
 <para>
  <table>
   <title>Bitmap values recognized</title>
   <tgroup cols="2">
    <thead>
     <row>
      <entry>Value</entry>
      <entry>Description</entry>
     </row>
    </thead>
    <tbody>
     <row>
      <entry><literal>0x000001FF</literal></entry>
      <entry>
       These bits are reserved for defining specific file permissions
       of a file.  Permissions are used for <function>fstat</function>
       and can be used to recreate desired permissions upon extraction.
      </entry>
     </row>
     <row>
      <entry><literal>0x00001000</literal></entry>
      <entry>
       If set, this file is compressed with zlib DEFLATE compression
      </entry>
     </row>
     <row>
      <entry><literal>0x00002000</literal></entry>
      <entry>
       If set, this file is compressed with bzip2 compression
      </entry>
     </row>
    </tbody>
   </tgroup>
  </table>
 </para>
</section>
<section xml:id="phar.fileformat.signature" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
 <title>Phar Signature format</title>
 <para>
  Phars containing a signature always have the signature appended to the
  end of the Phar archive after the loader, manifest, and file contents.
  The signature formats supported at this time are MD5, SHA1, SHA256, SHA512,
  and OPENSSL.
 </para>
 <para>
  <table>
   <title>Signature format</title>
   <tgroup cols="2">
    <thead>
     <row>
      <entry>Length in bytes</entry>
      <entry>Description</entry>
     </row>
    </thead>
    <tbody>
     <row>
      <entry>varying</entry>
      <entry>
       The actual signature, 20 bytes for an SHA1 signature,
       16 bytes for an MD5 signature, 32 bytes for an SHA256 signature,
       and 64 bytes for an SHA512 signature. The length of an OPENSSL
       signature depends on the size of the private key.
      </entry>
     </row>
     <row>
      <entry>4 bytes</entry>
      <entry>
       Signature flags.  <literal>0x0001</literal> is used to
       define an MD5 signature, <literal>0x0002</literal> is used
       to define an SHA1 signature, <literal>0x0003</literal> is used
       to define an SHA256 signature, and <literal>0x0004</literal> is
       used to define an SHA512 signature.  The SHA256 and SHA512 signature
       support is available as of API version 1.1.0.
       <literal>0x0010</literal> is used to define an OPENSSL signature, what
       is available as of API version 1.1.1, if OpenSSL is available.
      </entry>
     </row>
     <row>
      <entry>4 bytes</entry>
      <entry>
       Magic <literal>GBMB</literal> used to define the presence of a signature.
      </entry>
     </row>
    </tbody>
   </tgroup>
  </table>
 </para>
</section>
</chapter>

<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
vim600: syn=xml fen fdm=syntax fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->
