Name

pws3_file_create, pws3_file_destroy, pws3_file_get_error_code, pws3_file_get_error_message, pws3_file_read_mem, pws3_file_read_stream, pws3_file_write_mem, pws3_file_write_stream, pws3_file_set_header_field, pws3_file_get_header_field, pws3_file_remove_header_field, pws3_file_insert_empty_group, pws3_file_get_empty_group, pws3_file_remove_empty_group, pws3_file_first_empty_group, pws3_file_last_empty_group, pws3_file_next_empty_group, pws3_file_prev_empty_group, pws3_file_insert_record, pws3_file_get_record, pws3_file_remove_record, pws3_file_first_record, pws3_file_last_record, pws3_file_next_record, pws3_file_prev_record, pws3_field_create, pws3_field_destroy, pws3_field_is_header, pws3_field_get_type, pws3_field_get_data_type, pws3_field_set_uuid, pws3_field_set_text, pws3_field_set_time, pws3_field_set_uint8, pws3_field_set_uint16, pws3_field_set_uint32, pws3_field_set_bytes, pws3_field_get_uuid, pws3_field_get_text, pws3_field_get_time, pws3_field_get_uint8, pws3_field_get_uint16, pws3_field_get_uint32, pws3_field_get_bytes, pws3_record_create, pws3_record_destroy, pws3_record_set_field, pws3_record_get_field, pws3_record_remove_field — create and manipulate Password Safe File Version 3 files

Synopsis

cc [ flag ...] file ... -lpws -lnettle [ library ...]

#include <pws.h>
struct pws3_file *pws3_file_create(void); 
 
void pws3_file_destroy(struct pws3_file *pws_file);
 
enum pws_error_code pws3_file_get_error_code(struct pws3_file *pws_file);
 
const char * pws3_file_get_error_message(struct pws3_file *pws_file);
 
int pws3_file_read_mem(struct pws3_file *pws_file,
 const char *password,
 unsigned char *s,
 size_t n);
 
int pws3_file_read_stream(struct pws3_file *pws_file,
 const char *password,
 FILE *fp);
 
int pws3_file_write_mem(struct pws3_file *pws_file,
 const char *password,
 uint32_t n_iter,
 unsigned char **memp,
 size_t *mem_sizep);
 
int pws3_file_write_stream(struct pws3_file *pws_file,
 const char *password,
 uint32_t n_iter);
 
void pws3_file_set_header_field(struct pws3_file *pws_file,
 struct pws3_field *field);
 
struct pws3_field * pws3_file_get_header_field(struct pws3_file *pws_file,
 uint8_t field_type);
 
struct pws3_field * pws3_file_remove_header_field(struct pws3_file *pws_file,
 uint8_t field_type);
 
void pws3_file_insert_empty_group(struct pws3_file *pws_file,
 struct pws3_field *field);
 
struct pws3_field * pws3_file_get_empty_group(struct pws3_file *pws_file,
 const char *group_name);
 
struct pws3_field * pws3_file_remove_empty_group(struct pws3_file *pws_file,
 const char *group_name);
 
struct pws3_field * pws3_file_first_empty_group(struct pws3_file *pws_file);
 
struct pws3_field * pws3_file_last_empty_group(struct pws3_file *pws_file);
 
struct pws3_field * pws3_file_next_empty_group(struct pws3_file *pws_file,
 struct pws3_field *field);
 
struct pws3_field * pws3_file_prev_empty_group(struct pws3_file *pws_file,
 struct pws3_field *field);
 
void pws3_file_insert_record(struct pws3_file *pws_file,
 struct pws3_record *record);
 
struct pws3_record * pws3_file_get_record(struct pws3_file *pws_file,
 const unsigned char uuid[static PWS3_UUID_SIZE]);
 
struct pws3_record * pws3_file_remove_record(struct pws3_file *pws_file,
 const unsigned char uuid[static PWS3_UUID_SIZE]);
 
struct pws3_record * pws3_file_first_record(struct pws3_file *pws_file);
 
struct pws3_record * pws3_file_last_record(struct pws3_file *pws_file);
 
struct pws3_record * pws3_file_next_record(struct pws3_file *pws_file,
 struct pws3_record *record);
 
