view pws3_file_create.3.xml @ 11:96a507a110c8

Add support for format 0x030E
author Guido Berhoerster <guido+libpws@berhoerster.name>
date Fri, 02 Aug 2019 14:47:43 +0200
parents b3fc9f7e2b43
children
line wrap: on
line source

<?xml version="1.0"?>
<!--

Copyright (C) 2015 Guido Berhoerster <guido+libpws@berhoerster.name>

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

-->
<refentry xmlns="http://docbook.org/ns/docbook"
  xmlns:xlink="http://www.w3.org/1999/xlink" xml:lang="en">
  <info>
    <author>
      <personname>
        <firstname>Guido</firstname>
        <surname>Berhoerster</surname>
      </personname>
      <email>guido+libpws@berhoerster.name</email>
      <personblurb/>
    </author>
    <date>21 March, 2015</date>
  </info>
  <refmeta>
    <refentrytitle>pws3_file_create</refentrytitle>
    <manvolnum>3</manvolnum>
    <refmiscinfo class="source"/>
    <refmiscinfo class="version"/>
    <refmiscinfo class="manual">Library Functions</refmiscinfo>
  </refmeta>
  <refnamediv>
    <refname>pws3_file_create</refname>
    <refname>pws3_file_destroy</refname>
    <refname>pws3_file_get_error_code</refname>
    <refname>pws3_file_get_error_message</refname>
    <refname>pws3_file_read_mem</refname>
    <refname>pws3_file_read_stream</refname>
    <refname>pws3_file_write_mem</refname>
    <refname>pws3_file_write_stream</refname>
    <refname>pws3_file_set_header_field</refname>
    <refname>pws3_file_get_header_field</refname>
    <refname>pws3_file_remove_header_field</refname>
    <refname>pws3_file_insert_empty_group</refname>
    <refname>pws3_file_get_empty_group</refname>
    <refname>pws3_file_remove_empty_group</refname>
    <refname>pws3_file_first_empty_group</refname>
    <refname>pws3_file_last_empty_group</refname>
    <refname>pws3_file_next_empty_group</refname>
    <refname>pws3_file_prev_empty_group</refname>
    <refname>pws3_file_insert_record</refname>
    <refname>pws3_file_get_record</refname>
    <refname>pws3_file_remove_record</refname>
    <refname>pws3_file_first_record</refname>
    <refname>pws3_file_last_record</refname>
    <refname>pws3_file_next_record</refname>
    <refname>pws3_file_prev_record</refname>
    <refname>pws3_field_create</refname>
    <refname>pws3_field_destroy</refname>
    <refname>pws3_field_is_header</refname>
    <refname>pws3_field_get_type</refname>
    <refname>pws3_field_get_data_type</refname>
    <refname>pws3_field_set_uuid</refname>
    <refname>pws3_field_set_text</refname>
    <refname>pws3_field_set_time</refname>
    <refname>pws3_field_set_uint8</refname>
    <refname>pws3_field_set_uint16</refname>
    <refname>pws3_field_set_uint32</refname>
    <refname>pws3_field_set_bytes</refname>
    <refname>pws3_field_get_uuid</refname>
    <refname>pws3_field_get_text</refname>
    <refname>pws3_field_get_time</refname>
    <refname>pws3_field_get_uint8</refname>
    <refname>pws3_field_get_uint16</refname>
    <refname>pws3_field_get_uint32</refname>
    <refname>pws3_field_get_bytes</refname>
    <refname>pws3_record_create</refname>
    <refname>pws3_record_destroy</refname>
    <refname>pws3_record_set_field</refname>
    <refname>pws3_record_get_field</refname>
    <refname>pws3_record_remove_field</refname>
    <refpurpose>create and manipulate Password Safe File Version 3
    files</refpurpose>
  </refnamediv>
  <refsynopsisdiv>
    <cmdsynopsis>
      <command>cc</command>
      <arg choice="opt" rep="repeat">
        <option>flag</option>
      </arg>
      <arg choice="plain" rep="repeat">
        <option>file</option>
      </arg>
      <arg choice="plain">
        <option>-lpws</option>
      </arg>
      <arg choice="plain">
        <option>-lnettle</option>
      </arg>
      <arg choice="opt" rep="repeat">
        <option>library</option>
      </arg>
    </cmdsynopsis>
    <funcsynopsis>
      <funcsynopsisinfo>