struct pws3_record * pws3_file_prev_record(struct pws3_file *pws_file,
 struct pws3_record *record);
 
struct pws3_field * pws3_field_create(int is_header,
 uint8_t field_type);
 
void pws3_field_destroy(struct pws3_field *field);
 
int pws3_field_is_header(struct pws3_field *field);
 
uint8_t * pws3_field_get_type(struct pws3_field *field);
 
enum pws_data_type * pws3_field_get_data_type(struct pws3_field *field);
 
int pws3_field_set_uuid(struct pws3_field *field,
 const unsigned char uuid[static PWS3_UUID_SIZE]);
 
int pws3_field_set_text(struct pws3_field *field,
 const char s[static 1]);
 
int pws3_field_set_time(struct pws3_field *field,
 time_t time);
 
int pws3_field_set_uint8(struct pws3_field *field,
 uint8_t u8);
 
int pws3_field_set_uint16(struct pws3_field *field,
 uint16_t u16);
 
int pws3_field_set_uint32(struct pws3_field *field,
 uint32_t u32);
 
int pws3_field_set_bytes(struct pws3_field *field,
 const unsigned char s[static 1],
 size_t n);
 
const unsigned char * pws3_field_get_uuid(struct pws3_field *field);
 
const char * pws3_field_get_text(struct pws3_field *field);
 
time_t pws3_field_get_time(struct pws3_field *field);
 
uint8_t pws3_field_get_uint8(struct pws3_field *field);
 
uint16_t pws3_field_get_uint16(struct pws3_field *field);
 
uint32_t pws3_field_get_uint32(struct pws3_field *field);
 
void pws3_field_get_bytes(struct pws3_field *field,
 const unsigned char **pp,
 size_t *np);
 
PWS3_VERSION

PWS3_MAX_FIELD_LEN

PWS3_MAX_PASSWORD_LEN

PWS3_UUID_SIZE

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;

Description

Introduction

The pws3_*() 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.

A header or record field value can be of one of seven basic data types defined below:

Table 1. Header and Record Field Value Data Types
Data TypeC TypeDescription
PWS_DATA_TYPE_UUIDunsigned char [PWS3_UUID_SIZE]UUID
PWS_DATA_TYPE_TEXTchar *NUL-delimited UTF-8 encoded string
PWS_DATA_TYPE_TIMEtime_tsystem-specific representation of time
PWS_DATA_TYPE_UINT8uint8_t8-bit wide unsigned integer
PWS_DATA_TYPE_UINT16uint16_t16-bit wide unsigned integer
PWS_DATA_TYPE_UINT32uint32_t32-bit wide unsigned integer
PWS_DATA_TYPE_BYTESunsigned char *array of bytes


The data type of each header field is defined in Table 2, “Header Fields” and the data type of each record field is defined in Table 3, “Record Fields”. Each header field, with the exception of the empty groups header field, can only occur once. The version header field (PWS3_HEADER_FIELD_VERSION) 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 libpws(3). The supported version is defined by the PWS3_VERSION 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 PWS_DATA_TYPE_BYTES data type. All strings are expected to be in UTF-8 encoding.

The only mandatory record field is the UUID field which uniquely identifies a record in the file.

The complete and authoritative specification of the file format is included with the original Password Safe application available from https://pwsafe.org/.

Password Safe File Data Structure

The pws3_file_create() 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 PWS3_VERSION macro.

The pws3_file_destroy() function deallocates all header fields and records of the file structure passed to it and then deallocates the file structure itself.

The pws3_file_read_mem() and pws3_file_read_stream() functions read and parse a Password Safe file into the given data structure passed via the pws_file argument, replacing any existing header fields and records. The key used to decrypt the file is derived from the given password parameter. The pws3_file_read_mem() function reads the file from a block of memory s with the size of n bytes. The pws3_file_read_stream() reads the file from the stream of the fp file pointer.

The pws3_file_write_mem() and pws3_file_write_stream() functions write a new Password Safe file from the given datat structure. The key used to encrypt the file is derived from the password argument using the number of iterations to stretch the key determined by the n_iter argument. The pws3_file_write_mem() will allocate and place the file contents into memory and return the location and size to the locations sp and np point to. The pws3_file_write_stream() will write the file contents to the stream of the fp file pointer.