#include &lt;pws.h&gt;
</funcsynopsisinfo>
      <funcprototype>
        <funcdef>struct pws3_file
        *<function>pws3_file_create</function></funcdef>
        <void/>
      </funcprototype>
      <funcprototype>
        <funcdef>void <function>pws3_file_destroy</function></funcdef>
        <paramdef>struct pws3_file
        *<parameter><replaceable>pws_file</replaceable></parameter></paramdef>
      </funcprototype>
      <funcprototype>
        <funcdef>enum pws_error_code
        <function>pws3_file_get_error_code</function></funcdef>
        <paramdef>struct pws3_file
        *<parameter><replaceable>pws_file</replaceable></parameter></paramdef>
      </funcprototype>
      <funcprototype>
        <funcdef>const char *
        <function>pws3_file_get_error_message</function></funcdef>
        <paramdef>struct pws3_file
        *<parameter><replaceable>pws_file</replaceable></parameter></paramdef>
      </funcprototype>
      <funcprototype>
        <funcdef>int <function>pws3_file_read_mem</function></funcdef>
        <paramdef>struct pws3_file
        *<parameter><replaceable>pws_file</replaceable></parameter></paramdef>
        <paramdef>const char
        *<parameter><replaceable>password</replaceable></parameter></paramdef>
        <paramdef>unsigned char
        *<parameter><replaceable>s</replaceable></parameter></paramdef>
        <paramdef>size_t
        <parameter><replaceable>n</replaceable></parameter></paramdef>
      </funcprototype>
      <funcprototype>
        <funcdef>int <function>pws3_file_read_stream</function></funcdef>
        <paramdef>struct pws3_file
        *<parameter><replaceable>pws_file</replaceable></parameter></paramdef>
        <paramdef>const char
        *<parameter><replaceable>password</replaceable></parameter></paramdef>
        <paramdef>FILE
        *<parameter><replaceable>fp</replaceable></parameter></paramdef>
      </funcprototype>
      <funcprototype>
        <funcdef>int <function>pws3_file_write_mem</function></funcdef>
        <paramdef>struct pws3_file
        *<parameter><replaceable>pws_file</replaceable></parameter></paramdef>
        <paramdef>const char
        *<parameter><replaceable>password</replaceable></parameter></paramdef>
        <paramdef>uint32_t
        <parameter><replaceable>n_iter</replaceable></parameter></paramdef>
        <paramdef>unsigned char
        **<parameter><replaceable>memp</replaceable></parameter></paramdef>
        <paramdef>size_t
        *<parameter><replaceable>mem_sizep</replaceable></parameter></paramdef>
      </funcprototype>
      <funcprototype>
        <funcdef>int <function>pws3_file_write_stream</function></funcdef>
        <paramdef>struct pws3_file
        *<parameter><replaceable>pws_file</replaceable></parameter></paramdef>
        <paramdef>const char
        *<parameter><replaceable>password</replaceable></parameter></paramdef>
        <paramdef>uint32_t
        <parameter><replaceable>n_iter</replaceable></parameter></paramdef>
      </funcprototype>
      <funcprototype>
        <funcdef>void <function>pws3_file_set_header_field</function></funcdef>
        <paramdef>struct pws3_file
        *<parameter><replaceable>pws_file</replaceable></parameter></paramdef>
        <paramdef>struct pws3_field
        *<parameter><replaceable>field</replaceable></parameter></paramdef>
      </funcprototype>
      <funcprototype>
        <funcdef>struct pws3_field *
        <function>pws3_file_get_header_field</function></funcdef>
        <paramdef>struct pws3_file
        *<parameter><replaceable>pws_file</replaceable></parameter></paramdef>
        <paramdef>uint8_t
        <parameter><replaceable>field_type</replaceable></parameter></paramdef>
      </funcprototype>
      <funcprototype>
        <funcdef>struct pws3_field *
        <function>pws3_file_remove_header_field</function></funcdef>
        <paramdef>struct pws3_file
        *<parameter><replaceable>pws_file</replaceable></parameter></paramdef>
        <paramdef>uint8_t
        <parameter><replaceable>field_type</replaceable></parameter></paramdef>
      </funcprototype>
      <funcprototype>
        <funcdef>void
        <function>pws3_file_insert_empty_group</function></funcdef>
        <paramdef>struct pws3_file
        *<parameter><replaceable>pws_file</replaceable></parameter></paramdef>
        <paramdef>struct pws3_field
        *<parameter><replaceable>field</replaceable></parameter></paramdef>
      </funcprototype>
      <funcprototype>
        <funcdef>struct pws3_field *
        <function>pws3_file_get_empty_group</function></funcdef>
        <paramdef>struct pws3_file
        *<parameter><replaceable>pws_file</replaceable></parameter></paramdef>
        <paramdef>const char
        *<parameter><replaceable>group_name</replaceable></parameter></paramdef>
      </funcprototype>
      <funcprototype>
        <funcdef>struct pws3_field *
        <function>pws3_file_remove_empty_group</function></funcdef>
        <paramdef>struct pws3_file
        *<parameter><replaceable>pws_file</replaceable></parameter></paramdef>
        <paramdef>const char
        *<parameter><replaceable>group_name</replaceable></parameter></paramdef>
      </funcprototype>
      <funcprototype>
        <funcdef>struct pws3_field *
        <function>pws3_file_first_empty_group</function></funcdef>
        <paramdef>struct pws3_file
        *<parameter><replaceable>pws_file</replaceable></parameter></paramdef>
      </funcprototype>
      <funcprototype>
        <funcdef>struct pws3_field *
        <function>pws3_file_last_empty_group</function></funcdef>
        <paramdef>struct pws3_file
        *<parameter><replaceable>pws_file</replaceable></parameter></paramdef>
      </funcprototype>
      <funcprototype>
        <funcdef>struct pws3_field *
        <function>pws3_file_next_empty_group</function></funcdef>
        <paramdef>struct pws3_file
        *<parameter><replaceable>pws_file</replaceable></parameter></paramdef>
        <paramdef>struct pws3_field
        *<parameter><replaceable>field</replaceable></parameter></paramdef>
      </funcprototype>
      <funcprototype>
        <funcdef>struct pws3_field *
        <function>pws3_file_prev_empty_group</function></funcdef>
        <paramdef>struct pws3_file
        *<parameter><replaceable>pws_file</replaceable></parameter></paramdef>
        <paramdef>struct pws3_field
        *<parameter><replaceable>field</replaceable></parameter></paramdef>
      </funcprototype>
      <funcprototype>
        <funcdef>void <function>pws3_file_insert_record</function></funcdef>
        <paramdef>struct pws3_file
        *<parameter><replaceable>pws_file</replaceable></parameter></paramdef>
        <paramdef>struct pws3_record
        *<parameter><replaceable>record</replaceable></parameter></paramdef>
      </funcprototype>
      <funcprototype>
        <funcdef>struct pws3_record *
        <function>pws3_file_get_record</function></funcdef>
        <paramdef>struct pws3_file
        *<parameter><replaceable>pws_file</replaceable></parameter></paramdef>
        <paramdef>const unsigned char
        <parameter><replaceable>uuid</replaceable>[static
        PWS3_UUID_SIZE]</parameter></paramdef>
      </funcprototype>
      <funcprototype>
        <funcdef>struct pws3_record *
        <function>pws3_file_remove_record</function></funcdef>
        <paramdef>struct pws3_file
        *<parameter><replaceable>pws_file</replaceable></parameter></paramdef>
        <paramdef>const unsigned char
        <parameter><replaceable>uuid</replaceable>[static
        PWS3_UUID_SIZE]</parameter></paramdef>
      </funcprototype>
      <funcprototype>
        <funcdef>struct pws3_record *
        <function>pws3_file_first_record</function></funcdef>
        <paramdef>struct pws3_file
        *<parameter><replaceable>pws_file</replaceable></parameter></paramdef>
      </funcprototype>
      <funcprototype>
        <funcdef>struct pws3_record *
        <function>pws3_file_last_record</function></funcdef>
        <paramdef>struct pws3_file
        *<parameter><replaceable>pws_file</replaceable></parameter></paramdef>
      </funcprototype>
      <funcprototype>
        <funcdef>struct pws3_record *
        <function>pws3_file_next_record</function></funcdef>
        <paramdef>struct pws3_file
        *<parameter><replaceable>pws_file</replaceable></parameter></paramdef>
        <paramdef>struct pws3_record
        *<parameter><replaceable>record</replaceable></parameter></paramdef>
      </funcprototype>
      <funcprototype>
        <funcdef>struct pws3_record *
        <function>pws3_file_prev_record</function></funcdef>
        <paramdef>struct pws3_file
        *<parameter><replaceable>pws_file</replaceable></parameter></paramdef>
        <paramdef>struct pws3_record
        *<parameter><replaceable>record</replaceable></parameter></paramdef>
      </funcprototype>
      <funcprototype>
        <funcdef>struct pws3_field *
        <function>pws3_field_create</function></funcdef>
        <paramdef>int
        <parameter><replaceable>is_header</replaceable></parameter></paramdef>
        <paramdef>uint8_t
        <parameter><replaceable>field_type</replaceable></parameter></paramdef>
      </funcprototype>
      <funcprototype>
        <funcdef>void <function>pws3_field_destroy</function></funcdef>
        <paramdef>struct pws3_field
        *<parameter><replaceable>field</replaceable></parameter></paramdef>
      </funcprototype>
      <funcprototype>
        <funcdef>int
        <function>pws3_field_is_header</function></funcdef>
        <paramdef>struct pws3_field
        *<parameter><replaceable>field</replaceable></parameter></paramdef>
      </funcprototype>
      <funcprototype>
        <funcdef>uint8_t *
        <function>pws3_field_get_type</function></funcdef>
        <paramdef>struct pws3_field
        *<parameter><replaceable>field</replaceable></parameter></paramdef>
      </funcprototype>
      <funcprototype>
        <funcdef>enum pws_data_type *
        <function>pws3_field_get_data_type</function></funcdef>
        <paramdef>struct pws3_field
        *<parameter><replaceable>field</replaceable></parameter></paramdef>
      </funcprototype>
      <funcprototype>
        <funcdef>int <function>pws3_field_set_uuid</function></funcdef>
        <paramdef>struct pws3_field
        *<parameter><replaceable>field</replaceable></parameter></paramdef>
        <paramdef>const unsigned char
        <parameter><replaceable>uuid</replaceable>[static
        PWS3_UUID_SIZE]</parameter></paramdef>
      </funcprototype>
      <funcprototype>
        <funcdef>int <function>pws3_field_set_text</function></funcdef>
        <paramdef>struct pws3_field
        *<parameter><replaceable>field</replaceable></parameter></paramdef>
        <paramdef>const char
        <parameter><replaceable>s</replaceable>[static 1]</parameter></paramdef>
      </funcprototype>
      <funcprototype>
        <funcdef>int <function>pws3_field_set_time</function></funcdef>
        <paramdef>struct pws3_field
        *<parameter><replaceable>field</replaceable></parameter></paramdef>
        <paramdef>time_t
        <parameter><replaceable>time</replaceable></parameter></paramdef>
      </funcprototype>
      <funcprototype>
        <funcdef>int <function>pws3_field_set_uint8</function></funcdef>
        <paramdef>struct pws3_field
        *<parameter><replaceable>field</replaceable></parameter></paramdef>
        <paramdef>uint8_t
        <parameter><replaceable>u8</replaceable></parameter></paramdef>
      </funcprototype>
      <funcprototype>
        <funcdef>int <function>pws3_field_set_uint16</function></funcdef>
        <paramdef>struct pws3_field
        *<parameter><replaceable>field</replaceable></parameter></paramdef>
        <paramdef>uint16_t
        <parameter><replaceable>u16</replaceable></parameter></paramdef>
      </funcprototype>
      <funcprototype>
        <funcdef>int <function>pws3_field_set_uint32</function></funcdef>
        <paramdef>struct pws3_field
        *<parameter><replaceable>field</replaceable></parameter></paramdef>
        <paramdef>uint32_t
        <parameter><replaceable>u32</replaceable></parameter></paramdef>
      </funcprototype>
      <funcprototype>
        <funcdef>int <function>pws3_field_set_bytes</function></funcdef>
        <paramdef>struct pws3_field
        *<parameter><replaceable>field</replaceable></parameter></paramdef>
        <paramdef>const unsigned char
        <parameter><replaceable>s</replaceable>[static 1]</parameter></paramdef>
        <paramdef>size_t
        <parameter><replaceable>n</replaceable></parameter></paramdef>
      </funcprototype>
      <funcprototype>
        <funcdef>const unsigned char *
        <function>pws3_field_get_uuid</function></funcdef>
        <paramdef>struct pws3_field
        *<parameter><replaceable>field</replaceable></parameter></paramdef>
      </funcprototype>
      <funcprototype>
        <funcdef>const char *
        <function>pws3_field_get_text</function></funcdef>
        <paramdef>struct pws3_field
        *<parameter><replaceable>field</replaceable></parameter></paramdef>
      </funcprototype>
      <funcprototype>
        <funcdef>time_t
        <function>pws3_field_get_time</function></funcdef>
        <paramdef>struct pws3_field
        *<parameter><replaceable>field</replaceable></parameter></paramdef>
      </funcprototype>
      <funcprototype>
        <funcdef>uint8_t
        <function>pws3_field_get_uint8</function></funcdef>
        <paramdef>struct pws3_field
        *<parameter><replaceable>field</replaceable></parameter></paramdef>
      </funcprototype>
      <funcprototype>
        <funcdef>uint16_t
        <function>pws3_field_get_uint16</function></funcdef>
        <paramdef>struct pws3_field
        *<parameter><replaceable>field</replaceable></parameter></paramdef>
      </funcprototype>
      <funcprototype>
        <funcdef>uint32_t
        <function>pws3_field_get_uint32</function></funcdef>
        <paramdef>struct pws3_field
        *<parameter><replaceable>field</replaceable></parameter></paramdef>
      </funcprototype>
      <funcprototype>
        <funcdef>void <function>pws3_field_get_bytes</function></funcdef>
        <paramdef>struct pws3_field
        *<parameter><replaceable>field</replaceable></parameter></paramdef>
        <paramdef>const unsigned char
        **<parameter><replaceable>pp</replaceable></parameter></paramdef>
        <paramdef>size_t
        *<parameter><replaceable>np</replaceable></parameter></paramdef>
      </funcprototype>
    </funcsynopsis>
    <synopsis>
<constant>PWS3_VERSION</constant>

<constant>PWS3_MAX_FIELD_LEN</constant>

<constant>PWS3_MAX_PASSWORD_LEN</constant>

<constant>PWS3_UUID_SIZE</constant>

struct pws3_field;

struct pws3_record;

struct pws3_file;

enum pws_error_code;

enum pws_data_type;

enum pws3_header_field_type;

enum pws3_record_field_type;
</synopsis>
  </refsynopsisdiv>
  <refsect1>
    <title>Description</title>
    <refsect2>
      <title>Introduction</title>
      <para>The <function>pws3_*()</function> family of functions allows
      creating, reading, writing, and manipulating Password Safe version 3
      files. Password Safe version 3 files consist of a header and a body part.
      The header is comprised of both mandatory and optional typed header
      fields which hold file-wide metadata. The body consists of records which
      in turn hold passwords and associated metadata in typed record
      fields.</para>
      <para>A header or record field value can be of one of seven basic data
      types defined below:
      <table xml:id="table-data-types">
        <title>Header and Record Field Value Data Types</title>
        <tgroup cols="3" align="left" colsep="1" rowsep="1">
          <thead>
            <row>
              <entry>Data Type</entry>
              <entry>C Type</entry>
              <entry>Description</entry>
            </row>
          </thead>
          <tbody>
            <row>
              <entry><constant>PWS_DATA_TYPE_UUID</constant></entry>
              <entry><code>unsigned char [PWS3_UUID_SIZE]</code></entry>
              <entry>UUID</entry>
            </row>
            <row>
              <entry><constant>PWS_DATA_TYPE_TEXT</constant></entry>
              <entry><code>char *</code></entry>
              <entry>NUL-delimited UTF-8 encoded string</entry>
            </row>
            <row>
              <entry><constant>PWS_DATA_TYPE_TIME</constant></entry>
              <entry><code>time_t</code></entry>
              <entry>system-specific representation of time</entry>
            </row>
            <row>
              <entry><constant>PWS_DATA_TYPE_UINT8</constant></entry>
              <entry><code>uint8_t</code></entry>
              <entry>8-bit wide unsigned integer</entry>
            </row>
            <row>
              <entry><constant>PWS_DATA_TYPE_UINT16</constant></entry>
              <entry><code>uint16_t</code></entry>
              <entry>16-bit wide unsigned integer</entry>
            </row>
            <row>
              <entry><constant>PWS_DATA_TYPE_UINT32</constant></entry>
              <entry><code>uint32_t</code></entry>
              <entry>32-bit wide unsigned integer</entry>
            </row>
            <row>
              <entry><constant>PWS_DATA_TYPE_BYTES</constant></entry>
              <entry><code>unsigned char *</code></entry>
              <entry>array of bytes</entry>
            </row>
          </tbody>
        </tgroup>
      </table>
      </para>
      <para>The data type of each header field is defined in
      <xref linkend="table-header-fields"/> and the data type of each record
      field is defined in <xref linkend="table-record-fields"/>. Each header
      field, with the exception of the empty groups header field, can only
      occur once. The version header field
      (<constant>PWS3_HEADER_FIELD_VERSION</constant>) is mandatory and must
      not be removed. When reading a file its value is checked and an error is
      returned if the file format version newer than the one supported by
      <citerefentry><refentrytitle>libpws</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
      The supported version is defined by the <constant>PWS3_VERSION</constant>
      macro, when creating a new file structure the version header field will be
      set to its value by default. Non-standard header and record fields will
      be preserved when a file is read and subsequently written again, they may
      be read and manipulated as if they had
      <constant>PWS_DATA_TYPE_BYTES</constant> data type. All strings are
      expected to be in UTF-8 encoding.</para>
      <para>The only mandatory record field is the UUID field which uniquely
      identifies a record in the file.</para>
      <para>The complete and authoritative specification of the file format is
      included with the original Password Safe application available from <link
      xlink:href="https://pwsafe.org/"/>.</para>
    </refsect2>
    <refsect2>
      <title>Password Safe File Data Structure</title>
      <para>The <function>pws3_file_create()</function> function allocates and
      intializes a Password Safe file data structure representing a Password
      Safe version 3 file. It automatically creates the mandatory version header
      field and initializes it to the value of the
      <constant>PWS3_VERSION</constant> macro.</para>
      <para>The <function>pws3_file_destroy()</function> function deallocates
      all header fields and records of the file structure passed to it and then
      deallocates the file structure itself.</para>
      <para>The <function>pws3_file_read_mem()</function> and
      <function>pws3_file_read_stream()</function> functions read and parse a
      Password Safe file into the given data structure passed via the
      <parameter>pws_file</parameter> argument, replacing any existing header
      fields and records. The key used to decrypt the file is derived from the
      given <parameter>password</parameter> parameter. The
      <function>pws3_file_read_mem()</function> function reads the file from a
      block of memory <parameter>s</parameter> with the size of
      <parameter>n</parameter> bytes. The
      <function>pws3_file_read_stream()</function> reads the file from the
      stream of the <parameter>fp</parameter> file pointer.</para>
      <para>The <function>pws3_file_write_mem()</function> and
      <function>pws3_file_write_stream()</function> functions write a new
      Password Safe file from the given datat structure. The key used to
      encrypt the file is derived from the <parameter>password</parameter>
      argument using the number of iterations to stretch the key determined by
      the <parameter>n_iter</parameter> argument. The
      <function>pws3_file_write_mem()</function> will allocate and place the
      file contents into memory and return the location and size to the
      locations <parameter>sp</parameter> and <parameter>np</parameter>
      point to. The <function>pws3_file_write_stream()</function> will write the
      file contents to the stream of the <parameter>fp</parameter> file
      pointer.</para>
    </refsect2>
    <refsect2>
      <title>Fields</title>
      <para>Both header and record fields are stored in
      <varname>pws3_field</varname> structures which are allocated and
      initialized with the <function>pws3_field_create()</function> function.
      Depending on whether <parameter>is_header</parameter> is non-zero either
      a header field or a record field data structure of the given field type
      will be created.</para>
      <para>The <function>pws3_field_destroy()</function> function
      deallocates the given field data structure and its content.</para>
      <para>The <function>pws3_field_is_header()</function> function
      can be used to test whether the given field data structure refers to a
      header field or a record field.</para>
      <para>The <function>pws3_field_get_type()</function> function
      returns the field type of the given field data structure.</para>
      <para>The <function>pws3_field_get_data_type()</function> function
      returns the data type of the given field structure.</para>
      <para>The <function>pws3_field_set_uuid()</function>,
      <function>pws3_field_set_text()</function>,
      <function>pws3_field_set_time()</function>,
      <function>pws3_field_set_uint8()</function>,
      <function>pws3_field_set_uint16()</function>,
      <function>pws3_field_set_uint32()</function>, and
      <function>pws3_field_set_bytes()</function> functions set the
      content of the given field. The given data is always copied and
      existing content is replaced. The data type used by the function must
      match the data type of the field specified in <xref
      linkend="table-header-fields"/> in case of header fields or that in <xref
      linkend="table-record-fields"/> in case of record fields.</para>
      <para>The <function>pws3_field_get_time()</function>,
      <function>pws3_field_get_uint8()</function>,
      <function>pws3_field_get_uint16()</function>, and
      <function>pws3_field_get_uint32()</function> functions return the
      value of the given field. The
      <function>pws3_field_get_uuid()</function>,
      <function>pws3_field_get_text()</function>, and
      <function>pws3_field_get_bytes()</function> functions return a
      pointer to the data of the given field if it has been set. The data type
      used by the function must match the data type of the field specified in
      <xref linkend="table-header-fields"/> in case of header fields and that
      in <xref linkend="table-record-fields"/> in case of record fields.
      Returned pointers are only valid until a field is modified or
      deallocated.</para>
    </refsect2>
    <refsect2>
      <title>Header Fields</title>
      <para>Header fields are used to store metadata for the whole file, each
      type of header field with the exception of the empty groups header field
      only occurs once. The following header fields are supported:
      <table xml:id="table-header-fields">
        <title>Header Fields</title>
        <tgroup cols="4" align="left" colsep="1" rowsep="1">
          <thead>
            <row>
              <entry>Header Field Type</entry>
              <entry>Numeric Value</entry>
              <entry>Data Type</entry>
              <entry>Description</entry>
            </row>
          </thead>
          <tbody>
            <row>
              <entry><constant>PWS3_&#8203;HEADER_&#8203;FIELD_&#8203;VERSION</constant></entry>
              <entry><literal>0x00</literal></entry>
              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;UINT16</constant></entry>
              <entry>file format version</entry>
            </row>
            <row>
              <entry><constant>PWS3_&#8203;HEADER_&#8203;FIELD_&#8203;UUID</constant></entry>
              <entry><literal>0x01</literal></entry>
              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;UUID</constant></entry>
              <entry>UUID</entry>
            </row>
            <row>
              <entry><constant>PWS3_&#8203;HEADER_&#8203;FIELD_&#8203;NON_&#8203;DEFAULT_&#8203;PREFERENCES</constant></entry>
              <entry><literal>0x02</literal></entry>
              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
              <entry>non-default preferences</entry>
            </row>
            <row>
              <entry><constant>PWS3_&#8203;HEADER_&#8203;FIELD_&#8203;TREE_&#8203;DISPLAY_&#8203;STATUS</constant></entry>
              <entry><literal>0x03</literal></entry>
              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
              <entry>expandended/&#8203;collapsed state of the tree of groups</entry>
            </row>
            <row>
              <entry><constant>PWS3_&#8203;HEADER_&#8203;FIELD_&#8203;SAVE_&#8203;TIMESTAMP</constant></entry>
              <entry><literal>0x04</literal></entry>
              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TIME</constant></entry>
              <entry>time when the file was last saved</entry>
            </row>
            <row>
              <entry><constant>PWS3_&#8203;HEADER_&#8203;FIELD_&#8203;SAVE_&#8203;USER_&#8203;HOST</constant></entry>
              <entry><literal>0x05</literal></entry>
              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
              <entry>name of the user who last saved the file and name of the host where the file was saved</entry>
            </row>
            <row>
              <entry><constant>PWS3_&#8203;HEADER_&#8203;FIELD_&#8203;SAVE_&#8203;APPLICATION</constant></entry>
              <entry><literal>0x06</literal></entry>
              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
              <entry>name of the application used to save the file</entry>
            </row>
            <row>
              <entry><constant>PWS3_&#8203;HEADER_&#8203;FIELD_&#8203;SAVE_&#8203;USER</constant></entry>
              <entry><literal>0x07</literal></entry>
              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
              <entry>name of the user who last saved the file</entry>
            </row>
            <row>
              <entry><constant>PWS3_&#8203;HEADER_&#8203;FIELD_&#8203;SAVE_&#8203;HOST</constant></entry>
              <entry><literal>0x08</literal></entry>
              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
              <entry>name of the host where the file was last saved</entry>
            </row>
            <row>
              <entry><constant>PWS3_&#8203;HEADER_&#8203;FIELD_&#8203;DATABASE_&#8203;NAME</constant></entry>
              <entry><literal>0x09</literal></entry>
              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
              <entry>logical name for referring to the file</entry>
            </row>
            <row>
              <entry><constant>PWS3_&#8203;HEADER_&#8203;FIELD_&#8203;DATABASE_&#8203;DESCRIPTION</constant></entry>
              <entry><literal>0x0a</literal></entry>
              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
              <entry>description of the file</entry>
            </row>
            <row>
              <entry><constant>PWS3_&#8203;HEADER_&#8203;FIELD_&#8203;DATABASE_&#8203;FILTERS</constant></entry>
              <entry><literal>0x0b</literal></entry>
              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
              <entry>filters for this file</entry>
            </row>
            <row>
              <entry><constant>PWS3_&#8203;HEADER_&#8203;FIELD_&#8203;RESERVED_&#8203;1</constant></entry>
              <entry><literal>0x0c</literal></entry>
              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;BYTES</constant></entry>
              <entry>reserved</entry>
            </row>
            <row>
              <entry><constant>PWS3_&#8203;HEADER_&#8203;FIELD_&#8203;RESERVED_&#8203;2</constant></entry>
              <entry><literal>0x0d</literal></entry>
              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;BYTES</constant></entry>
              <entry>reserved</entry>
            </row>
            <row>
              <entry><constant>PWS3_&#8203;HEADER_&#8203;FIELD_&#8203;RESERVED_&#8203;3</constant></entry>
              <entry><literal>0x0e</literal></entry>
              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;BYTES</constant></entry>
              <entry>reseved</entry>
            </row>
            <row>
              <entry><constant>PWS3_&#8203;HEADER_&#8203;FIELD_&#8203;RECENTLY_&#8203;USED_&#8203;ENTRIES</constant></entry>
              <entry><literal>0x0f</literal></entry>
              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
              <entry>list of recently used entries</entry>
            </row>
            <row>
              <entry><constant>PWS3_&#8203;HEADER_&#8203;FIELD_&#8203;NAMED_&#8203;PASSWORD_&#8203;POLICIES</constant></entry>
              <entry><literal>0x10</literal></entry>
              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
              <entry>named password policies</entry>
            </row>
            <row>
              <entry><constant>PWS3_&#8203;HEADER_&#8203;FIELD_&#8203;EMPTY_&#8203;GROUPS</constant></entry>
              <entry><literal>0x11</literal></entry>
              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
              <entry>empty groups which contain no entries</entry>
            </row>
            <row>
              <entry><constant>PWS3_&#8203;HEADER_&#8203;FIELD_&#8203;YUBICO</constant></entry>
              <entry><literal>0x12</literal></entry>
              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
              <entry>reserved</entry>
            </row>
            <row>
              <entry><constant>PWS3_&#8203;HEADER_&#8203;FIELD_&#8203;PASSWORD_&#8203;TIMESTAMP</constant></entry>
              <entry><literal>0x13</literal></entry>
              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TIME</constant></entry>
              <entry>time the master password was last changed</entry>
            </row>
          </tbody>
        </tgroup>
      </table>
      </para>
      <para>The <function>pws3_file_set_header_field()</function> function sets
      the header field on the given file. An existing field of the same type is
      replaced with the exception of fields of type
      <constant>PWS3_HEADER_FIELD_EMPTY_GROUPS</constant> for which
      <function>pws3_file_set_header_field()</function> has the same effect as
      calling the <function>pws3_file_insert_empty_group()</function>
      function.</para>
      <para>The <function>pws3_file_get_header_field()</function> function
      returns a pointer to the header field data structure of the given header
      field type. In case of the
      <constant>PWS3_HEADER_FIELD_EMPTY_GROUPS</constant> field type a pointer
      to the first empty group field is returned.</para>
      <para>The <function>pws3_file_remove_header_field()</function> function
      removes the header field from the given file and returns a pointer to it.
      It is the responsibility of the caller to deallocate the header field
      data structure. In case of the
      <constant>PWS3_HEADER_FIELD_EMPTY_GROUPS</constant> field type the first
      empty group is removed.</para>
      <para>The <function>pws3_file_insert_empty_group()</function> function
      inserts the given empty groups field into the file, an existing field for
      a group of the same name is replaced.</para>
      <para>The <function>pws3_file_get_empty_group()</function> function
      returns a pointer to the header field datat structure representing an
      empty group of the given name.</para>
      <para>The <function>pws3_file_remove_empty_group()</function> function
      removes the field representing the empty group of the given name from the
      file and returns a pointer to the header field data structure. It is the
      responsibility of the caller to deallocate the header field data
      structure.</para>
      <para>The <function>pws3_file_first_empty_group()</function> function
      returns a pointer to the first empty group header field.</para>
      <para>The <function>pws3_file_last_empty_group()</function> function
      returns a pointer to the last empty group header field.</para>
      <para>The <function>pws3_file_next_empty_group()</function> function
      returns a pointer to the next empty group header filed data structure
      following the given <parameter>field</parameter>.</para>
      <para>The <function>pws3_file_prev_empty_groupious()</function> function
      returns a pointer to the previous empty group header filed data structure
      preceding the given <parameter>field</parameter>.</para>
    </refsect2>
    <refsect2>
      <title>Records</title>
      <para>Records consist of at least one or more typed fields, they are
      identified by an UUID which is the only mandatory field and must not be
      removed. For presentational purposes records may be organized in
      hierarchical groups. The following record fields are supported:
      <table xml:id="table-record-fields">
        <title>Record Fields</title>
        <tgroup cols="4" align="left" colsep="1" rowsep="1">
          <thead>
            <row>
              <entry>Record Field Type</entry>
              <entry>Numeric Value</entry>
              <entry>Data Type</entry>
              <entry>Description</entry>
            </row>
          </thead>
          <tbody>
            <row>
              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;UUID</constant></entry>
              <entry><literal>0x01</literal></entry>
              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;UUID</constant></entry>
              <entry>UUID identifying the record</entry>
            </row>
            <row>
              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;GROUP</constant></entry>
              <entry><literal>0x02</literal></entry>
              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
              <entry>group name the record is a member of</entry>
            </row>
            <row>
              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;TITLE</constant></entry>
              <entry><literal>0x03</literal></entry>
              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
              <entry>title</entry>
            </row>
            <row>
              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;USERNAME</constant></entry>
              <entry><literal>0x04</literal></entry>
              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
              <entry>username</entry>
            </row>
            <row>
              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;NOTES</constant></entry>
              <entry><literal>0x05</literal></entry>
              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
              <entry>notes</entry>
            </row>
            <row>
              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;PASSWORD</constant></entry>
              <entry><literal>0x06</literal></entry>
              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
              <entry>password</entry>
            </row>
            <row>
              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;CREATION_&#8203;TIME</constant></entry>
              <entry><literal>0x07</literal></entry>
              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TIME</constant></entry>
              <entry>time when the record was created</entry>
            </row>
            <row>
              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;PASSWORD_&#8203;MODIFICATION_&#8203;TIME</constant></entry>
              <entry><literal>0x08</literal></entry>
              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TIME</constant></entry>
              <entry>time when the password was last modified</entry>
            </row>
            <row>
              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;ACCESS_&#8203;TIME</constant></entry>
              <entry><literal>0x09</literal></entry>
              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TIME</constant></entry>
              <entry>time when the record was last accessed</entry>
            </row>
            <row>
              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;PASSWORD_&#8203;EXPIRY_&#8203;TIME</constant></entry>
              <entry><literal>0x0a</literal></entry>
              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TIME</constant></entry>
              <entry>time when the password expires</entry>
            </row>
            <row>
              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;RESERVED_&#8203;1</constant></entry>
              <entry><literal>0x0b</literal></entry>
              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;BYTES</constant></entry>
              <entry>reserved</entry>
            </row>
            <row>
              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;MODIFICATION_&#8203;TIME</constant></entry>
              <entry><literal>0x0c</literal></entry>
              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TIME</constant></entry>
              <entry>time at whcih the record was last modified</entry>
            </row>
            <row>
              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;URL</constant></entry>
              <entry><literal>0x0d</literal></entry>
              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
              <entry>URL</entry>
            </row>
            <row>
              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;AUTOTYPE</constant></entry>
              <entry><literal>0x0e</literal></entry>
              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
              <entry>text to be typed when using the autotype feature</entry>
            </row>
            <row>
              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;PASSWORD_&#8203;HISTORY</constant></entry>
              <entry><literal>0x0f</literal></entry>
              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
              <entry>creation time and values of previously used passwords</entry>
            </row>
            <row>
              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;PASSWORD_&#8203;POLICY</constant></entry>
              <entry><literal>0x10</literal></entry>
              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
              <entry>password policy</entry>
            </row>
            <row>
              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;PASSWORD_&#8203;EXPIRY_&#8203;INTERVAL</constant></entry>
              <entry><literal>0x11</literal></entry>
              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;UINT32</constant></entry>
              <entry>days until the password expires</entry>
            </row>
            <row>
              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;RUN_&#8203;COMMAND</constant></entry>
              <entry><literal>0x12</literal></entry>
              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
              <entry>command</entry>
            </row>
            <row>
              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;DOUBLE_&#8203;CLICK_&#8203;ACTION</constant></entry>
              <entry><literal>0x13</literal></entry>
              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;BYTES</constant></entry>
              <entry>action on double clicking</entry>
            </row>
            <row>
              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;EMAIL_&#8203;ADDRESS</constant></entry>
              <entry><literal>0x14</literal></entry>
              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
              <entry>email address</entry>
            </row>
            <row>
              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;PROTECTED</constant></entry>
              <entry><literal>0x15</literal></entry>
              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;UINT8</constant></entry>
              <entry>flag whether the record is protected from modification</entry>
            </row>
            <row>
              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;ALLOWED_&#8203;PASSWORD_&#8203;SYMBOLS</constant></entry>
              <entry><literal>0x16</literal></entry>
              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
              <entry>allowed symbols for generating passwords</entry>
            </row>
            <row>
              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;SHIFT_&#8203;DOUBLE_&#8203;CLICK_&#8203;ACTION</constant></entry>
              <entry><literal>0x17</literal></entry>
              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;BYTES</constant></entry>
              <entry>action on pressing shift and double clicking</entry>
            </row>
            <row>
              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;PASSWORD_&#8203;POLICY_&#8203;NAME</constant></entry>
              <entry><literal>0x18</literal></entry>
              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
              <entry>name of password policy saved in the header</entry>
            </row>
            <row>
              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;KEYBOARD_&#8203;SHORTCUT</constant></entry>
              <entry><literal>0x19</literal></entry>
              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;BYTES</constant></entry>
              <entry>keyboard shortcut</entry>
            </row>
            <row>
              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;RESERVED_&#8203;2</constant></entry>
              <entry><literal>0x1a</literal></entry>
              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;UUID</constant></entry>
              <entry>reserved</entry>
            </row>
            <row>
              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;TWO_&#8203;FACTOR_&#8203;KEY</constant></entry>
              <entry><literal>0x1b</literal></entry>
              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;BYTES</constant></entry>
              <entry>two factor key</entry>
            </row>
            <row>
              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;CREDIT_&#8203;CARD_&#8203;NUMBER</constant></entry>
              <entry><literal>0x1c</literal></entry>
              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
              <entry>credit card number</entry>
            </row>
            <row>
              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;CREDIT_&#8203;CARD_&#8203;EXPIRATION</constant></entry>
              <entry><literal>0x1d</literal></entry>
              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
              <entry>credit card expiration</entry>
            </row>
            <row>
              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;CREDIT_&#8203;CARD_&#8203;VERIFICATION_&#8203;VALUE</constant></entry>
              <entry><literal>0x1e</literal></entry>
              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
              <entry>credit card verification value</entry>
            </row>
            <row>
              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;CREDIT_&#8203;CARD_&#8203;PIN</constant></entry>
              <entry><literal>0x1f</literal></entry>
              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
              <entry>credit card PIN</entry>
            </row>
            <row>
              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;QR_&#8203;CODE</constant></entry>
              <entry><literal>0x20</literal></entry>
              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;TEXT</constant></entry>
              <entry>QR code</entry>
            </row>
            <row>
              <entry><constant>PWS3_&#8203;RECORD_&#8203;FIELD_&#8203;TESTING_&#8203;1</constant></entry>
              <entry><literal>0xdf</literal></entry>
              <entry><constant>PWS_&#8203;DATA_&#8203;TYPE_&#8203;BYTES</constant></entry>
              <entry>testing</entry>
            </row>
          </tbody>
        </tgroup>
      </table>
      </para>
      <para>The <function>pws3_record_create()</function> function allocates
      and creates a record data structure, generates an UUID record field and
      adds it to the record.</para>
      <para>The <function>pws3_record_destroy()</function> function deallocates
      the given record data structure and all its record fields.</para>
      <para>The <function>pws3_file_record_field_set()</function> function sets
      the record field on the given record, replacing an existing field of the
      same type.</para>
      <para>The <function>pws3_file_record_field_get()</function> function
      returns a pointer to the record field data structure of the given record
      field type.</para>
      <para>The <function>pws3_file_record_field_remove()</function> function
      removes the record field from the given record and returns a pointer to
      it. It is the responsibility of the caller to deallocate the record field
      data structure.</para>
      <para>The <function>pws3_file_insert_record()</function> function inserts
      the given record into the file, an existing record with the same UUID is
      replaced.</para>
      <para>The <function>pws3_file_get_record()</function> function returns a
      pointer to the record structure representing a record with the given
      UUID.</para>
      <para>The <function>pws3_file_remove_record()</function> function removes
      the record with the given UUID from the file and returns a pointer to the
      record data structure. It is the responsibility of the caller to
      deallocate the record data structure.</para>
      <para>The <function>pws3_file_first_record()</function> function returns a
      pointer to the first record.</para>
      <para>The <function>pws3_file_last_record()</function> function returns a
      pointer to the last record.</para>
      <para>The <function>pws3_file_next_record()</function> function returns a
      pointer to the next record following the given
      <parameter>record</parameter>.</para>
      <para>The <function>pws3_file_prev_record()</function>
      function returns a pointer to the previous group preceding the given
      <parameter>record</parameter>.</para>
    </refsect2>
    <refsect2>
      <title>Macros</title>
      <para>The macro <constant>PWS3_VERSION</constant> contains the supported
      version of the Password Safe version 3 file format.</para>
      <para>The macro <constant>PWS3_MAX_FIELD_SIZE</constant> contains the
      maxium size for header and record fields in bytes and
      <constant>PWS3_MAX_PASSWORD_LEN</constant> contains the maxium password
      length in bytes.</para>
      <para>The macro <constant>PWS3_UUID_SIZE</constant> contains the size of
      UUIDs in bytes.</para>
    </refsect2>
  </refsect1>
  <refsect1>
    <title>Return Values</title>
    <para>The <function>pws3_file_create()</function> function returns a
    pointer to a Password Safe file data structure if successful and
    <constant>NULL</constant> in case of an error.</para>
    <para>The <function>pws3_file_read_mem()</function>,
    <function>pws3_file_read_stream()</function>,
    <function>pws3_file_write_mem()</function>, and
    <function>pws3_file_write_stream()</function> functions return
    <returnvalue>0</returnvalue> on success and <returnvalue>-1</returnvalue>
    to indicate an error.</para>
    <para>The <function>pws3_file_get_header_field()</function> function
    returns a pointer to the header field data structure of the requested type
    and <constant>NULL</constant> if such a field does not exist.</para>
    <para>The <function>pws3_file_remove_header_field()</function> function
    returns a pointer to the header field data structure which was removed from
    the file or <constant>NULL</constant> if such a field does not exist.</para>
    <para>The <function>pws3_file_get_empty_group()</function> function returns
    a pointer to the header field data structure corresponding to the requested
    empty group and <constant>NULL</constant> if a group of that name does not
    exist.</para>
    <para>The <function>pws3_file_remove_empty_group()</function> function
    returns a pointer to the header field data structure of the empty group
    which was removed from the file or <constant>NULL</constant> if a group of
    that name does not exist.</para>
    <para>The <function>pws3_file_first_empty_group()</function> function
    returns a pointer to the first of the empty group header fields or
    <constant>NULL</constant> if there are no such fields.</para>
    <para>The <function>pws3_file_last_empty_group()</function> function
    returns a pointer to the last of the empty group header fields or
    <constant>NULL</constant> if there are no such fields.</para>
    <para>The <function>pws3_file_next_empty_group()</function> function
    returns a pointer to the next empty group header field or
    <constant>NULL</constant> if there are no more such fields.</para>
    <para>The <function>pws3_file_prev_empty_group()</function> function
    returns a pointer to the previous empty group header field or
    <constant>NULL</constant> if there are no more such fields.</para>
    <para>The <function>pws3_file_get_record()</function> function returns a
    pointer to the record data structure of the requested record or
    <constant>NULL</constant> if that record does not exist.</para>
    <para>The <function>pws3_file_remove_record()</function> function returns a
    pointer to the record data structure which was removed from the file or
    <constant>NULL</constant> if no such record exists.</para>
    <para>The <function>pws3_file_first_record()</function> function returns a
    pointer to the record data structure of the first record or
    <constant>NULL</constant> if no records exist.</para>
    <para>The <function>pws3_file_last_record()</function> function returns a
    pointer to the record data structure of the last record or
    <constant>NULL</constant> if no records exist.</para>
    <para>The <function>pws3_file_next_record()</function> function returns a
    pointer to the record data structure of the next record or
    <constant>NULL</constant> if no records exist.</para>
    <para>The <function>pws3_file_prev_record()</function> function returns a
    pointer to the record data structure of the previous record or
    <constant>NULL</constant> if no records exist.</para>
    <para>The <function>pws3_field_create()</function> function returns a
    pointer to the new header field data structure on success and
    <constant>NULL</constant> on failure.</para>
    <para>The <function>pws3_field_get_type()</function> function returns
    the field type of the header field structure.</para>
    <para>The <function>pws3_field_get_data_type()</function> function
    returns the data type of the header field structure.</para>
    <para>The <function>pws3_field_set_uuid()</function>,
    <function>pws3_field_set_text()</function>,
    <function>pws3_field_set_time()</function>,
    <function>pws3_field_set_uint8()</function>,
    <function>pws3_field_set_uint16()</function>,
    <function>pws3_field_set_uint32()</function>, and
    <function>pws3_field_set_bytes()</function> functions return
    <returnvalue>0</returnvalue> on success and <returnvalue>-1</returnvalue>
    on failure.</para>
    <para>The <function>pws3_field_get_time()</function>,
    <function>pws3_field_get_uint8()</function>,
    <function>pws3_field_get_uint16()</function>, and
    <function>pws3_field_get_uint32()</function> functions return a
    value of the type corresponding to the type of header field.</para>
    <para>The <function>pws3_field_get_uuid()</function> function
    returns a pointer to a UUID.</para>
    <para>The <function>pws3_field_get_text()</function> function
    returns a pointer to a string or <constant>NULL</constant> if no value has
    been set.</para>
    <para>The <function>pws3_record_create()</function> function returns a
    pointer to a record data structure if successful and
    <constant>NULL</constant> on failure.</para>
    <para>The <function>pws3_record_get_field()</function> function returns a
    pointer to the record field data structure of the requested type or
    <constant>NULL</constant> if such a field does not exist.</para>
    <para>The <function>pws3_record_remove_field()</function> function returns
    a pointer to the record field data structure which was removed from the
    record or <constant>NULL</constant> if such a field does not exist.</para>
  </refsect1>
  <refsect1>
    <title>Errors</title>
    <para>If the <function>pws3_file_read_mem()</function>,
    <function>pws3_file_read_stream()</function>,
    <function>pws3_file_write_mem()</function>, and
    <function>pws3_file_write_stream()</function> functions fail, an error code
    indicating the nature of the error may be obtained using the
    <function>pws3_file_get_error_code()</function> function and a pointer to a
    detailed error message may be retrieved using the
    <function>pws3_file_get_error_message()</function> function. The above
    functions may fail if:</para>
    <variablelist>
      <varlistentry>
        <term><errorname>PWS_ERR_GENERIC_ERROR</errorname></term>
        <listitem>
          <para>An unknown error occurred.</para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term><errorname>PWS_ERR_NO_MEMORY</errorname></term>
        <listitem>
          <para>There was not enough space to allocate memory.</para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term><errorname>PWS_ERR_IO_ERROR</errorname></term>
        <listitem>
          <para>An I/O error occurred.</para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term><errorname>PWS_ERR_TRUNCATED_FILE</errorname></term>
        <listitem>
          <para>The file appears to be truncated.</para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term><errorname>PWS_ERR_INVALID_CHECKSUM</errorname></term>
        <listitem>
          <para>The calculated checksum does not match the checksum of the
          file.</para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term><errorname>PWS_ERR_INVALID_RECORD</errorname></term>
        <listitem>
          <para>A record is invalid.</para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term><errorname>PWS_ERR_INVALID_HEADER</errorname></term>
        <listitem>
          <para>A header is invalid.</para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term><errorname>PWS_ERR_UNSUPPORTED_VERSION</errorname></term>
        <listitem>
          <para>The file format version is not supported.</para>
        </listitem>
      </varlistentry>
    </variablelist>
  </refsect1>
  <refsect1>
    <title>Examples</title>
    <example>
      <title>Creating a Password Safe file</title>
      <para>The following code creates a new Password Safe file and sets the
      save application header field:</para>
      <programlisting>