Fields

Both header and record fields are stored in pws3_field structures which are allocated and initialized with the pws3_field_create() function. Depending on whether is_header is non-zero either a header field or a record field data structure of the given field type will be created.

The pws3_field_destroy() function deallocates the given field data structure and its content.

The pws3_field_is_header() function can be used to test whether the given field data structure refers to a header field or a record field.

The pws3_field_get_type() function returns the field type of the given field data structure.

The pws3_field_get_data_type() function returns the data type of the given field structure.

The pws3_field_set_uuid(), pws3_field_set_text(), pws3_field_set_time(), pws3_field_set_uint8(), pws3_field_set_uint16(), pws3_field_set_uint32(), and pws3_field_set_bytes() 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 Table 2, “Header Fields” in case of header fields or that in Table 3, “Record Fields” in case of record fields.

The pws3_field_get_time(), pws3_field_get_uint8(), pws3_field_get_uint16(), and pws3_field_get_uint32() functions return the value of the given field. The pws3_field_get_uuid(), pws3_field_get_text(), and pws3_field_get_bytes() 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 Table 2, “Header Fields” in case of header fields and that in Table 3, “Record Fields” in case of record fields. Returned pointers are only valid until a field is modified or deallocated.

Header Fields

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 2. Header Fields
Header Field TypeNumeric ValueData TypeDescription
PWS3_​HEADER_​FIELD_​VERSION0x00PWS_​DATA_​TYPE_​UINT16file format version
PWS3_​HEADER_​FIELD_​UUID0x01PWS_​DATA_​TYPE_​UUIDUUID
PWS3_​HEADER_​FIELD_​NON_​DEFAULT_​PREFERENCES0x02PWS_​DATA_​TYPE_​TEXTnon-default preferences
PWS3_​HEADER_​FIELD_​TREE_​DISPLAY_​STATUS0x03PWS_​DATA_​TYPE_​TEXTexpandended/​collapsed state of the tree of groups
PWS3_​HEADER_​FIELD_​SAVE_​TIMESTAMP0x04PWS_​DATA_​TYPE_​TIMEtime when the file was last saved
PWS3_​HEADER_​FIELD_​SAVE_​USER_​HOST0x05PWS_​DATA_​TYPE_​TEXTname of the user who last saved the file and name of the host where the file was saved
PWS3_​HEADER_​FIELD_​SAVE_​APPLICATION0x06PWS_​DATA_​TYPE_​TEXTname of the application used to save the file
PWS3_​HEADER_​FIELD_​SAVE_​USER0x07PWS_​DATA_​TYPE_​TEXTname of the user who last saved the file
PWS3_​HEADER_​FIELD_​SAVE_​HOST0x08PWS_​DATA_​TYPE_​TEXTname of the host where the file was last saved
PWS3_​HEADER_​FIELD_​DATABASE_​NAME0x09PWS_​DATA_​TYPE_​TEXTlogical name for referring to the file
PWS3_​HEADER_​FIELD_​DATABASE_​DESCRIPTION0x0aPWS_​DATA_​TYPE_​TEXTdescription of the file
PWS3_​HEADER_​FIELD_​DATABASE_​FILTERS0x0bPWS_​DATA_​TYPE_​TEXTfilters for this file
PWS3_​HEADER_​FIELD_​RESERVED_​10x0cPWS_​DATA_​TYPE_​BYTESreserved
PWS3_​HEADER_​FIELD_​RESERVED_​20x0dPWS_​DATA_​TYPE_​BYTESreserved
PWS3_​HEADER_​FIELD_​RESERVED_​30x0ePWS_​DATA_​TYPE_​BYTESreseved
PWS3_​HEADER_​FIELD_​RECENTLY_​USED_​ENTRIES0x0fPWS_​DATA_​TYPE_​TEXTlist of recently used entries
PWS3_​HEADER_​FIELD_​NAMED_​PASSWORD_​POLICIES0x10PWS_​DATA_​TYPE_​TEXTnamed password policies
PWS3_​HEADER_​FIELD_​EMPTY_​GROUPS0x11PWS_​DATA_​TYPE_​TEXTempty groups which contain no entries
PWS3_​HEADER_​FIELD_​YUBICO0x12PWS_​DATA_​TYPE_​TEXTreserved
PWS3_​HEADER_​FIELD_​PASSWORD_​TIMESTAMP0x13PWS_​DATA_​TYPE_​TIMEtime the master password was last changed