<![CDATA[
#include <pws.h>

/* ... */

struct pws3_file *file;
struct pws3_field *application_field;

/* ... */

/* initialize libpws */
if (pws_init() != 0) {
	/* handle error */
}

/* ... */

/* create a new empty file structure */
file = pws3_file_create();
if (file == NULL) {
	/* handle error */
}
/* create new empty save application field */
application_field = pws3_field_create(1, PWS3_HEADER_FIELD_SAVE_APPLICATION);
if (application_field == NULL) {
	/* handle error */
}
/* set the value of the field */
if (pws3_field_set_text(application_field, "PasswordManager 2.0") != 0) {
	/* handle error */
}
/* set the header save application field in the file to the new field */
pws3_file_set_field(file, application_field);
]]>
</programlisting>
    </example>
    <example>
      <title>Print the title of each record</title>
      <para>The following code loops over each record of an existing Password
      Safe file and prints the content of the title field if it exists:</para>
      <programlisting>
<![CDATA[
#include <stdio.h>
#include <pws.h>

/* ... */

struct pws3_file *file;
struct pws3_record *record;
struct pws3_field *title_field;

/* ... */

/* interate over each record */
for (record = pws3_file_first_record(file); record != NULL;
    record = pws3_file_next_record(file, record)) {
	/* retrieve title field */
	title_field = pws3_record_get_field(record, PWS3_RECORD_FIELD_TITLE);
	/* print the title field or "No title" if it does not exitst */
	printf("Title: %s\n", (title_field != NULL) ?
	    pws3_record_field_get_text(PWS3_RECORD_FIELD_TITLE) : "No title");
}
]]>
</programlisting>
    </example>
    <example>
      <title>Add a new record to a file</title>
      <para>The following code creates a new record with a password field, a
      title field, and a creation time field and adds it to an existing
      Password Safe file:</para>
      <programlisting>