The pws3_file_set_header_field() 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 PWS3_HEADER_FIELD_EMPTY_GROUPS for which pws3_file_set_header_field() has the same effect as calling the pws3_file_insert_empty_group() function.

The pws3_file_get_header_field() function returns a pointer to the header field data structure of the given header field type. In case of the PWS3_HEADER_FIELD_EMPTY_GROUPS field type a pointer to the first empty group field is returned.

The pws3_file_remove_header_field() 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 PWS3_HEADER_FIELD_EMPTY_GROUPS field type the first empty group is removed.

The pws3_file_insert_empty_group() function inserts the given empty groups field into the file, an existing field for a group of the same name is replaced.

The pws3_file_get_empty_group() function returns a pointer to the header field datat structure representing an empty group of the given name.

The pws3_file_remove_empty_group() 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.

The pws3_file_first_empty_group() function returns a pointer to the first empty group header field.

The pws3_file_last_empty_group() function returns a pointer to the last empty group header field.

The pws3_file_next_empty_group() function returns a pointer to the next empty group header filed data structure following the given field.

The pws3_file_prev_empty_groupious() function returns a pointer to the previous empty group header filed data structure preceding the given field.

Records

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 3. Record Fields
Record Field TypeNumeric ValueData TypeDescription
PWS3_​RECORD_​FIELD_​UUID0x01PWS_​DATA_​TYPE_​UUIDUUID identifying the record
PWS3_​RECORD_​FIELD_​GROUP0x02PWS_​DATA_​TYPE_​TEXTgroup name the record is a member of
PWS3_​RECORD_​FIELD_​TITLE0x03PWS_​DATA_​TYPE_​TEXTtitle
PWS3_​RECORD_​FIELD_​USERNAME0x04PWS_​DATA_​TYPE_​TEXTusername
PWS3_​RECORD_​FIELD_​NOTES0x05PWS_​DATA_​TYPE_​TEXTnotes
PWS3_​RECORD_​FIELD_​PASSWORD0x06PWS_​DATA_​TYPE_​TEXTpassword
PWS3_​RECORD_​FIELD_​CREATION_​TIME0x07PWS_​DATA_​TYPE_​TIMEtime when the record was created
PWS3_​RECORD_​FIELD_​PASSWORD_​MODIFICATION_​TIME0x08PWS_​DATA_​TYPE_​TIMEtime when the password was last modified
PWS3_​RECORD_​FIELD_​ACCESS_​TIME0x09PWS_​DATA_​TYPE_​TIMEtime when the record was last accessed
PWS3_​RECORD_​FIELD_​PASSWORD_​EXPIRY_​TIME0x0aPWS_​DATA_​TYPE_​TIMEtime when the password expires
PWS3_​RECORD_​FIELD_​RESERVED_​10x0bPWS_​DATA_​TYPE_​BYTESreserved
PWS3_​RECORD_​FIELD_​MODIFICATION_​TIME0x0cPWS_​DATA_​TYPE_​TIMEtime at whcih the record was last modified
PWS3_​RECORD_​FIELD_​URL0x0dPWS_​DATA_​TYPE_​TEXTURL
PWS3_​RECORD_​FIELD_​AUTOTYPE0x0ePWS_​DATA_​TYPE_​TEXTtext to be typed when using the autotype feature
PWS3_​RECORD_​FIELD_​PASSWORD_​HISTORY0x0fPWS_​DATA_​TYPE_​TEXTcreation time and values of previously used passwords
PWS3_​RECORD_​FIELD_​PASSWORD_​POLICY0x10PWS_​DATA_​TYPE_​TEXTpassword policy
PWS3_​RECORD_​FIELD_​PASSWORD_​EXPIRY_​INTERVAL0x11PWS_​DATA_​TYPE_​UINT32days until the password expires
PWS3_​RECORD_​FIELD_​RUN_​COMMAND0x12PWS_​DATA_​TYPE_​TEXTcommand
PWS3_​RECORD_​FIELD_​DOUBLE_​CLICK_​ACTION0x13PWS_​DATA_​TYPE_​BYTESaction on double clicking
PWS3_​RECORD_​FIELD_​EMAIL_​ADDRESS0x14PWS_​DATA_​TYPE_​TEXTemail address
PWS3_​RECORD_​FIELD_​PROTECTED0x15PWS_​DATA_​TYPE_​UINT8flag whether the record is protected from modification
PWS3_​RECORD_​FIELD_​ALLOWED_​PASSWORD_​SYMBOLS0x16PWS_​DATA_​TYPE_​TEXTallowed symbols for generating passwords
PWS3_​RECORD_​FIELD_​SHIFT_​DOUBLE_​CLICK_​ACTION0x17PWS_​DATA_​TYPE_​BYTESaction on pressing shift and double clicking
PWS3_​RECORD_​FIELD_​PASSWORD_​POLICY_​NAME0x18PWS_​DATA_​TYPE_​TEXTname of password policy saved in the header
PWS3_​RECORD_​FIELD_​KEYBOARD_​SHORTCUT0x19PWS_​DATA_​TYPE_​BYTESkeyboard shortcut
PWS3_​RECORD_​FIELD_​RESERVED_​20x1aPWS_​DATA_​TYPE_​UUIDreserved
PWS3_​RECORD_​FIELD_​TWO_​FACTOR_​KEY0x1bPWS_​DATA_​TYPE_​BYTEStwo factor key
PWS3_​RECORD_​FIELD_​CREDIT_​CARD_​NUMBER0x1cPWS_​DATA_​TYPE_​TEXTcredit card number
PWS3_​RECORD_​FIELD_​CREDIT_​CARD_​EXPIRATION0x1dPWS_​DATA_​TYPE_​TEXTcredit card expiration
PWS3_​RECORD_​FIELD_​CREDIT_​CARD_​VERIFICATION_​VALUE0x1ePWS_​DATA_​TYPE_​TEXTcredit card verification value
PWS3_​RECORD_​FIELD_​CREDIT_​CARD_​PIN0x1fPWS_​DATA_​TYPE_​TEXTcredit card PIN
PWS3_​RECORD_​FIELD_​QR_​CODE0x20PWS_​DATA_​TYPE_​TEXTQR code
PWS3_​RECORD_​FIELD_​TESTING_​10xdfPWS_​DATA_​TYPE_​BYTEStesting


The pws3_record_create() function allocates and creates a record data structure, generates an UUID record field and adds it to the record.

The pws3_record_destroy() function deallocates the given record data structure and all its record fields.

The pws3_file_record_field_set() function sets the record field on the given record, replacing an existing field of the same type.

The pws3_file_record_field_get() function returns a pointer to the record field data structure of the given record field type.

The pws3_file_record_field_remove() 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.

The pws3_file_insert_record() function inserts the given record into the file, an existing record with the same UUID is replaced.

The pws3_file_get_record() function returns a pointer to the record structure representing a record with the given UUID.

The pws3_file_remove_record() 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.

The pws3_file_first_record() function returns a pointer to the first record.

The pws3_file_last_record() function returns a pointer to the last record.

The pws3_file_next_record() function returns a pointer to the next record following the given record.

The pws3_file_prev_record() function returns a pointer to the previous group preceding the given record.

Macros

The macro PWS3_VERSION contains the supported version of the Password Safe version 3 file format.

The macro PWS3_MAX_FIELD_SIZE contains the maxium size for header and record fields in bytes and PWS3_MAX_PASSWORD_LEN contains the maxium password length in bytes.

The macro PWS3_UUID_SIZE contains the size of UUIDs in bytes.

Return Values

The pws3_file_create() function returns a pointer to a Password Safe file data structure if successful and NULL in case of an error.

The pws3_file_read_mem(), pws3_file_read_stream(), pws3_file_write_mem(), and pws3_file_write_stream() functions return 0 on success and -1 to indicate an error.

The pws3_file_get_header_field() function returns a pointer to the header field data structure of the requested type and NULL if such a field does not exist.