<![CDATA[
#include <time.h>
#include <pws.h>

/* ... */

struct pws3_file *file;
struct pws3_record *record;
struct pws3_field *password_field;
struct pws3_field *title_field;
struct pws3_field *ctime_field;
time_t		now;

/* ... */

/* create new record */
record = pws3_record_create();
if (record == NULL) {
	/* handle error */
}

/* create a password field */
password_field = pws3_record_field_create(PWS3_RECORD_FIELD_PASSWORD);
if (password_field == NULL) {
	/* handle error */
}
/* set the value of the password field to "PaSsWoRd" */
if (pws3_record_field_set_text(password_field, "PaSsWoRd") != 0) {
	/* handle error */
}
/* set the password field of the record to the new field */
pws3_record_set_field(record, password_field);

/* create a title field */
title_field = pws3_record_field_create(PWS3_RECORD_FIELD_TITLE);
if (title_field == NULL) {
	/* handle error */
}
/* set the value of the title field to "Foo Bar" */
if (pws3_record_field_set_text(title_field, "Foo Bar") != 0) {
	/* handle error */
}
/* set the title field of the record to the new field */
pws3_record_set_field(record, title_field);

/* create a new creation time field */
ctime_field = pws3_record_field_create(PWS3_RECORD_FIELD_CREATION_TIME);
if (ctime_field == NULL) {
	/* handle error */
}
/* set the value of the creation time field to the current time */
pws3_record_field_set_time(ctime_field, time(NULL));
/* set the creation time field of the record to the new field */
pws3_record_set_field(record, ctime_field);

/* insert the new record into the file */
pws3_file_insert_record(file, record);
]]>
</programlisting>
    </example>
    <example>
      <title>Reading a Password Safe file</title>
      <para>The following code opens a Password Safe file named
      <filename>example.pwsafe3</filename> and parses it:</para>
      <programlisting>
<![CDATA[
#include <stdio.h>
#include <pws.h>

/* ... */

FILE		*fp;
struct pws3_file *file;

/* ... */

/* initialize libpws */
if (pws_init() != 0) {
	/* handle error */
}

/* ... */

/* create a new empty file structure */
file = pws3_file_create();
if (file == NULL) {
	/* handle error */
}

/* open the file */
fp = fopen("example.pwsafe3", "r");
if (fp == NULL) {
	/* handle error */
}

/* read and parse the file contents into the file structure */
if (pws3_file_read_stream(file, "PaSsWoRd", fp) != 0) {
	fprintf(stderr, "error: %s\n",
	   pws3_file_get_error_message(file));
	/* handle error */
}
]]>
</programlisting>
    </example>
    <example>
      <title>Writing a Password Safe file</title>
      <para>The following code writes a Password Safe file to a file
      named <filename>example.pwsafe3</filename>:</para>
      <programlisting>
<![CDATA[
#include <stdio.h>
#include <pws.h>

/* ... */

FILE		*fp;
struct pws3_file *file;

/* ... */

fp = fopen("example.pwsafe3", "w");
if (fp == NULL) {
	/* handle error */
}

if (pws3_file_write_stream(file, "FoOBaR", 10000, fp) != 0) {
	/* handle error */
}

fflush(fp);
fclose(fp);
]]>
</programlisting>
    </example>
  </refsect1>
  <refsect1>
    <title>See Also</title>
    <para><citerefentry><refentrytitle>libpws</refentrytitle>
    <manvolnum>3</manvolnum></citerefentry>,
    <citerefentry><refentrytitle>pws_init</refentrytitle>
    <manvolnum>3</manvolnum></citerefentry>,
    <link xlink:href="https://pwsafe.org/"/></para>
  </refsect1>
</refentry>