The pws3_file_remove_header_field() function returns a pointer to the header field data structure which was removed from the file or NULL if such a field does not exist.

The pws3_file_get_empty_group() function returns a pointer to the header field data structure corresponding to the requested empty group and NULL if a group of that name does not exist.

The pws3_file_remove_empty_group() function returns a pointer to the header field data structure of the empty group which was removed from the file or NULL if a group of that name does not exist.

The pws3_file_first_empty_group() function returns a pointer to the first of the empty group header fields or NULL if there are no such fields.

The pws3_file_last_empty_group() function returns a pointer to the last of the empty group header fields or NULL if there are no such fields.

The pws3_file_next_empty_group() function returns a pointer to the next empty group header field or NULL if there are no more such fields.

The pws3_file_prev_empty_group() function returns a pointer to the previous empty group header field or NULL if there are no more such fields.

The pws3_file_get_record() function returns a pointer to the record data structure of the requested record or NULL if that record does not exist.

The pws3_file_remove_record() function returns a pointer to the record data structure which was removed from the file or NULL if no such record exists.

The pws3_file_first_record() function returns a pointer to the record data structure of the first record or NULL if no records exist.

The pws3_file_last_record() function returns a pointer to the record data structure of the last record or NULL if no records exist.

The pws3_file_next_record() function returns a pointer to the record data structure of the next record or NULL if no records exist.

The pws3_file_prev_record() function returns a pointer to the record data structure of the previous record or NULL if no records exist.

The pws3_field_create() function returns a pointer to the new header field data structure on success and NULL on failure.

The pws3_field_get_type() function returns the field type of the header field structure.

The pws3_field_get_data_type() function returns the data type of the header field structure.

The pws3_field_set_uuid(), pws3_field_set_text(), pws3_field_set_time(), pws3_field_set_uint8(), pws3_field_set_uint16(), pws3_field_set_uint32(), and pws3_field_set_bytes() functions return 0 on success and -1 on failure.

The pws3_field_get_time(), pws3_field_get_uint8(), pws3_field_get_uint16(), and pws3_field_get_uint32() functions return a value of the type corresponding to the type of header field.

The pws3_field_get_uuid() function returns a pointer to a UUID.

The pws3_field_get_text() function returns a pointer to a string or NULL if no value has been set.

The pws3_record_create() function returns a pointer to a record data structure if successful and NULL on failure.

The pws3_record_get_field() function returns a pointer to the record field data structure of the requested type or NULL if such a field does not exist.

The pws3_record_remove_field() function returns a pointer to the record field data structure which was removed from the record or NULL if such a field does not exist.

Errors

If the pws3_file_read_mem(), pws3_file_read_stream(), pws3_file_write_mem(), and pws3_file_write_stream() functions fail, an error code indicating the nature of the error may be obtained using the pws3_file_get_error_code() function and a pointer to a detailed error message may be retrieved using the pws3_file_get_error_message() function. The above functions may fail if:

PWS_ERR_GENERIC_ERROR

An unknown error occurred.

PWS_ERR_NO_MEMORY

There was not enough space to allocate memory.

PWS_ERR_IO_ERROR

An I/O error occurred.

PWS_ERR_TRUNCATED_FILE

The file appears to be truncated.

PWS_ERR_INVALID_CHECKSUM

The calculated checksum does not match the checksum of the file.

PWS_ERR_INVALID_RECORD

A record is invalid.

PWS_ERR_INVALID_HEADER

A header is invalid.

PWS_ERR_UNSUPPORTED_VERSION

The file format version is not supported.

Examples

Example 1. Creating a Password Safe file

The following code creates a new Password Safe file and sets the save application header field:


#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);


Example 2. Print the title of each record

The following code loops over each record of an existing Password Safe file and prints the content of the title field if it exists:


#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");
}


Example 3. Add a new record to a file

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:


#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);


Example 4. Reading a Password Safe file

The following code opens a Password Safe file named example.pwsafe3 and parses it:


#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 */
}


Example 5. Writing a Password Safe file

The following code writes a Password Safe file to a file named example.pwsafe3:


#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);


See Also

libpws(3), pws_init(3), https://pwsafe.org/