diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 11 | ||||
-rw-r--r-- | src/vf_access.c | 661 | ||||
-rw-r--r-- | src/vf_access_calendar.c | 528 | ||||
-rw-r--r-- | src/vf_access_wrappers.c | 541 | ||||
-rw-r--r-- | src/vf_config.h | 85 | ||||
-rw-r--r-- | src/vf_create_object.c | 158 | ||||
-rw-r--r-- | src/vf_delete.c | 327 | ||||
-rw-r--r-- | src/vf_internals.h | 223 | ||||
-rw-r--r-- | src/vf_malloc.c | 270 | ||||
-rw-r--r-- | src/vf_malloc.h | 166 | ||||
-rw-r--r-- | src/vf_malloc_stdlib.c | 392 | ||||
-rw-r--r-- | src/vf_malloc_stdlib.h | 90 | ||||
-rw-r--r-- | src/vf_modified.c | 159 | ||||
-rw-r--r-- | src/vf_modified.h | 84 | ||||
-rw-r--r-- | src/vf_parser.c | 1182 | ||||
-rw-r--r-- | src/vf_reader.c | 277 | ||||
-rw-r--r-- | src/vf_search.c | 457 | ||||
-rw-r--r-- | src/vf_string_arrays.c | 435 | ||||
-rw-r--r-- | src/vf_string_arrays.h | 177 | ||||
-rw-r--r-- | src/vf_strings.c | 472 | ||||
-rw-r--r-- | src/vf_strings.h | 230 | ||||
-rw-r--r-- | src/vf_writer.c | 616 |
22 files changed, 7541 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..19b2d85 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,11 @@ +lib_LTLIBRARIES = libvformat.la + +libvformat_la_SOURCES = vf_access.c vf_malloc.c vf_strings.c vf_access_wrappers.c \ + vf_parser.c vf_writer.c vf_create_object.c \ + vf_access_calendar.c vf_reader.c vf_delete.c \ + vf_search.c vf_malloc_stdlib.c vf_modified.c vf_string_arrays.c + +EXTRA_DIST = *.h + +libvformat_la_LDFLAGS = -version-info 0 + diff --git a/src/vf_access.c b/src/vf_access.c new file mode 100644 index 0000000..7504150 --- /dev/null +++ b/src/vf_access.c @@ -0,0 +1,661 @@ +/**************************************************************************** + + (C) Nick Marley, 2001 - + + This software is distributed under the GNU Lesser General Public Licence. + Please read and understand the comments at the top of vf_iface.h before use! + +FILE + $Revision: 1.23 $ + $Author: tilda $ + +ORIGINAL AUTHOR + Nick Marley + +DESCRIPTION + Core access functions for VF_OBJECT_Ts. The library includes other access + functions (see vf_access_wrappers.c) which are often just alternative slightly + higher level versions of what's found below. + + The intention is to provide a basic interface which covers all the required + functionality and also some quick'n'easy functions which can be used but don't + bloat the code (in a static library build anyway). + +REFERENCES + (none) + +MODIFICATION HISTORY + * $Log: vf_access.c,v $ + * Revision 1.23 2002/11/03 18:43:16 tilda + * IID619851 - Update and check headers and function prototypes. + * + * Revision 1.22 2002/11/02 18:29:26 tilda + * IID485157 - UI does character conversion based on CHARSET property. + * + * Revision 1.21 2002/11/02 08:56:17 tilda + * Start of internationalisation changes. + * + * Revision 1.20 2002/10/26 16:09:24 tilda + * IID629125 - Ensure string functions used are portable. + * + * Revision 1.19 2002/10/08 21:45:06 tilda + * IID620473 - reduce c-runtime dependencies. + * + * Revision 1.18 2002/10/08 21:11:36 tilda + * Remove common.h. + * + * Revision 1.17 2002/02/24 17:10:34 tilda + * Add API for "is modified" functionality. + * + * Revision 1.16 2002/01/06 16:18:48 tilda + * Add dialog box for events / todos. + * + * Revision 1.15 2001/11/18 21:45:58 tilda + * Ensure parameters changed to QP are updated correctly. + * + * Revision 1.14 2001/11/17 17:40:29 tilda + * Image / sound dialog box now works. + * + * Revision 1.13 2001/11/05 21:07:20 tilda + * Various changes for initial version of vfedit. + * + * Revision 1.12 2001/10/24 18:36:06 tilda + * BASE64 bugfixes. Split reader/writer code. Start create/modify work. + * + * Revision 1.11 2001/10/24 05:30:39 tilda + * Start work on object create/modify API. + * + * Revision 1.10 2001/10/16 05:50:53 tilda + * Debug support for lists of vobjects from single file (ie. a phonebook). + * + * Revision 1.9 2001/10/14 20:42:37 tilda + * Addition of group searching. + * + * Revision 1.8 2001/10/14 16:40:05 tilda + * Initial testing of access functions. + * + * Revision 1.7 2001/10/13 16:22:08 tilda + * Introduce VBINDATA_T and VOBJDATA_T to tidy up internals. + * + * Revision 1.6 2001/10/13 14:58:56 tilda + * Tidy up version headers, add vf_strings.h where needed. + * + * Revision 1.5 2001/10/13 14:49:30 tilda + * Add string array code to unify handling of names / values. + * + * Revision 1.4 2001/10/12 16:20:03 tilda + * Correctly parse compound quoted printable properties. + * + * Revision 1.3 2001/10/10 20:53:56 tilda + * Various minor tidy ups. + * + * Revision 1.2 2001/10/09 22:01:59 tilda + * Remove older version control comments. + * + *****************************************************************************/ + +#ifndef NORCSID +static const char vf_access_c_vss_id[] = "$Header: /cvsroot/vformat/src/vformat/src/vf_access.c,v 1.23 2002/11/03 18:43:16 tilda Exp $"; +#endif + +/*============================================================================* + ANSI C & System-wide Header Files + *============================================================================*/ + +#include <common/types.h> + +/*===========================================================================* + Interface Header Files + *===========================================================================*/ + +#include "vformat/vf_iface.h" + +/*===========================================================================* + Local Header File + *===========================================================================*/ + +#include "vf_config.h" +#include "vf_malloc.h" +#include "vf_internals.h" +#include "vf_strings.h" +#include "vf_string_arrays.h" +#include "vf_modified.h" + +/*===========================================================================* + Public Data + *===========================================================================*/ +/* None */ + +/*===========================================================================* + Private Defines + *===========================================================================*/ + +#define MAXINCREMENT (5) +#define MAXNUMTAGS (10) + +/*===========================================================================* + Private Data Types + *===========================================================================*/ +/* None */ + +/*===========================================================================* + Private Function Prototypes + *===========================================================================*/ + +static bool_t strings_valid_index( + VPROP_T *p_vprop, /* The property */ + uint32_t n_string /* Index required */ + ); + +static bool_t ensure_value_encoding_tag( + VPROP_T *p_vprop, /* The property */ + vf_encoding_t encoding /* Encoding required */ + ); + +static bool_t set_prop_value_string( + VPROP_T *p_vprop, /* The property */ + uint32_t n_string, /* Index required */ + const char *p_string /* String required */ + ); + +static bool_t set_prop_value_base64( + VPROP_T *p_vprop, /* The property */ + const uint8_t *p_data, /* Pointer to the binary data */ + uint32_t length, /* Length of the binary data */ + bool_t copy /* Copy or keep pointer */ + ); + + + + +/*===========================================================================* + Private Data + *===========================================================================*/ +/* None */ + +/*===========================================================================* + Public Function Implementations + *===========================================================================*/ + + +/*---------------------------------------------------------------------------* + * NAME + * vf_get_prop_name() + * + * DESCRIPTION + * Build the property name string in the indicated buffer. + * + * RETURNS + * (none) + *---------------------------------------------------------------------------*/ + +void vf_get_prop_name( + VF_PROP_T *p_prop, /* The property */ + char *p_buffer, /* The buffer */ + uint32_t bufsize /* Size of the buffer */ + ) +{ + VPROP_T *p_vprop = (VPROP_T *)p_prop; + uint32_t i; + + if (p_vprop->p_group) + { + p_strcpy(p_buffer, p_vprop->p_group); + p_strcat(p_buffer, "."); + } + else + { + p_buffer[0] = '\0'; + } + + for (i = 0;i < p_vprop->name.n_strings;i++) + { + if (0 < i) + p_strcat(p_buffer, ";"); + + if (p_vprop->name.pp_strings[i]) + { + p_strcat(p_buffer, p_vprop->name.pp_strings[i]); + } + } +} + + + +/*---------------------------------------------------------------------------* + * NAME + * vf_get_object_type() + * + * DESCRIPTION + * Return the type string identifying the indicated vformat object. + * + * RETURNS + * Ptr to string. + *---------------------------------------------------------------------------*/ + +const char *vf_get_object_type( + VF_OBJECT_T *p_object + ) +{ + const char *p_ret = NULL; + + if (p_object) + { + p_ret = ((VOBJECT_T *)p_object)->p_type; + } + + return p_ret; +} + + + + + + +/*---------------------------------------------------------------------------* + * NAME + * vf_get_prop_value() + * + * DESCRIPTION + * Get hold of raw fields associated with the property. These are of + * various types: + * + * VF_ENC_VOBJECT + * - *pp_value = pointer to contained VF_OBJECT_T which can be + * passed back to any of the object manipulation functions. + * + * VF_ENC_7BIT, VF_ENC_QUOTEDPRINTABLE + * - *pp_value = ptr to array of char*, *p_size = number of elts. + * + * VF_ENC_8BIT, VF_BASE64 + * - *pp_value = ptr to bytes, *p_size = number of bytes + * + * RETURNS + * TRUE <=> encoding is valid, FALSE else. + *---------------------------------------------------------------------------*/ + +bool_t vf_get_prop_value( + VF_PROP_T *p_prop, /* The property */ + void **pp_value, /* Pointer value */ + uint32_t *p_size, /* Integer value */ + vf_encoding_t *p_encoding /* Type of return values */ + ) +{ + VPROP_T *p_vprop = (VPROP_T *)p_prop; + bool_t ret = TRUE; + + switch (p_vprop->value.encoding) + { + case VF_ENC_VOBJECT: + if (pp_value) + { + *pp_value = p_vprop->value.v.o.p_object; + } + break; + + case VF_ENC_7BIT: + case VF_ENC_QUOTEDPRINTABLE: + if (pp_value) + { + *pp_value = p_vprop->value.v.s.pp_strings; + } + if (p_size) + { + *p_size = p_vprop->value.v.s.n_strings; + } + break; + + case VF_ENC_8BIT: + case VF_ENC_BASE64: + if (pp_value) + { + *pp_value = p_vprop->value.v.b.p_buffer; + } + if (p_size) + { + *p_size = p_vprop->value.v.b.n_bufsize; + } + break; + + default: + ret = FALSE; + break; + } + + if (p_encoding) + { + *p_encoding = p_vprop->value.encoding; + } + + return ret; +} + + + + + + + +/*---------------------------------------------------------------------------* + * NAME + * vf_set_prop_value() + * + * DESCRIPTION + * Set values associated with a property. + * + * Passing a value of encoding not the same as the current property + * encoding will cause the property contents to be freed prior to + * setting the indicated value. + * + * RETURNS + * TRUE <=> re-allocation success & encoding correct, FALSE else. + *---------------------------------------------------------------------------*/ + +bool_t vf_set_prop_value( + VF_PROP_T *p_prop, /* The property */ + void *p_value, /* Pointer to the data */ + uint32_t n_param, /* Data size or index */ + vf_encoding_t encoding, /* Encoding in use */ + bool_t copy /* Copy the data? */ + ) +{ + VPROP_T *p_vprop = (VPROP_T *)p_prop; + bool_t ret = TRUE; + + if (!copy) + return FALSE; + + if (encoding == p_vprop->value.encoding) + { + /* Leave it as is */ + } + else + { + delete_prop_contents(p_prop, FALSE); + + ensure_value_encoding_tag(p_vprop, encoding); + } + + switch (p_vprop->value.encoding) + { + case VF_ENC_VOBJECT: + { + if (p_vprop->value.v.o.p_object != p_value) + { + mark_property_modified(p_vprop, TRUE); + } + + p_vprop->value.v.o.p_object = p_value; + } + break; + + case VF_ENC_7BIT: + case VF_ENC_QUOTEDPRINTABLE: + { + ret = set_prop_value_string(p_vprop, n_param, p_value); + } + break; + + case VF_ENC_8BIT: + case VF_ENC_BASE64: + { + ret = set_prop_value_base64(p_vprop, p_value, n_param, copy); + } + break; + + default: + ret = FALSE; + break; + } + + return ret; +} + + + + + + + +/*===========================================================================* + Private Function Implementations + *===========================================================================*/ + + + + +/*---------------------------------------------------------------------------* + * NAME + * set_prop_value_string() + * + * DESCRIPTION + * Set the value of a property. + * + * RETURNS + * TRUE <=> set successfully. + *---------------------------------------------------------------------------*/ + +bool_t set_prop_value_string( + VPROP_T *p_vprop, + uint32_t n_string, + const char *p_string + ) +{ + bool_t ret = FALSE; + + if (strings_valid_index(p_vprop, n_string)) + { + if ((p_vprop->value.v.s.pp_strings[n_string] && !p_string) || + (!p_vprop->value.v.s.pp_strings[n_string] && p_string) || + (p_vprop->value.v.s.pp_strings[n_string] && p_string && + p_stricmp(p_vprop->value.v.s.pp_strings[n_string], p_string))) + { + mark_property_modified(p_vprop, TRUE); + } + + ret = set_string_array_entry(&(p_vprop->value.v.s), p_string, n_string); + } + + return ret; +} + + + + +/*---------------------------------------------------------------------------* + * NAME + * set_prop_value_base64() + * + * DESCRIPTION + * Set the value of a property. + * + * RETURNS + * TRUE <=> set successfully. + *---------------------------------------------------------------------------*/ + +bool_t set_prop_value_base64( + VPROP_T *p_vprop, + const uint8_t *p_data, /* Pointer to the binary data */ + uint32_t length, /* Length of the binary data */ + bool_t copy /* Copy or keep pointer */ + ) +{ + bool_t ret = FALSE; + + if (copy) + { + p_vprop->value.v.b.p_buffer = vf_malloc(length); + + if (p_vprop->value.v.b.p_buffer) + { + p_memcpy(p_vprop->value.v.b.p_buffer, p_data, length); + p_vprop->value.v.b.n_bufsize = length; + + ret = TRUE; + } + } + else + { + /* TBD */ + } + + return ret; +} + + + + + + + +/*---------------------------------------------------------------------------* + * NAME + * strings_valid_index() + * + * DESCRIPTION + * Check request for indicated string. If it's either in the current + * object or represents a reasonable exapansion the request is allowed. + * + * RETURNS + * TRUE <=> object can include indicated string. + *---------------------------------------------------------------------------*/ + +bool_t strings_valid_index( + VPROP_T *p_vprop, + uint32_t n_string + ) +{ + bool_t ret = FALSE; + + if (n_string < p_vprop->value.v.s.n_strings) + { + /* String in current extent of object */ + + ret = TRUE; + } + else + if ((p_vprop->value.v.s.n_strings <= n_string) && (n_string < p_vprop->value.v.s.n_strings + MAXINCREMENT)) + { + /* Set string within reasonable expansion of object */ + + void *p_tmp = vf_realloc(p_vprop->value.v.s.pp_strings, (1 + n_string) * sizeof(char *)); + + if (p_tmp) + { + uint32_t i; + + p_vprop->value.v.s.pp_strings = p_tmp; + + for (i = p_vprop->value.v.s.n_strings;i < (uint32_t)(1 + n_string);i++) + { + p_vprop->value.v.s.pp_strings[i] = NULL; + } + + p_vprop->value.v.s.n_strings = (1 + n_string); + + ret = TRUE; + } + } + else + { + /* Invalid request */ + } + + return ret; +} + + + + + +/*---------------------------------------------------------------------------* + * NAME + * ensure_value_encoding_tag() + * + * DESCRIPTION + * Check/set encoding. + * + * RETURNS + * TRUE <=> encoding was set successfully. + *---------------------------------------------------------------------------*/ + +bool_t ensure_value_encoding_tag( + VPROP_T *p_vprop, + vf_encoding_t encoding + ) +{ + int n; + uint32_t i; + bool_t ret = TRUE; + + /* + * Locate the encoding value. + */ + for (i = 0, n = (-1);n == (-1) && (i < p_vprop->name.n_strings);i++) + { + const char *p_string = p_vprop->name.pp_strings[i]; + + if (p_string) + { + if (p_stristr(p_string, VFP_ENCODING) + || p_stristr(p_string, VFP_QUOTEDPRINTABLE) + || p_stristr(p_string, VFP_BASE64) + || p_stristr(p_string, VFP_8BIT) + || p_stristr(p_string, VFP_7BIT)) + { + n = i; + } + } + } + + /* + * Remove previous encoding + */ + if (0 <= n) + { + ret = set_string_array_entry(&(p_vprop->name), NULL, n); + } + + if (ret) + { + char *p_enc_string; + + switch (encoding) + { + case VF_ENC_QUOTEDPRINTABLE: + p_enc_string = VFP_QUOTEDPRINTABLE; + break; + + case VF_ENC_BASE64: + p_enc_string = VFP_BASE64; + break; + + default: + p_enc_string = NULL; + } + + if (p_enc_string) + { + if ((-1) == n) + { + ret = add_string_to_array(&(p_vprop->name), p_enc_string); + } + else + { + ret = set_string_array_entry(&(p_vprop->name), p_enc_string, n); + } + } + } + + if (ret) + { + p_vprop->value.encoding = encoding; + } + + return ret; +} + + +/*===========================================================================* + End Of File + *===========================================================================*/ diff --git a/src/vf_access_calendar.c b/src/vf_access_calendar.c new file mode 100644 index 0000000..159c432 --- /dev/null +++ b/src/vf_access_calendar.c @@ -0,0 +1,528 @@ +/**************************************************************************** + + (C) Nick Marley, 2001 - + + This software is distributed under the GNU Lesser General Public Licence. + Please read and understand the comments at the top of vf_iface.h before use! + +FILE + $Workfile: vf_access.c $ + $Revision: 1.7 $ + $Author: tilda $ + +ORIGINAL AUTHOR + Nick Marley + +DESCRIPTION + Wrappers on the core access functions & other utility functions. + +REFERENCES + (none) + +MODIFICATION HISTORY + * $Log: vf_access_calendar.c,v $ + * Revision 1.7 2002/11/24 14:26:22 tilda + * IID484686 - More vcard work. + * + * Revision 1.6 2002/11/15 09:15:00 tilda + * IID638823 - Various portability issues. + * + * Revision 1.5 2002/11/03 18:43:16 tilda + * IID619851 - Update and check headers and function prototypes. + * + * Revision 1.4 2002/10/26 16:09:24 tilda + * IID629125 - Ensure string functions used are portable. + * + * Revision 1.3 2002/10/08 21:45:07 tilda + * IID620473 - reduce c-runtime dependencies. + * + * Revision 1.2 2002/10/08 21:11:36 tilda + * Remove common.h. + * + * Revision 1.1 2002/01/06 16:18:48 tilda + * Add dialog box for events / todos. + * + *****************************************************************************/ + +#ifndef NORCSID +static const char vf_access_calendar_c_vss_id[] = "$Header: /cvsroot/vformat/src/vformat/src/vf_access_calendar.c,v 1.7 2002/11/24 14:26:22 tilda Exp $"; +#endif + +/*============================================================================* + ANSI C & System-wide Header Files + *============================================================================*/ + +#include <common/types.h> + +#include <time.h> +#include <stdio.h> +#include <ctype.h> + +/*===========================================================================* + Interface Header Files + *===========================================================================*/ + +#include "vformat/vf_iface.h" + +/*===========================================================================* + Local Header File + *===========================================================================*/ + +#include "vf_config.h" +#include "vf_malloc.h" +#include "vf_internals.h" +#include "vf_strings.h" +#include "vf_string_arrays.h" + +/*===========================================================================* + Public Data + *===========================================================================*/ +/* None */ + +/*===========================================================================* + Private Defines + *===========================================================================*/ + +#define ISO8061_TOKEN_YEARS 'Y' +#define ISO8061_TOKEN_MONTHS 'M' +#define ISO8061_TOKEN_WEEKS 'W' +#define ISO8061_TOKEN_DAYS 'D' +#define ISO8061_TOKEN_HOURS 'H' +#define ISO8061_TOKEN_MINUTES 'M' +#define ISO8061_TOKEN_SECONDS 'S' + +#define ISO8061_TOKEN_TIME 'T' +#define ISO8061_TOKEN_PERIOD 'P' + +/*===========================================================================* + Private Data Types + *===========================================================================*/ +/* None */ + +/*===========================================================================* + Private Function Prototypes + *===========================================================================*/ + +static void append_iso8061_value(char *p_string, uint32_t value, char symbol); +static void append_iso8061_tag(char *p_string, char symbol); + +/*===========================================================================* + Private Data + *===========================================================================*/ +/* None */ + +/*===========================================================================* + Public Function Implementations + *===========================================================================*/ + + +/*---------------------------------------------------------------------------* + * NAME + * vf_set_prop_value_time() + * + * DESCRIPTION + * Set a time_t value into a VF property. + * + * RETURNS + * TRUE iff property added & set OK. + *---------------------------------------------------------------------------*/ + +bool_t vf_set_prop_value_time( + VF_PROP_T *p_prop, /* The property */ + uint32_t n_string, /* Which string we're encoding to */ + const time_t t_value /* Time value */ + ) +{ + bool_t ret; + struct tm *p_tm; + + p_tm = localtime(&t_value); + + if (p_tm) + { + char value[256]; + + if (p_tm->tm_hour || p_tm->tm_min || p_tm->tm_sec) + { + sprintf(value, "%4d%02d%02dT%02d%02d%02d", + 1900 + p_tm->tm_year, + 1 + p_tm->tm_mon, + p_tm->tm_mday, + p_tm->tm_hour, + p_tm->tm_min, + p_tm->tm_sec); + } + else + { + sprintf(value, "%4d%02d%02d", + 1900 + p_tm->tm_year, + 1 + p_tm->tm_mon, + p_tm->tm_mday); + } + + ret = vf_set_prop_value_string(p_prop, n_string, value); + } + else + { + ret = FALSE; + } + + return ret; +} + + + + + + +/*---------------------------------------------------------------------------* + * NAME + * vf_get_prop_value_time() + * + * DESCRIPTION + * Fetch a time_t value from a VF property. + * + * RETURNS + * TRUE iff foudn & converted OK. + *---------------------------------------------------------------------------*/ + +bool_t vf_get_prop_value_time( + VF_PROP_T *p_prop, /* The property */ + uint32_t n_string, /* Which string we're decoding */ + time_t *p_t_value /* Pointer to output time value */ + ) +{ + bool_t ret; + const char *p_value; + + p_value = vf_get_prop_value_string(p_prop, n_string); + + if (p_value) + { + ret = vf_date_string_to_time(p_t_value, p_value); + } + else + { + ret = FALSE; + } + + return ret; +} + + + + + + + +/*---------------------------------------------------------------------------* + * NAME + * vf_date_string_to_time() + * + * DESCRIPTION + * Convert calendar string to absolute time. The basic formats are + * 19960401, 19960401T073000Z + * + * RETURNS + * TRUE <=> conversion OK, FALSE else. + *---------------------------------------------------------------------------*/ + +bool_t vf_date_string_to_time( + uint32_t *p_time, /* Output time value */ + const char *p_string /* Input string */ + ) +{ + bool_t ret = FALSE; + + if (p_string && p_time) + { + time_t t; + struct tm tm; + + p_memset(&tm, '\0', sizeof(tm)); + + /* + * p_string[8] is either 'T' or '\0' or an error. + */ + + if (ISO8061_TOKEN_TIME == p_string[8]) + { + if (6 == sscanf(p_string, "%4d%2d%2dT%2d%2d%2d", + &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec)) + { + if ((1970 <= tm.tm_year) && + ((1 <= tm.tm_mon) && (tm.tm_mon <= 12)) && + ((1 <= tm.tm_mday) && (tm.tm_mday <= 28)) && + ((0 <= tm.tm_hour) && (tm.tm_hour <= 23)) && + ((0 <= tm.tm_min) && (tm.tm_hour <= 59)) && + ((0 <= tm.tm_sec) && (tm.tm_sec <= 59))) + { + ret = TRUE; + } + } + } + else + if ('\0' == p_string[8]) + { + if (3 == sscanf(p_string, "%4d%2d%2d", + &tm.tm_year, &tm.tm_mon, &tm.tm_mday)) + { + if ((1970 <= tm.tm_year) && + ((1 <= tm.tm_mon) && (tm.tm_mon <= 12)) && + ((1 <= tm.tm_mday) && (tm.tm_mday <= 28))) + { + ret = TRUE; + } + } + } + else + { + /* Nor flesh nor fish nor fowl */ + } + + /* + * Reduce the year value to correct range & convert to time_t. + */ + + if (ret) + { + tm.tm_mon -= 1; + tm.tm_year -= 1900; + tm.tm_isdst = -1; + + t = mktime(&tm); + + if ((-1) == t) + { + ret = FALSE; + } + else + { + *p_time = (uint32_t)t; + } + } + } + + return ret; +} + + + + + + +/*---------------------------------------------------------------------------* + * NAME + * vf_period_string_to_time() + * + * DESCRIPTION + * Convert period definition string to time value. The format is + * P[aaaY][bbbM][cccW][dddD]T[eeeH][fffM][gggS] where 'aaa' is a + * number of years, bbb months etc. + * + * RETURNS + * TRUE <=> conversion OK, FALSE else. + *---------------------------------------------------------------------------*/ + +bool_t vf_period_string_to_time( + VF_ISO8601_PERIOD_T *p_period, /* Output time value */ + const char *p_string /* Input string */ + ) +{ + bool_t ret = TRUE; + bool_t in_time_part = FALSE; + + p_memset(p_period, '\0', sizeof(*p_period)); + + if (p_string && ('P' == p_string[0]) && *(++p_string)) + { + while (ret && *p_string) + { + uint32_t value = 0; + + while (isdigit((int)*p_string)) + { + value = (value * 10) + *(p_string++) - '0'; + } + + switch (*p_string++) + { + case '\0': + { + ret = FALSE; + } + break; + + case ISO8061_TOKEN_YEARS: + { + p_period->years = value; + } + break; + + case ISO8061_TOKEN_MONTHS: + /*case ISO8061_TOKEN_MINUTES:*/ + { + if (in_time_part) + { + p_period->minutes = value; + } + else + { + p_period->months = value; + } + } + break; + + case ISO8061_TOKEN_WEEKS: + { + p_period->weeks = value; + } + break; + + case ISO8061_TOKEN_DAYS: + { + p_period->days = value; + } + break; + + case ISO8061_TOKEN_TIME: + { + if (in_time_part) + { + ret = FALSE; + } + else + { + in_time_part = TRUE; + } + } + break; + + case ISO8061_TOKEN_HOURS: + { + p_period->hours = value; + } + break; + + case ISO8061_TOKEN_SECONDS: + { + p_period->seconds = value; + } + break; + + default: + { + ret = FALSE; + } + break; + } + } + } + else + { + ret = FALSE; + } + + return ret; +} + + + + +/*---------------------------------------------------------------------------* + * NAME + * vf_period_time_to_string() + * + * DESCRIPTION + * Convert a VF_ISO8601_PERIOD_T to a string. + * + * RETURNS + * Number of characters written. + *---------------------------------------------------------------------------*/ + +uint32_t vf_period_time_to_string( + char *p_string, /* Output string */ + const VF_ISO8601_PERIOD_T *p_period /* Input period value */ + ) +{ + uint32_t ret = 0; + + if (p_string && p_period) + { + p_string[0] = '\0'; + + append_iso8061_tag(p_string, ISO8061_TOKEN_PERIOD); + + append_iso8061_value(p_string, p_period->years, ISO8061_TOKEN_YEARS); + append_iso8061_value(p_string, p_period->months, ISO8061_TOKEN_MONTHS); + append_iso8061_value(p_string, p_period->weeks, ISO8061_TOKEN_WEEKS); + append_iso8061_value(p_string, p_period->days, ISO8061_TOKEN_DAYS); + + if (p_period->hours || p_period->minutes || p_period->seconds) + { + append_iso8061_tag(p_string, ISO8061_TOKEN_TIME); + } + + append_iso8061_value(p_string, p_period->hours, ISO8061_TOKEN_HOURS); + append_iso8061_value(p_string, p_period->minutes, ISO8061_TOKEN_MINUTES); + append_iso8061_value(p_string, p_period->seconds, ISO8061_TOKEN_SECONDS); + + ret = p_strlen(p_string); + } + + return ret; +} + + + +/*===========================================================================* + Private Function Implementations + *===========================================================================*/ + + + +/*---------------------------------------------------------------------------* + * NAME + * append_iso8061_value() + * + * DESCRIPTION + * Append xxxY value to the current encoded string. + * + * RETURNS + * (none) + *---------------------------------------------------------------------------*/ + +void append_iso8061_value(char *p_string, uint32_t value, char symbol) +{ + if (value) + { + sprintf(p_string + p_strlen(p_string), "%lu%c", (unsigned long)value, symbol); + } +} + + + + +/*---------------------------------------------------------------------------* + * NAME + * append_iso8061_tag() + * + * DESCRIPTION + * Append indicated character to string. + * + * RETURNS + * (none). + *---------------------------------------------------------------------------*/ + +void append_iso8061_tag(char *p_string, char symbol) +{ + p_string += p_strlen(p_string); + + *p_string++ = symbol; + *p_string++ = '\0'; +} + + +/*===========================================================================* + End Of File + *===========================================================================*/ diff --git a/src/vf_access_wrappers.c b/src/vf_access_wrappers.c new file mode 100644 index 0000000..2eea457 --- /dev/null +++ b/src/vf_access_wrappers.c @@ -0,0 +1,541 @@ +/**************************************************************************** + + (C) Nick Marley, 2001 - + + This software is distributed under the GNU Lesser General Public Licence. + Please read and understand the comments at the top of vf_iface.h before use! + +FILE + $Workfile: vf_access.c $ + $Revision: 1.16 $ + $Author: tilda $ + +ORIGINAL AUTHOR + Nick Marley + +DESCRIPTION + Wrappers on the core access functions & other utility functions. + +REFERENCES + (none) + +MODIFICATION HISTORY + * $Log: vf_access_wrappers.c,v $ + * Revision 1.16 2002/11/16 13:19:10 tilda + * IID639288 - Implement method for adding subobjects. + * + * Revision 1.15 2002/11/03 18:43:16 tilda + * IID619851 - Update and check headers and function prototypes. + * + * Revision 1.14 2002/11/02 18:29:26 tilda + * IID485157 - UI does character conversion based on CHARSET property. + * + * Revision 1.13 2002/10/26 16:09:24 tilda + * IID629125 - Ensure string functions used are portable. + * + * Revision 1.12 2002/10/08 21:45:07 tilda + * IID620473 - reduce c-runtime dependencies. + * + * Revision 1.11 2002/10/08 21:11:36 tilda + * Remove common.h. + * + * Revision 1.10 2001/11/18 22:07:02 tilda + * Ensure empty BASE64 properties get the encoding set correctly. + * + * Revision 1.9 2001/11/18 21:48:18 tilda + * Remove redundant code. + * + * Revision 1.8 2001/11/17 17:40:29 tilda + * Image / sound dialog box now works. + * + * Revision 1.7 2001/11/16 22:34:50 tilda + * New vf_get_property() allows append as well as find, + * + * Revision 1.6 2001/11/15 08:56:06 tilda + * Fix bug in qualifier location code. + * + * Revision 1.5 2001/11/14 22:36:56 tilda + * Add parameter to vf_find_prop_qual_index() + * + * Revision 1.4 2001/11/14 16:05:06 tilda + * Extend capabilities of vf_find_prop_qual_index(). + * + * Revision 1.3 2001/11/06 22:51:05 tilda + * Supporting access functions for image selection / deletion. + * + * Revision 1.2 2001/10/24 18:56:29 tilda + * Tidy headers after import. Fix include path in release build. + * + * Revision 1.1 2001/10/24 18:34:35 tilda + * Initial Version. + * + *****************************************************************************/ + +#ifndef NORCSID +static const char vf_access_wrappers_c_vss_id[] = "$Header: /cvsroot/vformat/src/vformat/src/vf_access_wrappers.c,v 1.16 2002/11/16 13:19:10 tilda Exp $"; +#endif + +/*============================================================================* + ANSI C & System-wide Header Files + *============================================================================*/ + +#include <common/types.h> + +/*===========================================================================* + Interface Header Files + *===========================================================================*/ + +#include "vformat/vf_iface.h" + +/*===========================================================================* + Local Header File + *===========================================================================*/ + +#include "vf_config.h" +#include "vf_malloc.h" +#include "vf_internals.h" +#include "vf_strings.h" +#include "vf_string_arrays.h" + +/*===========================================================================* + Public Data + *===========================================================================*/ +/* None */ + +/*===========================================================================* + Private Defines + *===========================================================================*/ +/* None */ + +/*===========================================================================* + Private Data Types + *===========================================================================*/ +/* None */ + +/*===========================================================================* + Private Function Prototypes + *===========================================================================*/ +/* None */ + +/*===========================================================================* + Private Data + *===========================================================================*/ +/* None */ + +/*===========================================================================* + Public Function Implementations + *===========================================================================*/ + +bool_t vf_prop_belongs_to_object( + VF_PROP_T *p_prop, + VF_OBJECT_T *p_object + ); + + +/*---------------------------------------------------------------------------* + * NAME + * vf_get_prop_value_string() + * + * DESCRIPTION + * Obtain string pointer value from VF_PROP_T. If the array contains + * an entry for the indicated string return it. Return NULL if out of + * range request, ie. n_string=3 for N=0;1;2 + * + * RETURNS + * Pointer to string value if value present, NULL if index too large. + *---------------------------------------------------------------------------*/ + +char *vf_get_prop_value_string( + VF_PROP_T *p_prop, + uint32_t n_string + ) +{ + VPROP_T *p_vprop = (VPROP_T *)p_prop; + char *p_ret = NULL; + + if (p_vprop->value.v.s.pp_strings) + { + if (n_string < p_vprop->value.v.s.n_strings) + { + p_ret = p_vprop->value.v.s.pp_strings[n_string]; + } + } + + return p_ret; +} + + + + + +/*---------------------------------------------------------------------------* + * NAME + * vf_set_prop_value_string() + * + * DESCRIPTION + * Set the value of a property. + * + * RETURNS + * TRUE <=> set successfully. + *---------------------------------------------------------------------------*/ + +bool_t vf_set_prop_value_string( + VF_PROP_T *p_prop, + uint32_t n_string, + const char *p_string + ) +{ + return vf_set_prop_value(p_prop, (char *)p_string, n_string, VF_ENC_7BIT, TRUE); +} + + + + + + + + +/*---------------------------------------------------------------------------* + * NAME + * vf_get_prop_value_base64() + * + * DESCRIPTION + * Obtain data pointer for BASE64 data. + * + * RETURNS + * Pointer to data. + *---------------------------------------------------------------------------*/ + +const uint8_t *vf_get_prop_value_base64( + VF_PROP_T *p_prop, /* Property we're setting a value in */ + uint32_t *p_length /* Length of the binary data */ + ) +{ + const uint8_t *p_return = NULL; + + if (p_prop) + { + VPROP_T *p_vprop = (VPROP_T *)p_prop; + + p_return = p_vprop->value.v.b.p_buffer; + + if (p_length) + { + *p_length = p_vprop->value.v.b.n_bufsize; + } + } + + return p_return; +} + + + + + +/*---------------------------------------------------------------------------* + * NAME + * vf_set_prop_value_base64() + * + * DESCRIPTION + * Set the value of a property. + * + * RETURNS + * TRUE <=> set successfully. + *---------------------------------------------------------------------------*/ + +bool_t vf_set_prop_value_base64( + VF_PROP_T *p_prop, /* Property we're setting a value in */ + const uint8_t *p_data, /* Pointer to the binary data */ + uint32_t length, /* Length of the binary data */ + bool_t copy /* Copy or keep pointer */ + ) +{ + return vf_set_prop_value(p_prop, (char *)p_data, length, VF_ENC_BASE64, copy); +} + + + + + + +/*---------------------------------------------------------------------------* + * NAME + * vf_get_prop_value_object() + * + * DESCRIPTION + * Obtain object pointer value from VF_PROP_T. + * + * RETURNS + * Pointer to vobject value (or NULL if not found). + *---------------------------------------------------------------------------*/ + +VF_OBJECT_T *vf_get_prop_value_object( + VF_PROP_T *p_prop + ) +{ + VPROP_T *p_vprop = (VPROP_T *)p_prop; + + if (VF_ENC_VOBJECT == p_vprop->value.encoding) + { + return (VF_OBJECT_T *)(p_vprop->value.v.o.p_object); + } + + return NULL; +} + + + + + +/*---------------------------------------------------------------------------* + * NAME + * vf_set_prop_value_object() + * + * DESCRIPTION + * Set the value of the indicated property to be a VOBJECT. + * + * RETURNS + * TRUE <=> set successfully. + *---------------------------------------------------------------------------*/ + +bool_t vf_set_prop_value_object( + VF_PROP_T *p_prop, + VF_OBJECT_T *p_object + ) +{ + VPROP_T *p_vprop = (VPROP_T *)p_prop; + bool_t ret = FALSE; + + /* + * Avoid various sillies. + */ + if (p_prop && p_object && !vf_prop_belongs_to_object(p_prop, p_object)) + { + delete_prop_contents(p_prop, FALSE); + + p_vprop->value.v.o.p_object = (VOBJECT_T *)p_object; + p_vprop->value.encoding = VF_ENC_VOBJECT; + } + + return TRUE; +} + + + + + + + + +/*---------------------------------------------------------------------------* + * NAME + * vf_get_prop_name_string() + * + * DESCRIPTION + * Get n'th name string. + * + * RETURNS + * Pointer to string value if value present, NULL if index too large. + *---------------------------------------------------------------------------*/ + +char *vf_get_prop_name_string( + VF_PROP_T *p_prop, + uint32_t n_string + ) +{ + VPROP_T *p_vprop = (VPROP_T *)p_prop; + char *p_ret = NULL; + + if (p_vprop->name.pp_strings) + { + if (n_string < p_vprop->name.n_strings) + { + p_ret = p_vprop->name.pp_strings[n_string]; + } + } + + return p_ret; +} + + + + +/*---------------------------------------------------------------------------* + * NAME + * vf_set_prop_name_string() + * + * DESCRIPTION + * Set n'th name string. + * + * RETURNS + * TRUE iff allocation OK, FALSE else. + *---------------------------------------------------------------------------*/ + +bool_t vf_set_prop_name_string( + VF_PROP_T *p_prop, /* Property we're setting a value in */ + uint32_t n_string, /* Index to string */ + const char *p_string /* Pointer to string */ + ) +{ + VPROP_T *p_vprop; + bool_t ret = FALSE; + + p_vprop = (VPROP_T *)p_prop; + + if (p_vprop) + { + if ((-1) == n_string) + { + ret = add_string_to_array(&p_vprop->name, p_string); + } + else + { + ret = set_string_array_entry(&p_vprop->name, p_string, n_string); + } + } + + return TRUE; +} + + + + + + +/*---------------------------------------------------------------------------* + * NAME + * vf_find_prop_qual_index() + * + * DESCRIPTION + * Locate property qualifier given either an array of possible values + * or a single token that is either present or absent. For example + * if we have a property: + * + * NAME;THIRD;TIME;LUCKY:VALUE1;VALUE2;VALUE3 + * + * Then there are two possible searches. + * + * Firstly we can look for the property qualifier which can take values + * from the array { "FIRST", "SECOND", THIRD" } in which case the array + * is passed as pp_possible_values and the function returns with the + * values *p_found_value_index=2, p_qualifier_index=1 + * + * Secondly we can look for the token with value "TIME" in which case + * p_token is set to "TIME" and the function returns *p_qualifier_index=2. + * + * RETURNS + * TRUE iff found, FALSE else. + *---------------------------------------------------------------------------*/ + +bool_t vf_find_prop_qual_index( + VF_PROP_T *p_prop, /* The property we're querying */ + uint32_t *p_qualifier_index, /* Ptr to output name index */ + uint32_t *p_found_value_index, /* Ptr to output index in array */ + const char **pp_possible_values, /* Array of possible values */ + const char *p_token, /* Token searched for */ + vf_search_flags_t match /* String comparison flags */ + ) +{ + uint32_t n; + bool_t ret; + + VPROP_T *p_vprop = (VPROP_T *)p_prop; + + for (n = 0, ret = FALSE;!ret && (n < p_vprop->name.n_strings);n++) + { + const char *p_string = p_vprop->name.pp_strings[n]; + + if (p_string) + { + if (pp_possible_values) + { + uint32_t i; + + for (i = 0;!ret && pp_possible_values[i];i++) + { + if (0 == p_stricmp(pp_possible_values[i], p_string)) + { + if (p_found_value_index) + *p_found_value_index = i; + if (p_qualifier_index) + *p_qualifier_index = n; + + ret = TRUE; + } + } + } + else + if (p_token) + { + if (0 == p_stricmp(p_token, p_string)) + { + if (p_qualifier_index) + *p_qualifier_index = n; + + ret = TRUE; + } + } + else + { + /*???*/ + } + } + } + + return ret; +} + + + + + + +/*----------------------------------------------------------------------------* + * NAME + * vf_find_charset() + * + * DESCRIPTION + * Locate the charset + * + * RETURNS + * vf_charset_t. + *---------------------------------------------------------------------------*/ + +const char *vf_find_charset( + VF_PROP_T *p_prop + ) +{ + VPROP_T *p_vprop = (VPROP_T *)p_prop; + char *ret; + + if (!string_array_contains_string(&p_vprop->name, &ret, -1, VFP_CHARSET, FALSE)) + { + ret = NULL; + } + else + { + ret += 1 + p_strlen(VFP_CHARSET); + } + + return ret; +} + + + + + +/*===========================================================================* + Private Function Implementations + *===========================================================================*/ + +bool_t vf_prop_belongs_to_object( + VF_PROP_T *p_prop, + VF_OBJECT_T *p_object + ) +{ + return FALSE; +} + +/*===========================================================================* + End Of File + *===========================================================================*/ diff --git a/src/vf_config.h b/src/vf_config.h new file mode 100644 index 0000000..2a4ff8f --- /dev/null +++ b/src/vf_config.h @@ -0,0 +1,85 @@ +/****************************************************************************** + + (C) Nick Marley, 2001 - + + This software is distributed under the GNU Lesser General Public Licence. + Please read and understand the comments at the top of vf_iface.h before use! + +FILE + $Workfile: vf_common.h $ + $Revision: 1.1 $ + $Author: tilda $ + +ORIGINAL AUTHOR + Nick Marley + +DESCRIPTION + Common header file for vformat library. This file is internal to vformat + (ie. changes here don't affect the interface) but contains the definitions + which affect the operation of various components eg. the memory debug. + + This file is #included before all other header files within the library. + +REFERENCES + (none) + +MODIFICATION HISTORY + * $Log: vf_config.h,v $ + * Revision 1.1 2002/10/26 15:57:11 tilda + * Initial Version + * + * + *******************************************************************************/ + +#ifndef _VF_CONFIG_H_ +#define _VF_CONFIG_H_ + +#ifndef NORCSID +static const char vf_config_h_vss_id[] = "$Header: /cvsroot/vformat/src/vformat/src/vf_config.h,v 1.1 2002/10/26 15:57:11 tilda Exp $"; +#endif + +/*=============================================================================* + Public Includes + *============================================================================*/ +/* None */ + +/*=============================================================================* + Public Defines + *============================================================================*/ + +/* + * If building debug version under windows then include the memory debug interface. + */ +#if (defined(WIN) || defined(WIN32)) && defined(_DEBUG) +#if !defined(VFORMAT_MEM_DEBUG) +#define VFORMAT_MEM_DEBUG +#endif +#endif + +/* + * Conditional compiles allowing configuration of various string portability functions. + */ +/* #define HAVE_STRLEN */ +/* #define HAVE_STRCPY */ +/* #define HAVE_STRCMP */ +/* #define HAVE_STRCAT */ +/* #define HAVE_STRSTR */ +/* #define HAVE_STRICMP */ +/* #define HAVE_MEMCPY */ +/* #define HAVE_MEMSET */ + +/*=============================================================================* + Public Types + *============================================================================*/ +/* None */ + +/*=============================================================================* + Public Functions + *============================================================================*/ +/* None */ + +/*=============================================================================* + End of file + *============================================================================*/ + +#endif /*_VF_CONFIG_H_*/ diff --git a/src/vf_create_object.c b/src/vf_create_object.c new file mode 100644 index 0000000..ab540b9 --- /dev/null +++ b/src/vf_create_object.c @@ -0,0 +1,158 @@ +/****************************************************************************** + + (C) Nick Marley, 2001 - + + This software is distributed under the GNU Lesser General Public Licence. + Please read and understand the comments at the top of vf_iface.h before use! + +FILE + $Revision: 1.8 $ + $Author: tilda $ + +ORIGINAL AUTHOR + Nick Marley. + +DESCRIPTION + The vf_create_object() function. + +REFERENCES + (none) + +MODIFICATION HISTORY + * $Log: vf_create_object.c,v $ + * Revision 1.8 2002/11/16 13:19:10 tilda + * IID639288 - Implement method for adding subobjects. + * + * Revision 1.7 2002/11/03 18:43:16 tilda + * IID619851 - Update and check headers and function prototypes. + * + * Revision 1.6 2002/10/29 07:19:20 tilda + * Tidy headers. + * + * Revision 1.5 2002/10/26 16:09:24 tilda + * IID629125 - Ensure string functions used are portable. + * + * Revision 1.4 2002/10/08 21:45:07 tilda + * IID620473 - reduce c-runtime dependencies. + * + * Revision 1.3 2002/10/08 21:11:36 tilda + * Remove common.h. + * + * Revision 1.2 2002/01/06 13:11:55 tilda + * Update header. + * + * Revision 1.1 2002/01/06 13:08:15 tilda + * Change file name from vf_createobject.c + * + *******************************************************************************/ + +#ifndef NORCSID +static const char vf_create_object_c_vss_id[] = "$Header: /cvsroot/vformat/src/vformat/src/vf_create_object.c,v 1.8 2002/11/16 13:19:10 tilda Exp $"; +#endif + +/*============================================================================* + ANSI C & System-wide Header Files + *===========================================================================*/ + +#include <common/types.h> + +/*===========================================================================* + Interface Header Files + *==========================================================================*/ + +#include "vformat/vf_iface.h" + +/*===========================================================================* + Local Header File + *==========================================================================*/ + +#include "vf_config.h" +#include "vf_malloc.h" +#include "vf_internals.h" +#include "vf_strings.h" +#include "vf_string_arrays.h" + +/*===========================================================================* + Public Data + *==========================================================================*/ +/* None */ + +/*===========================================================================* + Private Defines + *==========================================================================*/ +/* None */ + +/*===========================================================================* + Private Data Types + *==========================================================================*/ +/* None */ + +/*===========================================================================* + Private Function Prototypes + *==========================================================================*/ +/* None */ + +/*===========================================================================* + Private Data + *==========================================================================*/ +/* None */ + +/*===========================================================================* + Public Function Implementations + *==========================================================================*/ + + +/*---------------------------------------------------------------------------* + * NAME + * vf_create_object() + * + * DESCRIPTION + * Creates and empty vformat object. + * + * RETURNS + * Ptr to object if created else NULL. + *---------------------------------------------------------------------------*/ + +VF_OBJECT_T *vf_create_object( + const char *p_type, /* Type of object to create */ + VF_OBJECT_T *p_parent /* Parent object if any */ + ) +{ + VOBJECT_T *p_new = NULL; + + if (p_type) + { + p_new = vf_malloc(sizeof(VOBJECT_T)); + + if (p_new) + { + p_memset(p_new, '\0', sizeof(VOBJECT_T)); + + p_new->p_type = vf_malloc(1 + p_strlen(p_type)); + + p_new->p_parent = (VOBJECT_T *)p_parent; + + if (p_new->p_type) + { + p_strcpy(p_new->p_type, p_type); + } + else + { + vf_free(p_new); + p_new = NULL; + } + } + } + + return (VF_OBJECT_T *)p_new; +} + + +/*===========================================================================* + Private Function Implementations + *===========================================================================*/ +/* None */ + +/*===========================================================================* + End Of File + *===========================================================================*/ diff --git a/src/vf_delete.c b/src/vf_delete.c new file mode 100644 index 0000000..d70b8e4 --- /dev/null +++ b/src/vf_delete.c @@ -0,0 +1,327 @@ +/****************************************************************************** + + (C) Nick Marley, 2001 - + + This software is distributed under the GNU Lesser General Public Licence. + Please read and understand the comments at the top of vf_iface.h before use! + +FILE + $Workfile: vf_delete.c $ + $Revision: 1.14 $ + $Author: tilda $ + +ORIGINAL AUTHOR + Nick Marley + +DESCRIPTION + Delete a vformat object. + +REFERENCES + (none) + +MODIFICATION HISTORY + * $Log: vf_delete.c,v $ + * Revision 1.14 2002/11/03 18:43:16 tilda + * IID619851 - Update and check headers and function prototypes. + * + * Revision 1.13 2002/10/26 16:09:24 tilda + * IID629125 - Ensure string functions used are portable. + * + * Revision 1.12 2002/10/08 21:45:07 tilda + * IID620473 - reduce c-runtime dependencies. + * + * Revision 1.11 2002/10/08 21:11:36 tilda + * Remove common.h. + * + * Revision 1.10 2001/11/05 21:07:20 tilda + * Various changes for initial version of vfedit. + * + * Revision 1.9 2001/10/24 18:36:06 tilda + * BASE64 bugfixes. Split reader/writer code. Start create/modify work. + * + * Revision 1.8 2001/10/14 19:53:36 tilda + * Group handling. NO group searching functions. + * + * Revision 1.7 2001/10/13 16:22:08 tilda + * Introduce VBINDATA_T and VOBJDATA_T to tidy up internals. + * + * Revision 1.6 2001/10/13 14:58:56 tilda + * Tidy up version headers, add vf_strings.h where needed. + * + * Revision 1.5 2001/10/13 14:49:30 tilda + * Add string array code to unify handling of names / values. + * + * Revision 1.4 2001/10/12 16:20:03 tilda + * Correctly parse compound quoted printable properties. + * + * Revision 1.3 2001/10/10 20:53:56 tilda + * Various minor tidy ups. + * + * Revision 1.2 2001/10/09 22:01:59 tilda + * Remove older version control comments. + * + *******************************************************************************/ + +#ifndef NORCSID +static const char vf_delete_c_vss_id[] = "$Header: /cvsroot/vformat/src/vformat/src/vf_delete.c,v 1.14 2002/11/03 18:43:16 tilda Exp $"; +#endif + +/*=============================================================================* + ANSI C & System-wide Header Files + *=============================================================================*/ + +#include <common/types.h> + +/*============================================================================* + Interface Header Files + *============================================================================*/ + +#include "vformat/vf_iface.h" + +/*============================================================================* + Local Header File + *============================================================================*/ + +#include "vf_config.h" +#include "vf_malloc.h" +#include "vf_internals.h" +#include "vf_string_arrays.h" + +/*============================================================================* + Public Data + *============================================================================*/ +/* None */ + +/*============================================================================* + Private Defines + *============================================================================*/ +/* None */ + +/*============================================================================* + Private Data Types + *============================================================================*/ +/* None */ + +/*============================================================================* + Private Function Prototypes + *============================================================================*/ + +static void free_prop_list( + VPROP_T *p_props /* List of properties to free */ + ); + + + +/*============================================================================* + Private Data + *============================================================================*/ +/* None */ + +/*============================================================================* + Public Function Implementations + *============================================================================*/ + + + +/*----------------------------------------------------------------------------* + * NAME + * vf_delete_object() + * + * DESCRIPTION + * Cleans up the memory used by the indicated vformat object. + * + * RETURNS + * (none) + *----------------------------------------------------------------------------*/ + +void vf_delete_object( + VF_OBJECT_T *p_object, + bool_t all + ) +{ + VOBJECT_T *p_obj = (VOBJECT_T *)p_object; + + if (p_obj) + { + VOBJECT_T *p_next = p_obj->p_next; + + free_prop_list(p_obj->p_props); + + if (p_obj->p_type) + { + vf_free(p_obj->p_type); + } + + vf_free(p_obj); + + if (all ) + { + vf_delete_object((VF_OBJECT_T *)p_next, TRUE); + } + } +} + + + + +/*----------------------------------------------------------------------------* + * NAME + * vf_delete_prop() + * + * DESCRIPTION + * Deletes indicated property from the indicated object. Deletes prop + * contents if dc is set. + * + * RETURNS + * (none) + *----------------------------------------------------------------------------*/ + +void vf_delete_prop( + VF_OBJECT_T *p_object, /* The object we're deleting from */ + VF_PROP_T *p_prop, /* The property we're removing */ + bool_t dc /* Should property contents be deleted? */ + ) +{ + VOBJECT_T *p_obj = (VOBJECT_T *)p_object; + + if (p_obj) + { + VPROP_T **p_vprop = &(p_obj->p_props); + + while (*p_vprop) + { + if ((*p_vprop) == (VPROP_T *)p_prop) + { + *p_vprop = ((VPROP_T *)p_prop)->p_next; + + if (dc) + { + delete_prop_contents(p_prop, TRUE); + } + + vf_free(p_prop); + + break; + } + else + { + p_vprop = &((*p_vprop)->p_next); + } + } + } +} + + + + + +/*----------------------------------------------------------------------------* + * NAME + * delete_prop_contents() + * + * DESCRIPTION + * Cleans up the memory used by the value associated with the property. + * The property is not deleted => can be a statically allocated variable. + * + * RETURNS + * (none) + *----------------------------------------------------------------------------*/ + +void delete_prop_contents( + VF_PROP_T *p_vprop, /* The VF_PROP_T to clean */ + bool_t delname /* Delete the name as well? */ + ) +{ + VPROP_T *p_prop = (VPROP_T *)p_vprop; + + if (delname) + { + free_string_array_contents(&p_prop->name); + + if (p_prop->p_group) + { + vf_free(p_prop->p_group); + p_prop->p_group = NULL; + } + } + + if (p_prop->value.v.b.p_buffer) + { + vf_free(p_prop->value.v.b.p_buffer); + p_prop->value.v.b.p_buffer = NULL; + } + + if (p_prop->value.v.s.pp_strings) + { + uint32_t n; + + for (n = 0;n < p_prop->value.v.s.n_strings;n++) + { + if (p_prop->value.v.s.pp_strings[n]) + { + vf_free(p_prop->value.v.s.pp_strings[n]); + p_prop->value.v.s.pp_strings[n] = NULL; + } + } + + vf_free(p_prop->value.v.s.pp_strings); + p_prop->value.v.s.pp_strings = NULL; + + p_prop->value.v.s.n_strings = 0; + } + + if (p_prop->value.v.o.p_object) + { + vf_delete_object((VF_OBJECT_T *)p_prop->value.v.o.p_object, TRUE); + p_prop->value.v.o.p_object = NULL; + } +} + + + + +/*============================================================================* + Private Function Implementations + *============================================================================*/ + + + +/*----------------------------------------------------------------------------* + * NAME + * free_prop_list() + * + * DESCRIPTION + * Cleans up the memory used by the indicated property list. + * + * RETURNS + * (none) + *----------------------------------------------------------------------------*/ + +void free_prop_list( + VPROP_T *p_props /* List of properties to free */ + ) +{ + VPROP_T *p_tmp; + + for (p_tmp = p_props;p_tmp;) + { + VPROP_T *p_next = p_tmp->p_next; + + delete_prop_contents((VF_PROP_T *)p_tmp, TRUE); + + vf_free(p_tmp); + + p_tmp = p_next; + } +} + + + + + + + + +/*============================================================================* + End Of File + *============================================================================*/ diff --git a/src/vf_internals.h b/src/vf_internals.h new file mode 100644 index 0000000..98ddacc --- /dev/null +++ b/src/vf_internals.h @@ -0,0 +1,223 @@ +/******************************************************************************* + + (C) Nick Marley, 2001 - + + This software is distributed under the GNU Lesser General Public Licence. + Please read and understand the comments at the top of vf_iface.h before use! + +FILE + $Workfile: vf_internals.h $ + $Revision: 1.15 $ + $Author: tilda $ + +ORIGINAL AUTHOR + Nick Marley + +DESCRIPTION + Definition of the internal representation used for VOBJECTs. + +REFERENCES + (none) + +MODIFICATION HISTORY + * $Log: vf_internals.h,v $ + * Revision 1.15 2002/11/02 18:29:26 tilda + * IID485157 - UI does character conversion based on CHARSET property. + * + * Revision 1.14 2002/11/02 08:56:17 tilda + * Start of internationalisation changes. + * + * Revision 1.13 2002/10/26 16:09:24 tilda + * IID629125 - Ensure string functions used are portable. + * + * Revision 1.12 2002/10/08 21:45:07 tilda + * IID620473 - reduce c-runtime dependencies. + * + * Revision 1.11 2002/02/24 17:10:34 tilda + * Add API for "is modified" functionality. + * + * Revision 1.10 2001/10/24 18:36:06 tilda + * BASE64 bugfixes. Split reader/writer code. Start create/modify work. + * + * Revision 1.9 2001/10/14 19:53:36 tilda + * Group handling. NO group searching functions. + * + * Revision 1.8 2001/10/14 16:40:04 tilda + * Initial testing of access functions. + * + * Revision 1.7 2001/10/13 16:22:08 tilda + * Introduce VBINDATA_T and VOBJDATA_T to tidy up internals. + * + * Revision 1.6 2001/10/13 14:58:56 tilda + * Tidy up version headers, add vf_strings.h where needed. + * + * Revision 1.5 2001/10/13 14:49:30 tilda + * Add string array code to unify handling of names / values. + * + * Revision 1.4 2001/10/12 16:20:03 tilda + * Correctly parse compound quoted printable properties. + * + * Revision 1.3 2001/10/10 20:53:56 tilda + * Various minor tidy ups. + * + * Revision 1.2 2001/10/09 22:01:59 tilda + * Remove older version control comments. + * + *******************************************************************************/ + +#ifndef _VF_INTERNALS_H_ +#define _VF_INTERNALS_H_ + +#ifndef NORCSID +static const char vf_internals_h_vss_id[] = "$Header: /cvsroot/vformat/src/vformat/src/vf_internals.h,v 1.15 2002/11/02 18:29:26 tilda Exp $"; +#endif + +/*=============================================================================* + Public Includes + *============================================================================*/ +/* None */ + +/*=============================================================================* + Public Defines + *============================================================================*/ + +#define VFP_BEGIN "BEGIN" +#define VFP_END "END" + +/*=============================================================================* + Public Types + *============================================================================*/ + + +/*----------------------------------------------------------------------------* + * PURPOSE + * VSTRARRAY_T encapsulates an array of strings. + *----------------------------------------------------------------------------*/ + +typedef struct VSTRARRAY_T +{ + uint32_t n_strings; /* Then number of strings */ + char **pp_strings; /* The strings */ +} +VSTRARRAY_T; + + +/*----------------------------------------------------------------------------* + * PURPOSE + * VBINDATA_T encapsulates a chunk of binary data. Yes, you could encode + * any and all vformat attributes in BASE64 but custom is to use BASE64 + * for images etc. + *----------------------------------------------------------------------------*/ + +typedef struct VBINDATA_T +{ + char *p_buffer; /* Binary data */ + uint32_t n_bufsize; +} +VBINDATA_T; + + +/*----------------------------------------------------------------------------* + * PURPOSE + * VOBJDATA_T + *----------------------------------------------------------------------------*/ + +typedef struct VOBJDATA_T +{ + struct VOBJECT_T *p_object; /* Another vformat object */ +} +VOBJDATA_T; + + + +/*----------------------------------------------------------------------------* + * PURPOSE + * VPROPVALUE_T encapsulates the "value" half of a property. + *----------------------------------------------------------------------------*/ + +typedef struct VPROPVALUE_T +{ + vf_encoding_t encoding; + + struct + { + VSTRARRAY_T s; + VBINDATA_T b; + VOBJDATA_T o; + } + v; +} +VPROPVALUE_T; + + + +/*----------------------------------------------------------------------------* + * PURPOSE + * VPROP_T defines a single property. It's an association of a name + * and value pair. A vformat object is simply a list of properties. + * Associated with a property is (possibly) a group name. + *----------------------------------------------------------------------------*/ + +typedef struct VPROP_T +{ + char *p_group; /* Group - we keep the A.B.C format */ + VSTRARRAY_T name; /* Name fields */ + VPROPVALUE_T value; /* Value fields */ + + struct VPROP_T *p_next; /* Next property */ + struct VPROP_T *p_next_srch; /* Next in current search */ + + bool_t modified; /* Property modified? */ + + struct VOBJECT_T *p_parent; /* Owning object (if any) */ +} +VPROP_T; + + +/*----------------------------------------------------------------------------* + * PURPOSE + * VOBJECT_T defines a single vformat object. + *----------------------------------------------------------------------------*/ + +typedef struct VOBJECT_T +{ + char *p_type; /* "VCARD" or "VCALENDAR" etc. */ + VPROP_T *p_props; /* List of properties */ + + bool_t modified; /* Object modified? */ + + struct VOBJECT_T *p_parent; /* Owning object (if any) */ + struct VOBJECT_T *p_next; /* Next object (if any) */ +} +VOBJECT_T; + + +/*=============================================================================* + Public Functions + *============================================================================*/ + + +/*---------------------------------------------------------------------------* + * NAME + * delete_prop_contents() + * + * DESCRIPTION + * Cleans up the memory used by the value associated with the property. + * The property is not deleted => can be a statically allocated variable. + * + * RETURNS + * (none) + *---------------------------------------------------------------------------*/ + +extern void delete_prop_contents( + VF_PROP_T *p_vprop, /* The VF_PROP_T to clean */ + bool_t delname /* Delete the name as well? */ + ); + + +/*=============================================================================* + End of file + *============================================================================*/ + +#endif /*_VF_INTERNALS_H_*/ + diff --git a/src/vf_malloc.c b/src/vf_malloc.c new file mode 100644 index 0000000..ef405d9 --- /dev/null +++ b/src/vf_malloc.c @@ -0,0 +1,270 @@ +/****************************************************************************** + + (C) Nick Marley, 2001 - + + This software is distributed under the GNU Lesser General Public Licence. + Please read and understand the comments at the top of vf_iface.h before use! + +FILE + $Workfile: vf_malloc.c $ + $Revision: 1.7 $ + $Author: tilda $ + +ORIGINAL AUTHOR + Nick Marley + +DESCRIPTION + Implements the memory allocation functions used by the rest of the vformat + library, defaulting to the functions provided by vf_malloc_stdlib.c which + uses malloc() etc. + + Code below knows nothing about the specific allocation scheme in use or it's + debugging facilities and is simply provides the common functions and the + ability to point vformat at an alternative allocation module. + + The only conditional compile option recognised is VFORMAT_MEM_DEBUG which + is described in the accompanying header file. + + Note + ==== + The original code merged the malloc() implementation with the debug facility + and also included a conditional compile VFORMAT_EXT_MALLOC to control the use + of external allocation functions. Given that this tripped up the _author_ on + at least one public test event (UPF-9, where the sync engine was unable to read + VCARDS & extract the X-IRMC stuff) it was considered overcomplicated and has + been considerably simplified ;) - T. + +MODIFICATION HISTORY + * $Log: vf_malloc.c,v $ + * Revision 1.7 2002/10/26 16:09:23 tilda + * IID629125 - Ensure string functions used are portable. + * + * Revision 1.6 2002/10/08 21:45:07 tilda + * IID620473 - reduce c-runtime dependencies. + * + * Revision 1.5 2002/10/08 21:08:43 tilda + * Improve memory debugging functions. + * + * Revision 1.4 2001/10/13 14:58:56 tilda + * Tidy up version headers, add vf_strings.h where needed. + * + * Revision 1.3 2001/10/10 20:53:56 tilda + * Various minor tidy ups. + * + * Revision 1.2 2001/10/09 22:01:59 tilda + * Remove older version control comments. + * + *******************************************************************************/ + +#ifndef NORCSID +static const char vf_malloc_c_vss_id[] = "$Header: /cvsroot/vformat/src/vformat/src/vf_malloc.c,v 1.7 2002/10/26 16:09:23 tilda Exp $"; +#endif + +/*=============================================================================* + ANSI C & System-wide Header Files + *============================================================================*/ + +#include <common/types.h> + +/*============================================================================* + Interface Header Files + *============================================================================*/ + +#include "vformat/vf_iface.h" + +/*============================================================================* + Local Header File + *============================================================================*/ + +#include "vf_config.h" +#include "vf_malloc.h" +#include "vf_internals.h" +#if !defined(VFORMAT_EXCLUDE_MALLOC) +#include "vf_malloc_stdlib.h" +#endif + +/*============================================================================* + Public Data + *============================================================================*/ +/* None */ + +/*============================================================================* + Private Defines + *============================================================================*/ +/* None */ + +/*============================================================================* + Private Data Types + *============================================================================*/ +/* None */ + +/*============================================================================* + Private Function Prototypes + *============================================================================*/ +/* None */ + +/*============================================================================* + Private Data + *============================================================================*/ + +/* + * Pointers to the functions in use - initialised to the default CRT based allocation + * functions unless VFORMAT_EXCLUDE_MALLOC is set in which case they are initialised + * to NULL in the expectation that the user calls vf_set_mem_functions() at some point. + */ + +#if defined(VFORMAT_EXCLUDE_MALLOC) +static vf_malloc_fn_t vf_malloc_fn; +static vf_realloc_fn_t vf_realloc_fn; +static vf_free_fn_t vf_free_fn; +#else +static vf_malloc_fn_t vf_malloc_fn = _vf_stdlib_malloc; +static vf_realloc_fn_t vf_realloc_fn = _vf_stdlib_realloc; +static vf_free_fn_t vf_free_fn = _vf_stdlib_free; +#endif + +/*============================================================================* + Public Function Implementations + *============================================================================*/ + + + +/*----------------------------------------------------------------------------* + * NAME + * vf_set_mem_functions() + * + * DESCRIPTION + * Set the memory allocation functions we're using. + * + * RETURNS + * (none) + *----------------------------------------------------------------------------*/ + +void vf_set_mem_functions( + vf_malloc_fn_t malloc_fn, /* Allocation function */ + vf_realloc_fn_t realloc_fn, /* Reallocation function */ + vf_free_fn_t free_fn /* Free function */ + ) +{ + vf_realloc_fn = realloc_fn; + vf_malloc_fn = malloc_fn; + vf_free_fn = free_fn; +} + + + + + +/*----------------------------------------------------------------------------* + * NAME + * _vf_malloc() + * + * DESCRIPTION + * Allocate chunk of memory. + * + * RETURNS + * Ptr to new block, or NULL if failed. + *----------------------------------------------------------------------------*/ + +void *_vf_malloc( + uint32_t s /* Size required */ +#if defined(VFORMAT_MEM_DEBUG) + , const char *file, /* Filename */ + int line /* Line number */ +#endif + ) +{ + void *p = NULL; + + if (vf_malloc_fn) + { +#if defined(VFORMAT_MEM_DEBUG) + p = vf_malloc_fn(s, file, line); +#else + p = vf_malloc_fn(s); +#endif + } + + return p; +} + + + + + +/*----------------------------------------------------------------------------* + * NAME + * _vf_realloc() + * + * DESCRIPTION + * Re-allocate chunk of memory allocated by _vf_malloc(). + * + * RETURNS + * Ptr to new block, or NULL if failed. + *----------------------------------------------------------------------------*/ + +void *_vf_realloc( + void *p, /* Original pointer */ + uint32_t s /* Size required */ +#if defined(VFORMAT_MEM_DEBUG) + , const char *file, /* filename */ + int line /* line number */ +#endif + ) +{ + void *np = NULL; + + if (vf_realloc_fn) + { +#if defined(VFORMAT_MEM_DEBUG) + np = vf_realloc_fn(p, s, file, line); +#else + np = vf_realloc_fn(p, s); +#endif + } + + return np; +} + + + + + +/*----------------------------------------------------------------------------* + * NAME + * _vf_free() + * + * DESCRIPTION + * De-allocate chunk of memory allocated by _vf_malloc(). + * + * RETURNS + * (none) + *----------------------------------------------------------------------------*/ + +void _vf_free( + void *p /* Pointer */ +#if defined(VFORMAT_MEM_DEBUG) + , const char *file, /* Filename */ + int line /* Line number */ +#endif + ) +{ + if (vf_free_fn) + { +#if defined(VFORMAT_MEM_DEBUG) + vf_free_fn(p, file, line); +#else + vf_free_fn(p); +#endif + } +} + + +/*============================================================================* + Private Function Implementations + *============================================================================*/ +/* None */ + +/*============================================================================* + End Of File + *============================================================================*/ diff --git a/src/vf_malloc.h b/src/vf_malloc.h new file mode 100644 index 0000000..7116d64 --- /dev/null +++ b/src/vf_malloc.h @@ -0,0 +1,166 @@ +/****************************************************************************** + + (C) Nick Marley, 2001 - + + This software is distributed under the GNU Lesser General Public Licence. + Please read and understand the comments at the top of vf_iface.h before use! + +FILE + $Workfile: vf_malloc.h $ + $Revision: 1.6 $ + $Author: tilda $ + +ORIGINAL AUTHOR + Nick Marley + +DESCRIPTION + Memory allocation functions / macros for vformat code. The code always uses + vf_malloc(), vf_realloc() and vf_free() which are replaced by macros with the + names of functions implemented in vf_malloc.c. + + If the conditional compile VFORMAT_MEM_DEBUG is set then in addition to the + caller's allocation parameters, filename and line number information is + provided to the lower layer which may record this for debugging. + + Additionally, a function vf_set_mem_functions() is provided which allows an + application to replace the allocation functions with it's own. This should + be done before vformat allocates any memory ie. during initialisation. + + Unless the library is built with the symbol VFORMAT_EXCLUDE_MALLOC defined + then the library defaults to using malloc() etc. + +MODIFICATION HISTORY + * $Log: vf_malloc.h,v $ + * Revision 1.6 2002/10/26 16:09:23 tilda + * IID629125 - Ensure string functions used are portable. + * + * Revision 1.5 2002/10/08 21:08:43 tilda + * Improve memory debugging functions. + * + * Revision 1.4 2001/10/13 14:58:56 tilda + * Tidy up version headers, add vf_strings.h where needed. + * + * Revision 1.3 2001/10/10 20:53:56 tilda + * Various minor tidy ups. + * + * Revision 1.2 2001/10/09 22:01:59 tilda + * Remove older version control comments. + * + *******************************************************************************/ + +#ifndef _VF_MALLOC_H_ +#define _VF_MALLOC_H_ + +#ifndef NORCSID +static const char vf_malloc_h_vss_id[] = "$Header: /cvsroot/vformat/src/vformat/src/vf_malloc.h,v 1.6 2002/10/26 16:09:23 tilda Exp $"; +#endif + +/*=============================================================================* + Public Includes + *============================================================================*/ +/* None */ + +/*=============================================================================* + Public Defines + *============================================================================*/ + +/* + * If VFORMAT_MEM_DEBUG is defined, map the vf_xxx() allocation calls to + * the debugging versions found in vf_malloc.c + */ + +#if defined(VFORMAT_MEM_DEBUG) + +#define vf_malloc(x) _vf_malloc(x, __FILE__, __LINE__) +#define vf_realloc(x, y) _vf_realloc(x, y, __FILE__, __LINE__) +#define vf_free(x) _vf_free(x, __FILE__, __LINE__) + +#else /*defined(VFORMAT_MEM_DEBUG)*/ + +#define vf_malloc(x) _vf_malloc(x) +#define vf_realloc(x, y) _vf_realloc(x, y) +#define vf_free(x) _vf_free(x) + +#endif /*defined(VFORMAT_MEM_DEBUG)*/ + +/*=============================================================================* + Public Types + *============================================================================*/ + +#if defined(VFORMAT_MEM_DEBUG) + +typedef void *(*vf_malloc_fn_t)(uint32_t s, const char *file, int line); +typedef void *(*vf_realloc_fn_t)(void *p, uint32_t ns, const char *file, int line); +typedef void (*vf_free_fn_t)(void *p, const char *file, int line); + +#else /*defined(VFORMAT_MEM_DEBUG)*/ + +typedef void *(*vf_malloc_fn_t)(uint32_t s); +typedef void *(*vf_realloc_fn_t)(void *p, uint32_t ns); +typedef void (*vf_free_fn_t)(void *p); + +#endif /*defined(VFORMAT_MEM_DEBUG)*/ + +/*=============================================================================* + Public Functions + *============================================================================*/ +/* None */ + +/*=============================================================================* + End of file + *============================================================================*/ + + +/*----------------------------------------------------------------------------* + * NAME + * _vf_malloc(), _vf_realloc(), _vf_free() + * + * DESCRIPTION + * Memory allocation functions in use. If VFORMAT_MEM_DEBUG is defined + * the line & file are recorded as well. + * + * RETURNS + * (none) + *----------------------------------------------------------------------------*/ + +#if defined(VFORMAT_MEM_DEBUG) + +extern void *_vf_malloc(uint32_t s, const char *file, int line); +extern void *_vf_realloc(void *p, uint32_t ns, const char *file, int line); +extern void _vf_free(void *p, const char *file, int line); + +#else + +extern void *_vf_malloc(uint32_t s); +extern void *_vf_realloc(void *p, uint32_t ns); +extern void _vf_free(void *p); + +#endif + + + +/*----------------------------------------------------------------------------* + * NAME + * vf_set_mem_functions() + * + * DESCRIPTION + * Set the memory allocation functions we're using. + * + * RETURNS + * (none) + *----------------------------------------------------------------------------*/ + +extern VFORMATDECLSPEC void vf_set_mem_functions( + vf_malloc_fn_t malloc_fn, + vf_realloc_fn_t realloc_fn, + vf_free_fn_t free_fn + ); + + + + +/*=============================================================================* + FIN + *============================================================================*/ + +#endif /*_VF_MALLOC_H_*/ diff --git a/src/vf_malloc_stdlib.c b/src/vf_malloc_stdlib.c new file mode 100644 index 0000000..6318fa5 --- /dev/null +++ b/src/vf_malloc_stdlib.c @@ -0,0 +1,392 @@ +/****************************************************************************** + + (C) Nick Marley, 2001 - + + This software is distributed under the GNU Lesser General Public Licence. + Please read and understand the comments at the top of vf_iface.h before use! + +FILE + $Workfile: vf_malloc.c $ + $Revision: 1.2 $ + $Author: tilda $ + +ORIGINAL AUTHOR + Nick Marley + +DESCRIPTION + C standard library based memory allocation functions referenced by default in + the accompanying vf_malloc.c file. These are excluded from the build entirely + if VFORMAT_EXCLUDE_MALLOC is set in the build options. + +MODIFICATION HISTORY + * $Log: vf_malloc_stdlib.c,v $ + * Revision 1.2 2002/11/15 09:15:00 tilda + * IID638823 - Various portability issues. + * + * Revision 1.1 2002/10/26 15:57:11 tilda + * Initial Version + * + *******************************************************************************/ + +#if !defined(VFORMAT_EXCLUDE_MALLOC) + +#ifndef NORCSID +static const char vf_malloc_stdlib_c_vss_id[] = "$Header: /cvsroot/vformat/src/vformat/src/vf_malloc_stdlib.c,v 1.2 2002/11/15 09:15:00 tilda Exp $"; +#endif + +/*=============================================================================* + ANSI C & System-wide Header Files + *============================================================================*/ + +#include <common/types.h> + +#include <stdlib.h> +#include <stdio.h> + +/*============================================================================* + Interface Header Files + *============================================================================*/ + +#include "vformat/vf_iface.h" + +/*============================================================================* + Local Header File + *============================================================================*/ + +#include "vf_config.h" +#include "vf_malloc.h" +#include "vf_strings.h" + +/*============================================================================* + Public Data + *============================================================================*/ +/* None */ + +/*============================================================================* + Private Defines + *============================================================================*/ + +#define NUMMEMBLOCKS (1024) + +#if defined(WIN) || defined(WIN32) +#define DEBUGBREAK _asm { int 3 } +#endif + +#ifndef DEBUGBREAK +#define DEBUGBREAK +#endif + +#define ALLOCBREAK (-1) + +/*============================================================================* + Private Data Types + *============================================================================*/ + +typedef struct MEMBLOCK_T +{ + void *p; /* The block */ + uint32_t s; /* The size */ + char *file; /* filename it was allocated in */ + int line; /* line number */ +} +MEMBLOCK_T; + +/*============================================================================* + Private Function Prototypes + *============================================================================*/ + +#if defined(VFORMAT_MEM_DEBUG) +static void init_mem_debug(void); +static void atexit_dump_mem(void); +#endif + +/*============================================================================* + Private Data + *============================================================================*/ + +static MEMBLOCK_T blocks[NUMMEMBLOCKS]; + +/*============================================================================* + Public Function Implementations + *============================================================================*/ + + +/*----------------------------------------------------------------------------* + * NAME + * _vf_stdlib_malloc() + * + * DESCRIPTION + * vformat compatible memory allocator using C standard library functions. + * + * RETURNS + * Ptr to new block, or NULL if failed. + *----------------------------------------------------------------------------*/ + +void *_vf_stdlib_malloc( + uint32_t s /* Size required */ +#if defined(VFORMAT_MEM_DEBUG) + , const char *file, /* filename */ + int line /* line number */ +#endif + ) +{ + void *p = NULL; + +#if defined(VFORMAT_MEM_DEBUG) + + uint32_t i; + + init_mem_debug(); + + for (i = 0;i < NUMMEMBLOCKS;i++) + { + if (blocks[i].p) + { + } + else + { + p = malloc(s); + + if (p) + { + blocks[i].p = p; + blocks[i].s = s; + blocks[i].file = (char *)file; + blocks[i].line = line; + } + + if (i == ALLOCBREAK) + { + DEBUGBREAK; + } + + break; + } + } + +#else /*defined(VFORMAT_MEM_DEBUG)*/ + + p = malloc(s); + +#endif + + return p; +} + + + + + +/*----------------------------------------------------------------------------* + * NAME + * _vf_stdlib_realloc() + * + * DESCRIPTION + * Re-allocate chunk of memory allocated by _vf_malloc(). + * + * RETURNS + * Ptr to new block, or NULL if failed. + *----------------------------------------------------------------------------*/ + +void *_vf_stdlib_realloc( + void *p, /* Original pointer */ + uint32_t s /* Size required */ +#if defined(VFORMAT_MEM_DEBUG) + , const char *file, /* Filename */ + int line /* Line number */ +#endif + ) +{ + void *np = NULL; + +#if defined(VFORMAT_MEM_DEBUG) + + uint32_t i; + + init_mem_debug(); + + if (!p) + return _vf_stdlib_malloc(s, file, line); + + for (i = 0;i < NUMMEMBLOCKS;i++) + { + if (blocks[i].p == p) + { + np = realloc(p, s); + + if (np) + { + blocks[i].p = np; + blocks[i].s = s; + } + + break; + } + } + +#else /*defined(VFORMAT_MEM_DEBUG)*/ + + np = realloc(p, s); + +#endif /*defined(VFORMAT_MEM_DEBUG)*/ + + return np; +} + + + + + +/*----------------------------------------------------------------------------* + * NAME + * _vf_stdlib_free() + * + * DESCRIPTION + * De-allocate chunk of memory allocated by _vf_malloc(). + * + * RETURNS + * (none) + *----------------------------------------------------------------------------*/ + +void _vf_stdlib_free( + void *p /* Pointer */ +#if defined(VFORMAT_MEM_DEBUG) + , const char *file, /* Filename */ + int line /* Line number */ +#endif + ) +{ +#if defined(VFORMAT_MEM_DEBUG) + + uint32_t i; + + init_mem_debug(); + + for (i = 0;i < NUMMEMBLOCKS;i++) + { + if (blocks[i].p == p) + { + blocks[i].p = NULL; + blocks[i].s = 0; + blocks[i].line = 0; + blocks[i].file = NULL; + + free(p); + + break; + } + } + +#else + + free(p); + +#endif +} + + + + + +/*----------------------------------------------------------------------------* + * NAME + * vf_stdlib_dump_alloc_info() + * + * DESCRIPTION + * Display current state of memory allocator. + * + * RETURNS + * TRUE if blocks are currently allocated, FALSE else. + *----------------------------------------------------------------------------*/ + +bool_t vf_stdlib_dump_alloc_info() +{ + unsigned long i; + unsigned long c, s; + + for (i = 0, c = 0, s = 0;i < NUMMEMBLOCKS;i++) + { + if (blocks[i].p) + { + c += 1; + s += blocks[i].s; + + printf("block[%lu] size %lu, file %s, line %d\n", + i, (unsigned long)blocks[i].s, blocks[i].file, blocks[i].line); + } + } + + if (c) + { + printf("... a total of %lu blocks, %lu bytes\n", c, s); + } + + return (0 < c) ? TRUE : FALSE; +} + + + +/*============================================================================* + Private Function Implementations + *============================================================================*/ + +#if defined(VFORMAT_MEM_DEBUG) + +/*----------------------------------------------------------------------------* + * NAME + * init_mem_debug() + * + * DESCRIPTION + * Initialisation function. + * + * RETURNS + * (none) + *----------------------------------------------------------------------------*/ + +static void init_mem_debug() +{ + static bool_t init_yet = FALSE; + + if (init_yet) + { + /* OK */ + } + else + { + p_memset(blocks, '\0', sizeof(blocks)); + + atexit(atexit_dump_mem); + + init_yet = TRUE; + } +} + + + + + +/*----------------------------------------------------------------------------* + * NAME + * atexit_dump_mem() + * + * DESCRIPTION + * atexit() callback function which dumps memory allocated info. + * + * RETURNS + * (none) + *----------------------------------------------------------------------------*/ + +static void atexit_dump_mem(void) +{ + vf_stdlib_dump_alloc_info(); +} + +#endif /*defined(VFORMAT_MEM_DEBUG)*/ + + +#endif /*defined(VFORMAT_EXCLUDE_MALLOC)*/ + + +/*============================================================================* + End Of File + *============================================================================*/ diff --git a/src/vf_malloc_stdlib.h b/src/vf_malloc_stdlib.h new file mode 100644 index 0000000..d765256 --- /dev/null +++ b/src/vf_malloc_stdlib.h @@ -0,0 +1,90 @@ +/****************************************************************************** + + (C) Nick Marley, 2001 - + + This software is distributed under the GNU Lesser General Public Licence. + Please read and understand the comments at the top of vf_iface.h before use! + +FILE + $Workfile: vf_malloc.h $ + $Revision: 1.1 $ + $Author: tilda $ + +ORIGINAL AUTHOR + Nick Marley + +DESCRIPTION + Externs for the malloc() based memory allocator. + +MODIFICATION HISTORY + * $Log: vf_malloc_stdlib.h,v $ + * Revision 1.1 2002/10/26 15:57:11 tilda + * Initial Version + * + * + *******************************************************************************/ + +#ifndef _VF_MALLOC_STDLIB_H_ +#define _VF_MALLOC_STDLIB_H_ + +#ifndef NORCSID +static const char vf_malloc_stdlib_h_vss_id[] = "$Header: /cvsroot/vformat/src/vformat/src/vf_malloc_stdlib.h,v 1.1 2002/10/26 15:57:11 tilda Exp $"; +#endif + +/*=============================================================================* + Public Includes + *============================================================================*/ +/* None */ + +/*=============================================================================* + Public Defines + *============================================================================*/ +/* None */ + +/*=============================================================================* + Public Types + *============================================================================*/ +/* None */ + +/*=============================================================================* + Public Functions + *============================================================================*/ +/* None */ + +/*=============================================================================* + End of file + *============================================================================*/ + + +/*----------------------------------------------------------------------------* + * NAME + * _vf_stdlib_malloc(), _vf_stdlib_realloc(), _vf_stdlib_free() + * + * DESCRIPTION + * Memory allocation functions provided in terms of C runtime library + * malloc() etc. If VFORMAT_MEM_DEBUG is defined the line & file are + * passed through for ebugging purposes. + * + * RETURNS + * (various) + *----------------------------------------------------------------------------*/ + +#if defined(VFORMAT_MEM_DEBUG) + +extern void *_vf_stdlib_malloc(uint32_t s, const char *file, int line); +extern void *_vf_stdlib_realloc(void *p, uint32_t ns, const char *file, int line); +extern void _vf_stdlib_free(void *p, const char *file, int line); + +#else + +extern void *_vf_stdlib_malloc(uint32_t s); +extern void *_vf_stdlib_realloc(void *p, uint32_t ns); +extern void _vf_stdlib_free(void *p); + +#endif + +/*=============================================================================* + FIN + *============================================================================*/ + +#endif /*_VF_MALLOC_STDLIB_H_*/ diff --git a/src/vf_modified.c b/src/vf_modified.c new file mode 100644 index 0000000..427698a --- /dev/null +++ b/src/vf_modified.c @@ -0,0 +1,159 @@ +/****************************************************************************** + + (C) Nick Marley, 2001 - + + This software is distributed under the GNU Lesser General Public Licence. + Please read and understand the comments at the top of vf_iface.h before use! + +FILE + $Workfile: vf_modified.c $ + $Revision: 1.4 $ + $Author: tilda $ + +ORIGINAL AUTHOR + Nick Marley + +DESCRIPTION + Memory allocation system for vformat parser / editor. + +REFERENCES + (none) + +MODIFICATION HISTORY + * $Log: vf_modified.c,v $ + * Revision 1.4 2002/11/02 18:29:26 tilda + * IID485157 - UI does character conversion based on CHARSET property. + * + * Revision 1.3 2002/10/29 07:19:20 tilda + * Tidy headers. + * + * Revision 1.2 2002/10/26 16:09:23 tilda + * IID629125 - Ensure string functions used are portable. + * + * Revision 1.1 2002/10/11 20:29:25 tilda + * Include vf_modified.c + * + *******************************************************************************/ + +#ifndef NORCSID +static const char vf_modified_c_vss_id[] = "$Header: /cvsroot/vformat/src/vformat/src/vf_modified.c,v 1.4 2002/11/02 18:29:26 tilda Exp $"; +#endif + +/*=============================================================================* + ANSI C & System-wide Header Files + *============================================================================*/ + +#include <common/types.h> + +/*============================================================================* + Interface Header Files + *============================================================================*/ + +#include "vformat/vf_iface.h" + +/*============================================================================* + Local Header File + *============================================================================*/ + +#include "vf_config.h" +#include "vf_malloc.h" +#include "vf_internals.h" +#include "vf_modified.h" + +/*============================================================================* + Public Data + *============================================================================*/ +/* None */ + +/*============================================================================* + Private Defines + *============================================================================*/ +/* None */ + +/*============================================================================* + Private Data Types + *============================================================================*/ +/* None */ + +/*============================================================================* + Private Function Prototypes + *============================================================================*/ +/* None */ + +/*============================================================================* + Private Data + *============================================================================*/ +/* None */ + +/*============================================================================* + Public Function Implementations + *============================================================================*/ + +/*---------------------------------------------------------------------------* + * NAME + * vf_is_modified() + * + * DESCRIPTION + * Return the status of the modified flag for the indicated object. + * + * RETURNS + * TRUE/FALSE + *---------------------------------------------------------------------------*/ + +bool_t vf_is_modified( + VF_OBJECT_T *p_object + ) +{ + bool_t ret = FALSE; + + if (p_object) + { + ret = ((VOBJECT_T *)p_object)->modified; + } + + return ret; +} + + + + +/*---------------------------------------------------------------------------* + * NAME + * mark_property_modified() + * + * DESCRIPTION + * Mark indicated property and it's owning object as modified. If the + * recurse flag is st, then the owning object's parent object is also + * marked as modified recursively up to the top of the tree. + * + * RETURNS + * (none) + *---------------------------------------------------------------------------*/ + +void mark_property_modified( + VPROP_T *p_prop, /* The property */ + bool_t recurse /* Recurse? */ + ) +{ + p_prop->modified = TRUE; + p_prop->p_parent->modified = TRUE; + + if (recurse) + { + VOBJECT_T *p_parent = p_prop->p_parent->p_parent; + + for (;p_parent;p_parent = p_parent->p_parent) + { + p_parent->modified = TRUE; + } + } +} + + +/*============================================================================* + Private Function Implementations + *============================================================================*/ + + /*============================================================================* + End Of File + *============================================================================*/ diff --git a/src/vf_modified.h b/src/vf_modified.h new file mode 100644 index 0000000..f1616a4 --- /dev/null +++ b/src/vf_modified.h @@ -0,0 +1,84 @@ +/******************************************************************************* + + (C) Nick Marley, 2001 - + + This software is distributed under the GNU Lesser General Public Licence. + Please read and understand the comments at the top of vf_iface.h before use! + +FILE + $Workfile: vf_modified.h $ + $Revision: 1.1 $ + $Author: tilda $ + +ORIGINAL AUTHOR + Nick Marley + +DESCRIPTION + Library internal access to the modification status. + +REFERENCES + (none) + +MODIFICATION HISTORY + * $Log: vf_modified.h,v $ + * Revision 1.1 2002/10/11 20:22:32 tilda + * Added / repaired vf_modified.h + * + * + * 2 9/05/02 3:49p Nm2 + * Adjust memoruy allocation system for use in an embedded build. + * + * 1 7/08/02 7:24a Nm2 + * + *******************************************************************************/ + +#ifndef _VF_MODIFIED_H_ +#define _VF_MODIFIED_H_ + +#ifndef NORCSID +static const char vf_modified_h_vss_id[] = "$Header: /cvsroot/vformat/src/vformat/src/vf_modified.h,v 1.1 2002/10/11 20:22:32 tilda Exp $"; +#endif + +/*=============================================================================* + Public Includes + *============================================================================*/ +/* None */ + +/*=============================================================================* + Public Defines + *============================================================================*/ +/* None */ + +/*=============================================================================* + Public Types + *============================================================================*/ +/* None */ + +/*=============================================================================* + Public Functions + *============================================================================*/ + +/*---------------------------------------------------------------------------* + * NAME + * mark_property_modified() + * + * DESCRIPTION + * Mark indicated property and it's owning object as modified. If the + * recurse flag is st, then the owning object's parent object is also + * marked as modified recursively up to the top of the tree. + * + * RETURNS + * (none) + *---------------------------------------------------------------------------*/ + +extern void mark_property_modified( + VPROP_T *p_prop, /* The property */ + bool_t recurse /* Recurse? */ + ); + + +/*=============================================================================* + End of file + *============================================================================*/ + +#endif /*_VF_MODIFIED_H_*/ diff --git a/src/vf_parser.c b/src/vf_parser.c new file mode 100644 index 0000000..bf7b789 --- /dev/null +++ b/src/vf_parser.c @@ -0,0 +1,1182 @@ +/****************************************************************************** + + (C) Nick Marley, 2001 - + + This software is distributed under the GNU Lesser General Public Licence. + Please read and understand the comments at the top of vf_iface.h before use! + +FILE + $Workfile: vf_parser.c $ + $Revision: 1.22 $ + $Author: tilda $ + +ORIGINAL AUTHOR + Nick Marley + +DESCRIPTION + Parser for text stream in vobject format. + +REFERENCES + (none) + +MODIFICATION HISTORY + * $Log: vf_parser.c,v $ + * Revision 1.22 2002/11/16 13:19:10 tilda + * IID639288 - Implement method for adding subobjects. + * + * Revision 1.21 2002/11/15 09:15:00 tilda + * IID638823 - Various portability issues. + * + * Revision 1.20 2002/11/03 18:43:16 tilda + * IID619851 - Update and check headers and function prototypes. + * + * Revision 1.19 2002/11/02 18:29:26 tilda + * IID485157 - UI does character conversion based on CHARSET property. + * + * Revision 1.18 2002/11/02 08:56:17 tilda + * Start of internationalisation changes. + * + * Revision 1.17 2002/10/26 16:09:23 tilda + * IID629125 - Ensure string functions used are portable. + * + * Revision 1.16 2002/10/08 21:45:07 tilda + * IID620473 - reduce c-runtime dependencies. + * + * Revision 1.15 2002/10/08 21:25:28 tilda + * Assignment of parent property. + * + * Revision 1.14 2002/10/08 21:11:36 tilda + * Remove common.h. + * + * Revision 1.13 2002/02/24 17:10:34 tilda + * Add API for "is modified" functionality. + * + * Revision 1.12 2001/12/13 06:45:35 tilda + * IID488021 - Various bugs with quoted printable format. + * + * Revision 1.11 2001/10/24 18:36:06 tilda + * BASE64 bugfixes. Split reader/writer code. Start create/modify work. + * + * Revision 1.10 2001/10/24 05:32:19 tilda + * BASE64 bugfixes - first part + * + * Revision 1.9 2001/10/14 20:42:37 tilda + * Addition of group searching. + * + * Revision 1.8 2001/10/14 19:53:36 tilda + * Group handling. NO group searching functions. + * + * Revision 1.7 2001/10/13 16:22:08 tilda + * Introduce VBINDATA_T and VOBJDATA_T to tidy up internals. + * + * Revision 1.6 2001/10/13 14:58:56 tilda + * Tidy up version headers, add vf_strings.h where needed. + * + * Revision 1.5 2001/10/13 14:49:30 tilda + * Add string array code to unify handling of names / values. + * + * Revision 1.4 2001/10/12 16:20:03 tilda + * Correctly parse compound quoted printable properties. + * + * Revision 1.3 2001/10/10 20:53:56 tilda + * Various minor tidy ups. + * + * Revision 1.2 2001/10/09 22:01:59 tilda + * Remove older version control comments. + * + *****************************************************************************/ + +#ifndef NORCSID +static const char vf_parser_c_vss_id[] = "$Header: /cvsroot/vformat/src/vformat/src/vf_parser.c,v 1.22 2002/11/16 13:19:10 tilda Exp $"; +#endif + +/*============================================================================* + ANSI C & System-wide Header Files + *===========================================================================*/ + +#include <common/types.h> + +/*============================================================================* + Interface Header Files + *===========================================================================*/ + +#include "vformat/vf_iface.h" + +/*============================================================================* + Local Header File + *===========================================================================*/ + +#include "vf_config.h" +#include "vf_malloc.h" +#include "vf_internals.h" +#include "vf_strings.h" +#include "vf_string_arrays.h" + +/*============================================================================* + Public Data + *===========================================================================*/ +/* None */ + +/*============================================================================* + Private Defines + *===========================================================================*/ + +/* + * Significant characters. + */ +#define PERIOD '.' +#define COLON ':' +#define SEMICOLON ';' +#define LINEFEED '\n' +#define CRETURN '\r' +#define TAB '\t' +#define BACKSLASH '\\' +#define SPACE ' ' +#define EQUALS '=' +#define PERIOD '.' + +/* + * dec hex oct char + * 10 0x0A 012 LF NL, line feed, new line, \n + * 13 0x0D 015 CR carriage return, \r + * + * => <CR><LF> = 0x0D 0x0A + */ + +/* + * States associated with propname:propvalue parsing. + */ +#define _VF_STATE_PROPNAME (1) /* reading name (including groupings) */ +#define _VF_STATE_PROPNAMEESCAPE (2) /* escaped semicolon in name */ +#define _VF_STATE_RFC822VALUE (3) /* basic */ +#define _VF_STATE_RFC822VALUEFOLD (4) /* waiting for line fold (simple fields) */ +#define _VF_STATE_QPIDLE (5) /* Non escaped position in QP */ +#define _VF_STATE_QPIDLENL (6) /* Non escaped position in QP */ +#define _VF_STATE_QPEQUALSC1 (7) /* After = in QP */ +#define _VF_STATE_QPEQUALSC2 (8) /* After =X in QP */ +#define _VF_STATE_BASE64 (9) /* Reading BASE64 */ + +#define ISCRORNL(c) ((CRETURN == (c)) || (LINEFEED == (c))) + +/*============================================================================* + Private Data Types + *===========================================================================*/ + +/*----------------------------------------------------------------------------* + * PURPOSE + * Maintains state variables etc. for current VOBJECT_T parsing. + *----------------------------------------------------------------------------*/ + +typedef struct +{ + int state; /* Main state variable */ + char qpchar; /* Workspace for QuotedPrintable decoder */ + char *p_b64buf; /* Workspace for BASE64 decoder */ + VOBJECT_T **pp_root_object; /* Pointer to the root */ + VOBJECT_T *p_object; /* Current position in tree */ + VPROP_T prop; /* Current property, copied into tree on completion */ +} +VPARSE_T; + +/*============================================================================* + Private Function Prototypes + *===========================================================================*/ + +static bool_t append_value_to_object( + VPROP_T **pp_prop, /* Pointer to the new property */ + VPARSE_T *p_parse /* The property we're naming */ + ); + +static bool_t handle_base64_chars( + VPARSE_T *p_parse, /* The property value we're adding to */ + const char *p_chars, /* Pointer to characters to add */ + int numchars /* Number of characters */ + ); + +static vf_encoding_t deduce_encoding( + VSTRARRAY_T *p_propname /* Property name */ + ); + +static uint8_t base64_to_char( + char c /* Character to convert */ + ); + +static bool_t is_hex_digit( + char *p_nibble, /* Output nibble value */ + char c /* Character read from file */ + ); + +static bool_t handle_value_complete( + VPARSE_T *p_parse /* Current parse state info */ + ); + +static bool_t alloc_next_object( + VPARSE_T *p_parse, /* Current parse state info */ + char *p_type /* Type of object */ + ); + +static bool_t alloc_sub_object( + VPARSE_T *p_parse, /* Current parse state info */ + char *p_type /* Type of object */ + ); + +static bool_t alloc_object( + VOBJECT_T **pp_new, /* Pointer to output pointer */ + VOBJECT_T *p_parent, /* Parent of new node */ + char *p_type, /* Type of new node */ + VPARSE_T *p_parse /* Current parse info */ + ); + +static bool_t append_group_name( + VPROP_T *p_prop /* Property we're updating */ + ); + + +/*============================================================================* + Private Data + *===========================================================================*/ +/* None */ + +/*============================================================================* + Public Function Implementations + *===========================================================================*/ + + + +/*----------------------------------------------------------------------------* + * NAME + * vf_parse_init() + * + * DESCRIPTION + * Initialise a parsing instance. + * + * RETURNS + * (none) + *---------------------------------------------------------------------------*/ + +bool_t vf_parse_init( + VF_PARSER_T **pp_parser, /* The parser */ + VF_OBJECT_T **pp_object /* The object we're parsing into */ + ) +{ + bool_t ret = FALSE; + + if (pp_parser && pp_object) + { + VPARSE_T *p_parse = (VPARSE_T *)vf_malloc(sizeof(VPARSE_T)); + + if (p_parse) + { + p_memset(p_parse, '\0', sizeof(VPARSE_T)); + + p_parse->state = _VF_STATE_PROPNAME; + p_parse->p_object = NULL; + p_parse->pp_root_object = (VOBJECT_T **)pp_object; + + *pp_parser = (VF_PARSER_T *)p_parse; + + *pp_object = NULL; + + ret = TRUE; + } + } + + return ret; +} + + + + + + +/*----------------------------------------------------------------------------* + * NAME + * vf_parse_text() + * + * DESCRIPTION + * Parse indicated text into the object associated with the VPARSE_T. + * + * RETURNS + * TRUE <=> allocation & syntax OK, FALSE else. + *---------------------------------------------------------------------------*/ + +bool_t vf_parse_text( + VF_PARSER_T *p_parser, /* The parser */ + char *p_chars, /* New characters to parse into object */ + int numchars /* Number of new characters */ + ) +{ + int i; + bool_t ok; + VPARSE_T *p_parse = (VPARSE_T *)p_parser; + + /* + * Check pointer. + */ + if (!p_parse) + { + return FALSE; + } + + /* + * Push each character through the state machine. + */ + for (i = 0, ok = TRUE;ok && (i < numchars);i++) + { + char c = p_chars[i]; + + switch (p_parse->state) + { + case _VF_STATE_RFC822VALUEFOLD: + { + if (ISCRORNL(c)) + { + /* Ignore */ + } + else + if (SPACE == c) + { + ok = append_to_curr_string(&(p_parse->prop.value.v.s), NULL, &c, 1); + + p_parse->state = _VF_STATE_RFC822VALUE; + } + else + { + ok = handle_value_complete(p_parse); + + p_parse->state = _VF_STATE_PROPNAME; + } + } + if (_VF_STATE_PROPNAME == p_parse->state) + { + /* Fall through */ + } + else + { + break; + } + + /* Fall through */ + + + case _VF_STATE_PROPNAME: + { + if (COLON == c) + { + p_parse->prop.value.encoding = deduce_encoding(&p_parse->prop.name); + + switch (p_parse->prop.value.encoding) + { + case VF_ENC_7BIT: + p_parse->state = _VF_STATE_RFC822VALUE; + break; + + case VF_ENC_BASE64: + p_parse->state = _VF_STATE_BASE64; + break; + + case VF_ENC_QUOTEDPRINTABLE: + p_parse->state = _VF_STATE_QPIDLE; + break; + + default: + ok = FALSE; + break; + } + } + else + if (BACKSLASH == c) + { + p_parse->state = _VF_STATE_PROPNAMEESCAPE; + } + else + if (ISCRORNL(c)) + { + /* ignore */ + + free_string_array_contents(&p_parse->prop.name); + } + else + if (SEMICOLON == c) + { + ok = add_string_to_array(&p_parse->prop.name, ""); + } + else + if (PERIOD == c) + { + ok = append_group_name(&p_parse->prop); + } + else + { + ok = append_to_curr_string(&(p_parse->prop.name), NULL, &c, 1); + } + } + break; + + case _VF_STATE_PROPNAMEESCAPE: + { + if (SEMICOLON == c) + { + ok = append_to_curr_string(&(p_parse->prop.name), NULL, &c, 1); + } + else + { + ok = FALSE; + } + } + break; + + case _VF_STATE_RFC822VALUE: + { + if (p_parse->prop.value.v.s.pp_strings) + { + /* Already allocated */ + } + else + { + ok = add_string_to_array(&(p_parse->prop.value.v.s), NULL); + } + + if (ISCRORNL(c)) + { + p_parse->state = _VF_STATE_RFC822VALUEFOLD; + } + else + if (SEMICOLON == c) + { + ok = add_string_to_array(&(p_parse->prop.value.v.s), NULL); + } + else + { + ok = append_to_curr_string(&(p_parse->prop.value.v.s), NULL, &c, 1); + } + } + break; + + case _VF_STATE_QPIDLENL: + { + if (ISCRORNL(c)) + { + break; + } + else + { + p_parse->state = _VF_STATE_QPIDLE; + } + } + + case _VF_STATE_QPIDLE: + { + if (p_parse->prop.value.v.s.pp_strings) + { + /* Already allocated */ + } + else + { + ok = add_string_to_array(&(p_parse->prop.value.v.s), NULL); + } + + if (EQUALS == c) + { + p_parse->qpchar = 0x00; + p_parse->state = _VF_STATE_QPEQUALSC1; + } + else + if (SEMICOLON == c) + { + ok = add_string_to_array(&(p_parse->prop.value.v.s), NULL); + } + else + if (ISCRORNL(c)) + { + ok = handle_value_complete(p_parse); + } + else + { + ok = append_to_curr_string(&(p_parse->prop.value.v.s), NULL, &c, 1); + } + } + break; + + case _VF_STATE_QPEQUALSC1: + { + uint8_t nibble; + + if (ISCRORNL(c)) + { + p_parse->state = _VF_STATE_QPIDLENL; + } + else + if (is_hex_digit(&nibble, c)) + { + (p_parse->qpchar) <<= 4; + (p_parse->qpchar) |= nibble; + + p_parse->state = _VF_STATE_QPEQUALSC2; + } + else + { + ok = FALSE; + } + } + break; + + case _VF_STATE_QPEQUALSC2: + { + uint8_t nibble; + + if (is_hex_digit(&nibble, c)) + { + (p_parse->qpchar) <<= 4; + (p_parse->qpchar) |= nibble; + + ok = append_to_curr_string(&(p_parse->prop.value.v.s), NULL, &(p_parse->qpchar), 1); + + p_parse->state = _VF_STATE_QPIDLE; + } + else + { + ok = FALSE; + } + } + break; + + case _VF_STATE_BASE64: + { + /* + * The cr/nl stuff associated with line ends & termination of BASE64 encoding + * seems to be particularly problematic. Searching and reading vCards from the + * internet shows that all sorts of wierd things are out there in use! In the + * interests of interoperability we look for the next value as an indication of + * the end of the object. We build up each line and if it's still in BASE64 + * format append the decoded data. Otherwise we use the parser recursively to + * decode the buffered text, which is probably something like "NEXT-VALUE:" + */ + + if (ISCRORNL(c)) + { + if (p_parse->p_b64buf) + { + ok = handle_base64_chars(p_parse, p_parse->p_b64buf, p_strlen(p_parse->p_b64buf)); + + vf_free(p_parse->p_b64buf); + p_parse->p_b64buf = NULL; + } + } + else + { + ok = append_to_pointer(&(p_parse->p_b64buf), NULL, &c, 1); + + if ((COLON == c) || (SEMICOLON == c)) + { + ok = handle_value_complete(p_parse); + + ok = vf_parse_text(p_parser, p_parse->p_b64buf, p_strlen(p_parse->p_b64buf)); + + vf_free(p_parse->p_b64buf); + p_parse->p_b64buf = NULL; + } + } + } + break; + } + } + + if (ok) + { + /* no need to panic */ + } + else + { + vf_delete_object((VF_OBJECT_T *)*(p_parse->pp_root_object), TRUE); + *(p_parse->pp_root_object) = NULL; + p_parse->p_object = NULL; + + if (p_parse->p_b64buf) + { + vf_free(p_parse->p_b64buf); + p_parse->p_b64buf = NULL; + } + + delete_prop_contents((VF_PROP_T *)&p_parse->prop, TRUE); + } + + return ok; +} + + + + + + +/*----------------------------------------------------------------------------* + * NAME + * vf_parse_end() + * + * DESCRIPTION + * Ensure parse completion. + * + * RETURNS + * TRUE <=> allocation & syntax OK, FALSE else. + *---------------------------------------------------------------------------*/ + +bool_t vf_parse_end( + VF_PARSER_T *p_parser /* The parser */ + ) +{ + bool_t ret = FALSE; + VPARSE_T *p_parse = (VPARSE_T *)p_parser; + + /* + * Check pointer. + */ + if (p_parse) + { + ret = handle_value_complete(p_parse); + + vf_free(p_parse); + } + + return ret; +} + + + + +/*============================================================================* + Private Functions + *===========================================================================*/ + + +/*----------------------------------------------------------------------------* + * NAME + * append_group_name() + * + * DESCRIPTION + * After reading a ".", we transfer the segment of name we've read (which + * must be the first string <G>) into the group name. Keep the group name + * in one string of "." tokens for simplicity, so we may end up with a + * group called "X-PHONE-BOOK.ENTRY.1" etc. + * + * RETURNS + * TRUE <=> allocation OK. + *---------------------------------------------------------------------------*/ + +bool_t append_group_name( + VPROP_T *p_prop + ) +{ + bool_t ok = TRUE; + + if (p_prop->p_group) + { + ok &= append_to_pointer(&p_prop->p_group, NULL, ".", 1); + } + + if (ok) + { + const char *p_string = p_prop->name.pp_strings[0]; + + ok &= append_to_pointer(&p_prop->p_group, NULL, p_string, p_strlen(p_string)); + + if (ok) + { + vf_free(p_prop->name.pp_strings[0]); + p_prop->name.pp_strings[0] = NULL; + } + } + + return ok; +} + + + + + +/*----------------------------------------------------------------------------* + * NAME + * handle_value_complete() + * + * DESCRIPTION + * Called when a complete value is parsed. + * + * RETURNS + * (none). + *---------------------------------------------------------------------------*/ + +bool_t handle_value_complete( + VPARSE_T *p_parse /* Current parse state info */ + ) +{ + bool_t ret = TRUE; + VOBJECT_T *p_object; + + /* + * If we've got no object open we ignore values until we read a BEGIN at which point + * we create a vformat object and start to parse properties into it. If we subsequently + * read a BEGIN we add a property & parse the next vobject into that. Each time we read + * an END we pop the pp_object pointer back up to the owner of the object we're parsing + * into. There should be an easier way of doing this <G> ... + */ + + p_object = p_parse->p_object; + + if (p_object) + { + if (string_array_contains_string(&p_parse->prop.name, NULL, 0, VFP_BEGIN, TRUE)) + { + char *p_type; + + p_type = p_parse->prop.value.v.s.pp_strings[0]; + p_parse->prop.value.v.s.pp_strings[0] = NULL; + + delete_prop_contents((VF_PROP_T *)(&(p_parse->prop)), TRUE); + + p_parse->prop.value.encoding = VF_ENC_VOBJECT; + + ret = add_string_to_array(&(p_parse->prop.name), p_type) && + alloc_sub_object(p_parse, p_type); + } + else + if (string_array_contains_string(&p_parse->prop.name, NULL, 0, VFP_END, TRUE)) + { + delete_prop_contents((VF_PROP_T *)(&(p_parse->prop)), TRUE); + + p_parse->p_object = p_parse->p_object->p_parent; + } + else + { + ret = append_value_to_object(NULL, p_parse); + } + } + else + { + if (string_array_contains_string(&p_parse->prop.name, NULL, 0, VFP_BEGIN, TRUE)) + { + char *p_type; + + p_type = p_parse->prop.value.v.s.pp_strings[0]; + p_parse->prop.value.v.s.pp_strings[0] = NULL; + + ret = alloc_next_object(p_parse, p_type); + } + + delete_prop_contents((VF_PROP_T *)(&(p_parse->prop)), TRUE); + } + + p_parse->state = _VF_STATE_PROPNAME; + + return ret; +} + + + + + + +/*----------------------------------------------------------------------------* + * NAME + * alloc_next_object() + * + * DESCRIPTION + * Allocate the "next" object, ie. annother vformat tagged to the p_next + * pointer to the current one. + * + * RETURNS + * TRUE iff memory allocated OK, FALSE else OK. + *---------------------------------------------------------------------------*/ + +bool_t alloc_next_object( + VPARSE_T *p_parse, /* Current parse state info */ + char *p_type /* Type of object */ + ) +{ + bool_t ok = TRUE; + VOBJECT_T *p_parent = p_parse->p_object; + VOBJECT_T *p_new = NULL; + + ok = alloc_object(&p_new, p_parent ? p_parent->p_parent : NULL, p_type, p_parse); + + if (ok) + { + if (*p_parse->pp_root_object) + { + /* root object already set */ + + if (p_new->p_parent) + { + /* Owned by property */ + } + else + { + /* Need to tag to end of top list */ + + VOBJECT_T **pp_tmp = p_parse->pp_root_object; + + while (*pp_tmp) + { + pp_tmp = &((*pp_tmp)->p_next); + } + + *pp_tmp = p_new; + } + } + else + { + *p_parse->pp_root_object = p_new; + } + } + + return ok; +} + + + + + + + +/*----------------------------------------------------------------------------* + * NAME + * alloc_sub_object() + * + * DESCRIPTION + * Allocate "sub" object, ie. annother vformat tagged to the p_object + * pointer of a VPROP_T allocated to contain it. + * + * RETURNS + * TRUE iff memory allocated OK, FALSE else OK. + *---------------------------------------------------------------------------*/ + +bool_t alloc_sub_object( + VPARSE_T *p_parse, /* Current parse state info */ + char *p_type /* Type of object */ + ) +{ + bool_t ok = FALSE; + VOBJECT_T *p_parent = p_parse->p_object; + + if (p_parent) + { + VPROP_T *p_tmp; + + ok = append_value_to_object(&p_tmp, p_parse); + + if (ok && p_tmp) + { + ok = alloc_object(&p_tmp->value.v.o.p_object, p_parent, p_type, p_parse); + } + } + + return ok; +} + + + + + + +/*----------------------------------------------------------------------------* + * NAME + * alloc_object() + * + * DESCRIPTION + * Allocate & initialise a new VOBJECT_T. The new element od made the + * current parse target (ie. new properties will be added to it). + * + * RETURNS + * TRUE <=> allocation went OK, FALSE else. + *---------------------------------------------------------------------------*/ + +bool_t alloc_object( + VOBJECT_T **pp_new, /* Pointer to output pointer */ + VOBJECT_T *p_parent, /* Parent of new node */ + char *p_type, /* Type of new node */ + VPARSE_T *p_parse /* Current parse info */ + ) +{ + bool_t ok = TRUE; + VOBJECT_T *p_new; + + p_new = (VOBJECT_T *)vf_malloc(sizeof(VOBJECT_T)); + + if (p_new) + { + p_memset(p_new, '\0', sizeof(VOBJECT_T)); + + p_new->p_parent = p_parent; + p_new->p_type = p_type; + + p_parse->p_object = p_new; + + *pp_new = p_new; + } + else + { + ok = FALSE; + } + + return ok; +} + + + + + + + +/*----------------------------------------------------------------------------* + * NAME + * handle_base64_chars() + * + * DESCRIPTION + * Handle BASE64 decoding. + * + * RETURNS + * TRUE <=> allocation OK, FALSE else. + *---------------------------------------------------------------------------*/ + +bool_t handle_base64_chars( + VPARSE_T *p_parse, /* The property value we're adding to */ + const char *p_chars, /* Pointer to characters to add */ + int numchars /* Number of characters */ + ) +{ + bool_t ok = TRUE; + + /* + * Skip spaces. + */ + while ((0 < numchars) && (SPACE == p_chars[0])) + { + numchars--; + p_chars++; + } + + /* + * Convert groups of 4 characters to byte triplets & append the bytes + * to the binary data. + */ + if (0 < numchars) + { + int i, j, len, num, left; + const char *p_quad; + + len = numchars; + num = len / 4; + left = len % 4; + + for (i = 0, p_quad = p_chars;(i < num);i++, p_quad += 4) + { + uint32_t b; + char bytes[3]; + uint8_t bits; + + for (j = 0, b = 0, bits = 0;(j < 4);j++) + { + b = (b << 6) | base64_to_char(p_quad[j]); + + if (EQUALS != p_quad[j]) + { + bits += 6; + } + } + + for (j = 0;(j < 3);j++) + { + bytes[2 - j] = (unsigned char)(b & 0xFF); + + b >>= 8; + } + + ok = append_to_pointer(&(p_parse->prop.value.v.b.p_buffer), &(p_parse->prop.value.v.b.n_bufsize), bytes, bits / 8); + } + } + + return ok; +} + + + + + + +/*----------------------------------------------------------------------------* + * NAME + * append_value_to_object() + * + * DESCRIPTION + * Append characters to the name half of a VOBJECT_T. The VOBJECT is + * allocated if not already present. + * + * RETURNS + * TRUE <=> allocation OK, FALSE else. + *---------------------------------------------------------------------------*/ + +bool_t append_value_to_object( + VPROP_T **pp_prop, /* Pointer to the new property */ + VPARSE_T *p_parse /* The property we're naming */ + ) +{ + bool_t ok = FALSE; + + VPROP_T **pp_tmp; + VPROP_T *p_prop; + + pp_tmp = &(p_parse->p_object->p_props); + + while (*pp_tmp) + { + pp_tmp = &((*pp_tmp)->p_next); + } + + *pp_tmp = p_prop = (VPROP_T *)vf_malloc(sizeof(VPROP_T)); + + if (pp_prop) + { + *pp_prop = p_prop; + } + + if (p_prop) + { + p_memset(p_prop, '\0', sizeof(VPROP_T)); + + *p_prop = p_parse->prop; + + p_memset(&(p_parse->prop), '\0', sizeof(VPROP_T)); + + p_prop->p_parent = p_parse->p_object; + + ok = TRUE; + } + + return ok; +} + + + + + + + +/*----------------------------------------------------------------------------* + * NAME + * deduce_encoding() + * + * DESCRIPTION + * Check property name for encoding tags. If none present, return the + * default encoding. + * + * RETURNS + * vf_encoding_t. + *---------------------------------------------------------------------------*/ + +vf_encoding_t deduce_encoding( + VSTRARRAY_T *p_propname /* Property name */ + ) +{ + vf_encoding_t ret = VF_ENC_7BIT; + + if (string_array_contains_string(p_propname, NULL, -1, VFP_QUOTEDPRINTABLE, FALSE)) + { + ret = VF_ENC_QUOTEDPRINTABLE; + } + else + if (string_array_contains_string(p_propname, NULL, -1, VFP_BASE64, FALSE)) + { + ret = VF_ENC_BASE64; + } + else + if (string_array_contains_string(p_propname, NULL, -1, VFP_8BIT, FALSE)) + { + ret = VF_ENC_8BIT; + } + + return ret; +} + + + + + + + +/*----------------------------------------------------------------------------* + * NAME + * is_hex_digit() + * + * DESCRIPTION + * + * + * RETURNS + * TRUE <=> valid HEX digit read. + *---------------------------------------------------------------------------*/ + +bool_t is_hex_digit( + char *p_nibble, /* Output nibble value */ + char c /* Character read from file */ + ) +{ + bool_t ret = TRUE; + + if (('A' <= c) && (c <= 'F')) + { + *p_nibble = c - 'A' + 10; + } + else + if (('a' <= c) && (c <= 'f')) + { + *p_nibble = c - 'a' + 10; + } + else + if (('0' <= c) && (c <= '9')) + { + *p_nibble = c - '0'; + } + else + { + ret = FALSE; + } + + return ret; +} + + + + + +/*----------------------------------------------------------------------------* + * NAME + * base64_to_char() + * + * DESCRIPTION + * Convert base 64 char to byte. + * + * RETURNS + * Number corresponding to char. + *---------------------------------------------------------------------------*/ + +uint8_t base64_to_char(char c) +{ + if (('A' <= c) && (c <= 'Z')) + return c - 'A'; + + if (('a' <= c) && (c <= 'z')) + return c - 'a' + 26; + + if (('0' <= c) && (c <= '9')) + return c - '0' + 52; + + if ('+' == c) + return 62; + + if ('/' == c) + return 63; + + return 0x00; +} + + +/*============================================================================* + End Of File + *===========================================================================*/ diff --git a/src/vf_reader.c b/src/vf_reader.c new file mode 100644 index 0000000..667279f --- /dev/null +++ b/src/vf_reader.c @@ -0,0 +1,277 @@ +/****************************************************************************** + + (C) Nick Marley, 2001 - + + This software is distributed under the GNU Lesser General Public Licence. + Please read and understand the comments at the top of vf_iface.h before use! + +FILE + $Workfile: vf_reader.c $ + $Revision: 1.18 $ + $Author: tilda $ + +ORIGINAL AUTHOR + Nick Marley. + +DESCRIPTION + Code for reading vformat files from disk. Delegates the real responsibility + to vf_parser for actually converting chunks of text into the memory data + structure. + +REFERENCES + (none) + +MODIFICATION HISTORY + * $Log: vf_reader.c,v $ + * Revision 1.18 2002/11/15 09:20:59 tilda + * IID638823 - Don't include unistd.h unless required. + * + * Revision 1.17 2002/11/15 09:15:00 tilda + * IID638823 - Various portability issues. + * + * Revision 1.16 2002/11/03 18:43:16 tilda + * IID619851 - Update and check headers and function prototypes. + * + * Revision 1.15 2002/10/26 16:09:23 tilda + * IID629125 - Ensure string functions used are portable. + * + * Revision 1.14 2002/10/08 21:11:36 tilda + * Remove common.h. + * + * Revision 1.13 2001/12/13 06:45:35 tilda + * IID488021 - Various bugs with quoted printable format. + * + * Revision 1.12 2001/11/05 21:07:19 tilda + * Various changes for initial version of vfedit. + * + * Revision 1.11 2001/10/24 18:36:06 tilda + * BASE64 bugfixes. Split reader/writer code. Start create/modify work. + * + * Revision 1.10 2001/10/24 05:32:19 tilda + * BASE64 bugfixes - first part + * + * Revision 1.9 2001/10/16 05:50:53 tilda + * Debug support for lists of vobjects from single file (ie. a phonebook). + * + * Revision 1.8 2001/10/14 19:53:36 tilda + * Group handling. NO group searching functions. + * + * Revision 1.7 2001/10/13 16:22:08 tilda + * Introduce VBINDATA_T and VOBJDATA_T to tidy up internals. + * + * Revision 1.6 2001/10/13 14:58:56 tilda + * Tidy up version headers, add vf_strings.h where needed. + * + * Revision 1.5 2001/10/13 14:49:30 tilda + * Add string array code to unify handling of names / values. + * + * Revision 1.4 2001/10/12 16:20:02 tilda + * Correctly parse compound quoted printable properties. + * + * Revision 1.3 2001/10/10 20:53:55 tilda + * Various minor tidy ups. + * + * Revision 1.2 2001/10/09 22:01:59 tilda + * Remove older version control comments. + * + *******************************************************************************/ + +#ifndef NORCSID +static const char vf_reader_c_vss_id[] = "$Header: /cvsroot/vformat/src/vformat/src/vf_reader.c,v 1.18 2002/11/15 09:20:59 tilda Exp $"; +#endif + +/*=============================================================================* + ANSI C & System-wide Header Files + *=============================================================================*/ + +#include <common/types.h> + +#include <stdio.h> +#include <sys/stat.h> + +#if defined(HAS_UNISTD_H) +#include <unistd.h> +#endif + +#if defined(WIN) || defined(WIN32) +#include <io.h> +#endif + + +/*============================================================================* + Interface Header Files + *============================================================================*/ + +#include <vformat/vf_iface.h> + +/*============================================================================* + Local Header File + *============================================================================*/ + +#include "vf_config.h" +#include "vf_internals.h" +#include "vf_malloc.h" + +/*============================================================================* + Public Data + *============================================================================*/ +/* None */ + +/*============================================================================* + Private Defines + *============================================================================*/ + +#define PARSEBUFSIZE (1024) + +/*============================================================================* + Private Data Types + *============================================================================*/ +/* None */ + +/*============================================================================* + Private Function Prototypes + *============================================================================*/ +/* None */ + +/*============================================================================* + Private Data + *============================================================================*/ +/* None */ + +/*============================================================================* + Public Function Implementations + *============================================================================*/ + +/*----------------------------------------------------------------------------* + * NAME + * vf_read_file() + * + * DESCRIPTION + * Reads indicated VOBJECT_T file. + * + * RETURNS + * TRUE <=> read OK, FALSE else. + *----------------------------------------------------------------------------*/ + +bool_t vf_read_file( + VF_OBJECT_T **pp_object, + const char *p_name + ) +{ + bool_t ret = FALSE; + + if (pp_object) + { + FILE *fp; + + fp = fopen(p_name, "rb"); + + if (fp) + { + char buffer[PARSEBUFSIZE]; + int charsread; + VF_PARSER_T *p_parser; + + if (vf_parse_init(&p_parser, pp_object)) + { + do + { + charsread = read(fileno(fp), buffer, sizeof(buffer)); + + if (0 < charsread) + { + ret = vf_parse_text(p_parser, buffer, charsread); + } + } + while (ret && (0 < charsread)) + ; + + if (!vf_parse_end(p_parser)) + { + ret = FALSE; + } + } + + if (0 == fclose(fp)) + { + /* OK */ + } + else + { + ret = FALSE; + } + } + } + + return ret; +} + + + + +/*---------------------------------------------------------------------------* + * NAME + * vf_set_property_from_file() + * + * DESCRIPTION + * Loads the indicated file into memory and sets the indicated property. + * + * RETURNS + * (none) + *---------------------------------------------------------------------------*/ + +bool_t vf_set_property_from_file( + VF_PROP_T *p_prop, /* The property */ + vf_encoding_t encoding, /* Encoding to use */ + const char *p_filename /* Source filename */ + ) +{ + bool_t ret = FALSE; + struct stat buf; + + if (0 == stat(p_filename, &buf)) + { + uint8_t *p_data = vf_malloc(buf.st_size); + + if (p_data) + { + FILE *fp = fopen(p_filename, "rb"); + + if (fp) + { + if ((int)buf.st_size == read(fileno(fp), p_data, buf.st_size)) + { + ret = TRUE; + } + + if (0 == fclose(fp)) + { + /* */ + } + else + { + ret = FALSE; + } + + if (ret) + { + ret &= vf_set_prop_value(p_prop, p_data, buf.st_size, encoding, TRUE); + } + } + + vf_free(p_data); + } + } + + return ret; +} + + +/*============================================================================* + Private Function Implementations + *============================================================================*/ +/* None */ + +/*============================================================================* + End Of File + *============================================================================*/ diff --git a/src/vf_search.c b/src/vf_search.c new file mode 100644 index 0000000..71be484 --- /dev/null +++ b/src/vf_search.c @@ -0,0 +1,457 @@ +/**************************************************************************** + + (C) Nick Marley, 2001 - + + This software is distributed under the GNU Lesser General Public Licence. + Please read and understand the comments at the top of vf_iface.h before use! + +FILE + $Workfile: vf_access.c $ + $Revision: 1.11 $ + $Author: tilda $ + +ORIGINAL AUTHOR + Nick Marley + +DESCRIPTION + Basic searching functions for the vformat library. + +REFERENCES + (none) + +MODIFICATION HISTORY + * $Log: vf_search.c,v $ + * Revision 1.11 2002/11/03 18:43:16 tilda + * IID619851 - Update and check headers and function prototypes. + * + * Revision 1.10 2002/11/02 18:29:26 tilda + * IID485157 - UI does character conversion based on CHARSET property. + * + * Revision 1.9 2002/10/26 16:09:23 tilda + * IID629125 - Ensure string functions used are portable. + * + * Revision 1.8 2002/10/08 21:45:07 tilda + * IID620473 - reduce c-runtime dependencies. + * + * Revision 1.7 2002/10/08 21:11:36 tilda + * Remove common.h. + * + * Revision 1.6 2002/02/24 17:10:34 tilda + * Add API for "is modified" functionality. + * + * Revision 1.5 2001/11/18 21:46:59 tilda + * Remove redundant code. + * + * Revision 1.4 2001/11/16 22:34:50 tilda + * New vf_get_property() allows append as well as find, + * + * Revision 1.3 2001/11/05 21:07:19 tilda + * Various changes for initial version of vfedit. + * + * Revision 1.2 2001/10/24 18:56:29 tilda + * Tidy headers after import. Fix include path in release build. + * + * Revision 1.1 2001/10/24 18:34:35 tilda + * Initial Version. + * + *****************************************************************************/ + +#ifndef NORCSID +static const char vf_search_c_vss_id[] = "$Header: /cvsroot/vformat/src/vformat/src/vf_search.c,v 1.11 2002/11/03 18:43:16 tilda Exp $"; +#endif + +/*============================================================================* + ANSI C & System-wide Header Files + *============================================================================*/ + +#include <common/types.h> + +/*===========================================================================* + Interface Header Files + *===========================================================================*/ + +#include "vformat/vf_iface.h" + +/*===========================================================================* + Local Header File + *===========================================================================*/ + +#include "vf_config.h" +#include "vf_malloc.h" +#include "vf_internals.h" +#include "vf_strings.h" +#include "vf_string_arrays.h" + +/*===========================================================================* + Public Data + *===========================================================================*/ +/* None */ + +/*===========================================================================* + Private Defines + *===========================================================================*/ + +/* + * Maximum supported search tags. + */ +#define MAXNUMTAGS (10) + +/*===========================================================================* + Private Data Types + *===========================================================================*/ +/* None */ + +/*===========================================================================* + Private Function Prototypes + *===========================================================================*/ + + +/*===========================================================================* + Private Data + *===========================================================================*/ +/* None */ + +/*===========================================================================* + Public Function Implementations + *===========================================================================*/ + + + +/*---------------------------------------------------------------------------* + * NAME + * vf_get_property() + * + * DESCRIPTION + * Basic searching function locating elements of the VOBJECT by qualified + * name. The function is a varargs function (like sprintf) and the list + * of arguments must be NULL terminated (hence the appearance of the + * p_qualifier argument in the arglist). Valid calls might be: + * + * vf_get_property(&p_out, p_object, FALSE, NULL, "N", NULL); + * vf_get_property(&p_out, p_object, FALSE, NULL, "TEL", "WORK", NULL); + * vf_get_property(&p_out, p_object, FALSE, "ME", "TEL", "WORK", NULL); + * vf_get_property(&p_out, p_object, FALSE, "ME", "*", NULL); + * + * A pointer to the first property matching the search criteria is returned + * the pp_prop argument. The search actually locates all such matches and + * pointer to subsequent entries (if there are >1) may be found by calling + * the vf_get_next_property() function. + * + * Qualifying tags (ie. not the name) may occur in any order + * + * Note that the VF_PROP_T returned vi pp_prop is an opaque type and the + * various accessor functions must be used to get to the data. + * + * RETURNS + * TRUE iff found/added successfully. ptr to prop returned via pp_prop. + *---------------------------------------------------------------------------*/ + +bool_t vf_get_property( + VF_PROP_T **pp_prop, /* Output pointer */ + VF_OBJECT_T *p_object, /* Object to add to */ + vf_get_t ops, /* Search flags */ + const char *p_group, /* Group name if any */ + const char *p_name, /* Name of tag */ + const char *p_qualifier, /* First qualifier if any */ + ... /* Subequent qualifiers */ + ) +{ + bool_t ret = FALSE; + va_list args; + + va_start(args, p_qualifier); + + ret = vf_get_property_ex(pp_prop, p_object, ops, p_group, p_name, p_qualifier, args); + + va_end(args); + + return ret; +} + + + + + + + + +/*---------------------------------------------------------------------------* + * NAME + * vf_get_property_ex() + * + * DESCRIPTION + * The grunt behind vf_get_property(). Manages the search as described + * vf_get_property() but takes the list of arguments as a va_list. + * + * RETURNS + * TRUE iff found / appended OK. + *---------------------------------------------------------------------------*/ + +bool_t vf_get_property_ex( + VF_PROP_T **pp_prop, /* Output pointer */ + VF_OBJECT_T *p_object, /* Object to search */ + vf_get_t ops, /* Search flags */ + const char *p_group, /* Group name if any */ + const char *p_name, /* Name of tag */ + const char *p_qualifier, /* First qualifier if any */ + va_list args /* Argument list */ + ) +{ + bool_t ret = FALSE; + char **pp_tags = NULL; + + if (!p_name || !p_object) + return ret; + + if (pp_prop) + { + *pp_prop = NULL; + } + + pp_tags = (char **)vf_malloc(MAXNUMTAGS * sizeof(char *)); + + if (pp_tags) + { + VOBJECT_T *p_obj = (VOBJECT_T *)p_object; + VPROP_T *p_props = p_obj->p_props; + int i; + + VPROP_T **pp_lastprop = &(p_obj->p_props); + VPROP_T **pp_next_srch = NULL; + + p_memset(pp_tags, '\0', MAXNUMTAGS * sizeof(char *)); + + pp_tags[0] = (char *)p_name; + + /* + * The name is the first tag. We insist on there being at least one qualifier in the + * argument list to make sure callers terminate the list. Subsequent arguments are + * optional, but will be ignored if the (first) qualifier is NULL. + */ + if (p_qualifier) + { + pp_tags[1] = (char *)p_qualifier; + + for (i = 2;i < MAXNUMTAGS;i++) + { + char *p_tag = va_arg(args, char *); + + if (p_tag) + { + pp_tags[i] = p_tag; + } + else + { + break; + } + } + } + + if (ops & VFGP_FIND) + { + /* + * Skip down the list or properties. I'm assuming that we only want to search the + * current object for properties not the current object AND any contained objects. + * Such a search sounds a bit application specific, ie. the caller would be looking + * for a particular structure of things. Each element that is found is stitched + * into the emerging list. + */ + for (;NULL != p_props;p_props = p_props->p_next) + { + bool_t found = TRUE; + + /* + * Check the name & qualifiers. + */ + for (i = 0;found && (i < MAXNUMTAGS) && pp_tags[i];i++) + { + if (0 != p_strcmp(VFP_ANY, pp_tags[i])) + found &= string_array_contains_string(&p_props->name, NULL, -1, pp_tags[i], TRUE); + } + if (p_group && found) + { + found = FALSE; + + if (p_props->p_group) + { + if (0 == p_stricmp(p_props->p_group, p_group)) + { + found = TRUE; + } + } + else + { + /* Search group specified & property doesn't have a group => not required */ + } + } + + if (found) + { + if (pp_prop) + { + if (!*pp_prop) + { + pp_next_srch = &(p_props->p_next_srch); + p_props->p_next_srch = NULL; + + *pp_prop = (VF_PROP_T *)p_props; + } + else + { + *pp_next_srch = p_props; + + pp_next_srch = &(p_props->p_next_srch); + p_props->p_next_srch = NULL; + } + } + + ret = TRUE; + } + + if (p_props->p_next) + { + pp_lastprop = &(p_props->p_next); + } + } + } + + if (!ret && (ops & VFGP_APPEND)) + { + VPROP_T *p_new = (VPROP_T *)vf_malloc(sizeof(VPROP_T)); + + if (p_new) + { + ret = TRUE; + + p_memset(p_new, '\0', sizeof(VPROP_T)); + + p_new->p_parent = p_obj; + + for (i = 0;ret && (i < MAXNUMTAGS) && pp_tags[i];i++) + { + ret = add_string_to_array(&p_new->name, pp_tags[i]); + } + + if (ret) + { + /* All OK */ + + p_new->value.encoding = VF_ENC_7BIT; + } + else + { + free_string_array_contents(&p_new->name); + + vf_free(p_new); + p_new = NULL; + } + } + + if (p_new) + { + if (pp_prop) + { + *pp_prop = (VF_PROP_T *)p_new; + } + + p_new->p_next = *pp_lastprop; + *pp_lastprop = p_new; + + ret = TRUE; + } + } + + vf_free(pp_tags); + } + + return ret; +} + + + + + + + +/*---------------------------------------------------------------------------* + * NAME + * vf_get_next_property() + * + * DESCRIPTION + * Find the next property given the current search critera. + * + * RETURNS + * TRUE iff found, FALSE else. *pp_prop points to the next property. + *---------------------------------------------------------------------------*/ + +bool_t vf_get_next_property( + VF_PROP_T **pp_prop /* Output pointer */ + ) +{ + bool_t ret = FALSE; + + if (pp_prop) + { + VPROP_T **pp_vprop = (VPROP_T **)pp_prop; + + if (*pp_vprop) + { + *pp_prop = (VF_PROP_T *)((*pp_vprop)->p_next_srch); + + if (*pp_prop) + { + ret = TRUE; + } + } + } + + return ret; +} + + + + +/*---------------------------------------------------------------------------* + * NAME + * vf_get_next_object() + * + * DESCRIPTION + * Find "next" vobject. + * + * RETURNS + * TRUE iff found next object. + *---------------------------------------------------------------------------*/ + +bool_t vf_get_next_object( + VF_OBJECT_T **pp_object + ) +{ + bool_t ret = FALSE; + + if (pp_object) + { + if (*pp_object) + { + *pp_object = (VF_OBJECT_T *)(((VOBJECT_T *)(*pp_object))->p_next); + + if (*pp_object) + { + ret = TRUE; + } + } + } + + return ret; +} + + + + +/*===========================================================================* + Private Function Implementations + *===========================================================================*/ +/* None */ + +/*===========================================================================* + End Of File + *===========================================================================*/ diff --git a/src/vf_string_arrays.c b/src/vf_string_arrays.c new file mode 100644 index 0000000..eee27f4 --- /dev/null +++ b/src/vf_string_arrays.c @@ -0,0 +1,435 @@ +/****************************************************************************** + + (C) Nick Marley, 2001 - + + This software is distributed under the GNU Lesser General Public Licence. + Please read and understand the comments at the top of vf_iface.h before use! + +FILE + $Workfile: vf_access.c $ + $Revision: 1.4 $ + $Author: tilda $ + +ORIGINAL AUTHOR + Nick Marley + +DESCRIPTION + Utility functions handling string arrays - the VSTRARRAY_T type. + +REFERENCES + (none) + +MODIFICATION HISTORY + * $Log: vf_string_arrays.c,v $ + * Revision 1.4 2002/11/03 18:43:16 tilda + * IID619851 - Update and check headers and function prototypes. + * + * Revision 1.3 2002/11/02 18:29:26 tilda + * IID485157 - UI does character conversion based on CHARSET property. + * + * Revision 1.2 2002/10/29 07:19:20 tilda + * Tidy headers. + * + * Revision 1.1 2002/10/26 15:57:11 tilda + * Initial Version + * + *******************************************************************************/ + +#ifndef NORCSID +static const char vf_string_arrays_c_vss_id[] = "$Header: /cvsroot/vformat/src/vformat/src/vf_string_arrays.c,v 1.4 2002/11/03 18:43:16 tilda Exp $"; +#endif + +/*=============================================================================* + ANSI C & System-wide Header Files + *=============================================================================*/ + +#include <common/types.h> + +/*============================================================================* + Interface Header Files + *============================================================================*/ + +#include "vformat/vf_iface.h" + +/*============================================================================* + Local Header File + *============================================================================*/ + +#include "vf_config.h" +#include "vf_malloc.h" +#include "vf_internals.h" +#include "vf_strings.h" +#include "vf_string_arrays.h" + +/*============================================================================* + Public Data + *============================================================================*/ +/* None */ + +/*============================================================================* + Private Defines + *============================================================================*/ +/* None */ + +/*============================================================================* + Private Data Types + *============================================================================*/ +/* None */ + +/*============================================================================* + Private Function Prototypes + *============================================================================*/ +/* None */ + +/*============================================================================* + Private Data + *============================================================================*/ +/* None */ + +/*============================================================================* + Public Function Implementations + *============================================================================*/ + + +/*----------------------------------------------------------------------------* + * NAME + * string_array_contains_string() + * + * DESCRIPTION + * Checks the strings in the indicated array to see if it contains a + * particulr value. Can check a particular index or the whole array. + * Can perform an exact match or check wether one of the strings simply + * contains the value. + * + * RETURNS + * TRUE <=> includes indicated value, FALSE else. + *----------------------------------------------------------------------------*/ + +bool_t string_array_contains_string( + VSTRARRAY_T *p_strarray, /* String array */ + char **pp_string_found, /* String found */ + uint32_t index, /* Which entry, (-1) => any */ + const char *p_string, /* The string we're looking for */ + bool_t exact /* Exact or partial match */ + ) +{ + bool_t ret = FALSE; + uint32_t i; + uint32_t s, e; + + if (index == (-1)) + { + s = 0; + e = p_strarray->n_strings; + } + else + { + s = index; + e = index + 1; + } + + for (i = s;!ret && (i < e);i++) + { + if ((i < p_strarray->n_strings) && p_strarray->pp_strings[i]) + { + if (exact) + { + if (0 == p_stricmp(p_strarray->pp_strings[i], p_string)) + ret = TRUE; + } + else + { + if (p_strstr(p_strarray->pp_strings[i], p_string)) + ret = TRUE; + } + } + + if (ret && pp_string_found) + { + *pp_string_found = p_strarray->pp_strings[i]; + } + } + + return ret; +} + + + + + + +/*----------------------------------------------------------------------------* + * NAME + * add_string_to_array() + * + * DESCRIPTION + * Append string to indicated array. + * + * RETURNS + * TRUE <=> allocation OK, FALSE else. + *----------------------------------------------------------------------------*/ + +bool_t add_string_to_array( + VSTRARRAY_T *p_strarray, /* String array */ + const char *p_string /* String to add */ + ) +{ + char **pp_new; + bool_t ret = FALSE; + + pp_new = vf_realloc(p_strarray->pp_strings, sizeof(char *) * (1 + p_strarray->n_strings)); + + if (pp_new) + { + if (p_string) + { + uint32_t l; + char *p_strcopy; + + l = p_strlen(p_string); + + p_strcopy = vf_malloc(1 + l); + + if (p_strcopy) + { + p_strcpy(p_strcopy, p_string); + + pp_new[p_strarray->n_strings] = p_strcopy; + + ret = TRUE; + } + else + { + vf_free(pp_new); + } + } + else + { + pp_new[p_strarray->n_strings] = NULL; + + ret = TRUE; + } + + if (ret) + { + p_strarray->n_strings += 1; + p_strarray->pp_strings = pp_new; + } + } + + return ret; +} + + + + + +/*----------------------------------------------------------------------------* + * NAME + * free_string_array_contents() + * + * DESCRIPTION + * Delete contents of a string array. The structure itself is not free()d. + * + * RETURNS + * (none) + *----------------------------------------------------------------------------*/ + +void free_string_array_contents( + VSTRARRAY_T *p_strarray /* String array */ + ) +{ + if (p_strarray && p_strarray->pp_strings) + { + uint32_t i; + + for (i = 0;i < p_strarray->n_strings;i++) + { + if (p_strarray->pp_strings[i]) + { + vf_free(p_strarray->pp_strings[i]); + p_strarray->pp_strings[i] = NULL; + } + } + + vf_free(p_strarray->pp_strings); + p_strarray->pp_strings = NULL; + + p_strarray->n_strings = 0; + } +} + + + + + + + +/*----------------------------------------------------------------------------* + * NAME + * append_to_curr_string() + * + * DESCRIPTION + * Append characters to the current string in a string array. + * + * RETURNS + * TRUE <=> allocation OK, FALSE else. + *----------------------------------------------------------------------------*/ + +bool_t append_to_curr_string( + VSTRARRAY_T *p_strarray, /* String array */ + uint32_t *p_length, /* Pointer to length, NULL if zero terminated */ + const char *p_chars, /* Characters to append */ + uint32_t numchars /* Number of characters */ + ) +{ + bool_t ret = TRUE; + + if (p_strarray && !p_strarray->pp_strings) + { + ret = add_string_to_array(p_strarray, ""); + } + + if (ret) + { + ret = append_to_pointer(&(p_strarray->pp_strings[p_strarray->n_strings - 1]), p_length, p_chars, numchars); + } + + return ret; +} + + + + + + + +/*----------------------------------------------------------------------------* + * NAME + * append_to_pointer() + * + * DESCRIPTION + * Append characters to indicated pointer. Handles both NULL terminated + * strings (for simple 7-bit values) and buffer/length pairs. Passing + * the p_length field indicates that we're building up binary data. + * + * RETURNS + * TRUE <=> allocation OK, FALSE else. + *----------------------------------------------------------------------------*/ + +bool_t append_to_pointer( + char **pp_string, /* String we're appending to */ + uint32_t *p_length, /* Pointer to length, NULL if ZT */ + const char *p_chars, /* Chars we're appending */ + int numchars /* Number of chars we're appending */ + ) +{ + bool_t ok = FALSE; + + if (pp_string) + { + int newlen, currlen; + char *p_new; + + newlen = numchars; + + if (*pp_string) + { + currlen = p_length ? *p_length : p_strlen(*pp_string); + + newlen += currlen; + } + else + { + currlen = 0; + } + + p_new = vf_realloc(*pp_string, newlen + (p_length ? 0 : 1)); + + if (p_new) + { + p_memcpy(p_new + currlen, p_chars, numchars); + + if (p_length) + { + *p_length = newlen; + } + else + { + p_new[newlen] = '\0'; + } + + *pp_string = p_new; + ok = TRUE; + } + } + + return ok; +} + + + + + + + +/*----------------------------------------------------------------------------* + * NAME + * set_string_array_entry() + * + * DESCRIPTION + * Set indicated entry in a string array. + * + * RETURNS + * TRUE <=> allocation OK, FALSE else. + *----------------------------------------------------------------------------*/ + +bool_t set_string_array_entry( + VSTRARRAY_T *p_strarray, /* String array */ + const char *p_string, /* String to insert */ + uint32_t n_string /* Insertion point */ + ) +{ + bool_t ret = FALSE; + + if (n_string < p_strarray->n_strings) + { + if (p_strarray->pp_strings[n_string]) + { + vf_free(p_strarray->pp_strings[n_string]); + p_strarray->pp_strings[n_string] = NULL; + } + + if (p_string) + { + uint32_t len = p_strlen(p_string); + + p_strarray->pp_strings[n_string] = vf_malloc(1 + len); + + if (p_strarray->pp_strings[n_string]) + { + p_strcpy(p_strarray->pp_strings[n_string], p_string); + + ret = TRUE; + } + } + else + { + /* NULL = "delete" */ + + ret = TRUE; + } + } + + return ret; +} + + +/*============================================================================* + Private Function Implementations + *============================================================================*/ +/* None */ + +/*============================================================================* + End Of File + *============================================================================*/ diff --git a/src/vf_string_arrays.h b/src/vf_string_arrays.h new file mode 100644 index 0000000..252da03 --- /dev/null +++ b/src/vf_string_arrays.h @@ -0,0 +1,177 @@ +/******************************************************************************* + + (C) Nick Marley, 2001 - + + This software is distributed under the GNU Lesser General Public Licence. + Please read and understand the comments at the top of vf_iface.h before use! + +FILE + $Workfile: vf_internals.h $ + $Revision: 1.2 $ + $Author: tilda $ + +ORIGINAL AUTHOR + Nick Marley + +DESCRIPTION + Utility functions handling string arrays - the VSTRARRAY_T type. + +REFERENCES + (none) + +MODIFICATION HISTORY + * $Log: vf_string_arrays.h,v $ + * Revision 1.2 2002/11/02 18:29:26 tilda + * IID485157 - UI does character conversion based on CHARSET property. + * + * Revision 1.1 2002/10/26 15:57:11 tilda + * Initial Version + * + *******************************************************************************/ + +#ifndef _VF_STRING_ARRAYS_H_ +#define _VF_STRING_ARRAYS_H_ + +#ifndef NORCSID +static const char vf_string_arrays_h_vss_id[] = "$Header: /cvsroot/vformat/src/vformat/src/vf_string_arrays.h,v 1.2 2002/11/02 18:29:26 tilda Exp $"; +#endif + +/*=============================================================================* + Public Includes + *============================================================================*/ +/* None */ + +/*=============================================================================* + Public Defines + *============================================================================*/ +/* None */ + +/*=============================================================================* + Public Types + *============================================================================*/ +/* None */ + +/*=============================================================================* + Public Functions + *============================================================================*/ + + +/*----------------------------------------------------------------------------* + * NAME + * string_array_contains_string() + * + * DESCRIPTION + * Checks the strings in the indicated array to see if it contains a + * particulr value. Can check a particular index or the whole array. + * Can perform an exact match or check wether one of the strings simply + * contains the value. + * + * RETURNS + * TRUE <=> includes indicated value, FALSE else. + *----------------------------------------------------------------------------*/ + +extern bool_t string_array_contains_string( + VSTRARRAY_T *p_strarray, /* String array */ + char **pp_string_found, /* String found */ + uint32_t index, /* Which entry, (-1) => any */ + const char *p_string, /* The string we're looking for */ + bool_t exact /* Exact or partial match */ + ); + + +/*----------------------------------------------------------------------------* + * NAME + * add_string_to_array() + * + * DESCRIPTION + * Append string to indicated array. + * + * RETURNS + * TRUE <=> allocation OK, FALSE else. + *----------------------------------------------------------------------------*/ + +extern bool_t add_string_to_array( + VSTRARRAY_T *p_strarray, /* String array */ + const char *p_string /* String to add */ + ); + + +/*----------------------------------------------------------------------------* + * NAME + * free_string_array_contents() + * + * DESCRIPTION + * Delete contents of a string array. The structure itself is not free()d. + * + * RETURNS + * (none) + *----------------------------------------------------------------------------*/ + +extern void free_string_array_contents( + VSTRARRAY_T *p_strarray /* String array */ + ); + + +/*----------------------------------------------------------------------------* + * NAME + * append_to_curr_string() + * + * DESCRIPTION + * Append characters to the current string in a string array. + * + * RETURNS + * TRUE <=> allocation OK, FALSE else. + *----------------------------------------------------------------------------*/ + +extern bool_t append_to_curr_string( + VSTRARRAY_T *p_strarray, /* String array */ + uint32_t *p_length, /* Pointer to length, NULL if zero terminated */ + const char *p_chars, /* Characters to append */ + uint32_t numchars /* Number of characters */ + ); + + +/*----------------------------------------------------------------------------* + * NAME + * append_to_pointer() + * + * DESCRIPTION + * Append characters to indicated pointer. Handles both NULL terminated + * strings (for simple 7-bit values) and buffer/length pairs. Passing + * the p_length field indicates that we're building up binary data. + * + * RETURNS + * TRUE <=> allocation OK, FALSE else. + *----------------------------------------------------------------------------*/ + +extern bool_t append_to_pointer( + char **pp_string, /* String we're appending to */ + uint32_t *p_length, /* Pointer to length, NULL if ZT */ + const char *p_chars, /* Chars we're appending */ + int numchars /* Number of chars we're appending */ + ); + + +/*----------------------------------------------------------------------------* + * NAME + * set_string_array_entry() + * + * DESCRIPTION + * Set indicated entry in a string array. + * + * RETURNS + * TRUE <=> allocation OK, FALSE else. + *----------------------------------------------------------------------------*/ + +extern bool_t set_string_array_entry( + VSTRARRAY_T *p_strarray, /* String array */ + const char *p_string, /* String to insert */ + uint32_t n_string /* Insertion point */ + ); + + +/*=============================================================================* + End of file + *============================================================================*/ + +#endif /*_VF_STRING_ARRAYS_H_*/ diff --git a/src/vf_strings.c b/src/vf_strings.c new file mode 100644 index 0000000..204a188 --- /dev/null +++ b/src/vf_strings.c @@ -0,0 +1,472 @@ +/****************************************************************************** + + (C) Nick Marley, 2001 - + + This software is distributed under the GNU Lesser General Public Licence. + Please read and understand the comments at the top of vf_iface.h before use! + +FILE + $Workfile$ + $Revision: 1.9 $ + $Author: tilda $ + +ORIGINAL AUTHOR + Nick Marley + +DESCRIPTION + String handling functions. The library uses the p_ functions (where hopefully + the 'p' stands for 'portable') and they are provided here in terms of C runtime + functions or implemented explicitly. + +REFERENCES + (none) + +MODIFICATION HISTORY + * $Log: vf_strings.c,v $ + * Revision 1.9 2002/11/15 09:15:00 tilda + * IID638823 - Various portability issues. + * + * Revision 1.8 2002/10/26 16:09:23 tilda + * IID629125 - Ensure string functions used are portable. + * + * Revision 1.7 2002/10/08 21:45:07 tilda + * IID620473 - reduce c-runtime dependencies. + * + * Revision 1.6 2002/10/08 21:11:36 tilda + * Remove common.h. + * + * Revision 1.5 2001/11/05 21:07:19 tilda + * Various changes for initial version of vfedit. + * + * Revision 1.4 2001/10/14 20:42:37 tilda + * Addition of group searching. + * + * Revision 1.3 2001/10/13 16:22:08 tilda + * Introduce VBINDATA_T and VOBJDATA_T to tidy up internals. + * + * Revision 1.2 2001/10/13 14:58:56 tilda + * Tidy up version headers, add vf_strings.h where needed. + * + * Revision 1.1 2001/10/13 14:50:33 tilda + * Add string array code to unify handling of names / values. + * + *******************************************************************************/ + +#ifndef NORCSID +static const char vf_strings_c_vss_id[] = "$Header: /cvsroot/vformat/src/vformat/src/vf_strings.c,v 1.9 2002/11/15 09:15:00 tilda Exp $"; +#endif + +/*=============================================================================* + ANSI C & System-wide Header Files + *=============================================================================*/ + +#include <common/types.h> + +#include <ctype.h> +#include <string.h> + +/*============================================================================* + Interface Header Files + *============================================================================*/ + +#include "vformat/vf_iface.h" + +/*============================================================================* + Local Header File + *============================================================================*/ + +#include "vf_config.h" +#include "vf_internals.h" +#include "vf_strings.h" + +/*============================================================================* + Public Data + *============================================================================*/ +/* None */ + +/*============================================================================* + Private Defines + *============================================================================*/ + + +/*============================================================================* + Private Data Types + *============================================================================*/ +/* None */ + +/*============================================================================* + Private Function Prototypes + *============================================================================*/ +/* None */ + +/*============================================================================* + Private Data + *============================================================================*/ +/* None */ + +/*============================================================================* + Public Function Implementations + *============================================================================*/ + + +/*----------------------------------------------------------------------------* + * NAME + * p_strlen() + * + * DESCRIPTION + * Find length of string. + * + * RETURNS + * Length of strings. + *----------------------------------------------------------------------------*/ + +int p_strlen( + const char *p_string /* String to measure */ + ) +{ +#if defined(HAVE_STRLEN) + return strlen(p_string); +#else + int len = 0; + + while (*p_string) + { + p_string++; + len++; + } + + return len; +#endif +} + + + + + +/*----------------------------------------------------------------------------* + * NAME + * p_strcpy() + * + * DESCRIPTION + * Copy string to buffer. + * + * RETURNS + * Pointer to buffer. + *----------------------------------------------------------------------------*/ + +char *p_strcpy( + char *p_string1, /* Buffer to copy to */ + const char *p_string2 /* String to copy */ + ) +{ +#if defined(HAVE_STRCPY) + return strcpy(p_string1, p_string2); +#else + char *p_return = p_string1; + + while ((*p_string1++ = *p_string2++)) + ; + + return p_return; +#endif +} + + + + + + +/*----------------------------------------------------------------------------* + * NAME + * p_strcmp() + * + * DESCRIPTION + * Case sensitive string comparison. + * + * RETURNS + * 0<=>strings match, !=0 else. + *----------------------------------------------------------------------------*/ + +int p_strcmp( + const char *p_string1, + const char *p_string2 + ) +{ +#if defined(HAVE_STRCMP) + return strcmp(p_string1, p_string2); +#else + while (*p_string1 && (*p_string1 == *p_string2)) + { + p_string1++; + p_string2++; + } + + return (*(unsigned char *)p_string1) - (*(unsigned char *)p_string2); +#endif +} + + + + + + +/*----------------------------------------------------------------------------* + * NAME + * p_strcat() + * + * DESCRIPTION + * Append one string to another. + * + * RETURNS + * Pointer to resulting string. + *----------------------------------------------------------------------------*/ + +char *p_strcat( + char *p_string1, /* String to append to */ + const char *p_string2 /* String to append */ + ) +{ +#if defined(HAVE_STRCAT) + return strcat(p_string1, p_string2); +#else + char *p_return = p_string1; + + while (*p_string1) + p_string1++; + + while ((*p_string1++ = *p_string2++)) + ; + + return p_return; +#endif +} + + + + + + +/*----------------------------------------------------------------------------* + * NAME + * p_strstr() + * + * DESCRIPTION + * Case sensitive string searching function. + * + * RETURNS + * Pointer to position "looked for" has been located or NULL if !found. + *----------------------------------------------------------------------------*/ + +char *p_strstr( + const char *p_searched, /* Buffer searched */ + const char *p_lookedfor /* String we're looking for */ + ) +{ +#if defined(HAVE_STRSTR) + return strstr(p_searched, p_lookedfor); +#else + if (*p_searched == 0) + { + if (*p_lookedfor) + { + return (char *)NULL; + } + + return (char *)p_searched; + } + + while (*p_searched) + { + uint32_t i; + + for (i = 0;;i++) + { + if (p_lookedfor[i] == 0) + { + return (char *)p_searched; + } + + if (p_lookedfor[i] != p_searched[i]) + { + break; + } + } + + p_searched++; + } + + return (char *)NULL; +#endif +} + + + + + + +/*----------------------------------------------------------------------------* + * NAME + * p_stricmp() + * + * DESCRIPTION + * Case insensitive string comparison function. + * + * RETURNS + * 0<=>strings match, !=0 else. + *----------------------------------------------------------------------------*/ + +int p_stricmp( + const char *p_string1, /* First string */ + const char *p_string2 /* Second string */ + ) +{ +#if defined(HAVE_STRCASECMP) + return strcasecmp(p_string1, p_string2); +#elif defined(HAVE_STRICMP) + return stricmp(p_string1, p_string2); +#else + while (*p_string1 && (tolower(*p_string1) == tolower(*p_string2))) + { + p_string1++; + p_string2++; + } + + return tolower(*(unsigned char *)p_string1) - tolower(*(unsigned char *)p_string2); +#endif +} + + + + + + + +/*----------------------------------------------------------------------------* + * NAME + * p_stristr() + * + * DESCRIPTION + * Case insensitive string searching function. + * + * RETURNS + * Pointer to position "looked for" has been located or NULL if !found. + *----------------------------------------------------------------------------*/ + +char *p_stristr( + const char *p_searched, /* Buffer searched */ + const char *p_lookedfor /* String we're looking for */ + ) +{ +#if defined(HAVE_STRISTR) + return strstr(p_searched, p_lookedfor); +#else + if (*p_searched == 0) + { + if (*p_lookedfor) + { + return (char *)NULL; + } + + return (char *)p_searched; + } + + while (*p_searched) + { + uint32_t i; + + for (i = 0;;i++) + { + if (p_lookedfor[i] == 0) + { + return (char *)p_searched; + } + + if (tolower(p_lookedfor[i]) != tolower(p_searched[i])) + { + break; + } + } + + p_searched++; + } + + return (char *)NULL; +#endif +} + + + + + + +/*----------------------------------------------------------------------------* + * NAME + * p_memcpy() + * + * DESCRIPTION + * Copy characetrs between buffers. No checks on overlap. + * + * RETURNS + * (none) + *----------------------------------------------------------------------------*/ + +void p_memcpy( + void *p_destination, /* Pointer to buffer */ + const void *p_source, /* Source of copy */ + uint32_t length /* Number of characters to copy */ + ) +{ +#if defined(HAVE_MEMCPY) + memcpy(p_destination, p_source, length); +#else + uint8_t *p_dst = (uint8_t *)p_destination; + uint8_t *p_src = (uint8_t *)p_source; + + while (length--) + { + *p_dst++ = *p_src++; + } +#endif +} + + + + + + +/*----------------------------------------------------------------------------* + * NAME + * p_memset() + * + * DESCRIPTION + * Fill buffer with indicated character. + * + * RETURNS + * (none) + *----------------------------------------------------------------------------*/ + +void p_memset( + void *p_destination, /* Pointer to buffer */ + uint8_t v, /* Character to fill with */ + uint32_t length /* Length of buffer to set */ + ) +{ +#if defined(HAVE_MEMSET) + memset(p_destination, v, length); +#else + uint8_t *p_dst = (uint8_t *)p_destination; + + while (length--) + *p_dst++ = v; +#endif +} + + +/*============================================================================* + Private Function Implementations + *============================================================================*/ +/* None */ + +/*============================================================================* + End Of File + *============================================================================*/ diff --git a/src/vf_strings.h b/src/vf_strings.h new file mode 100644 index 0000000..29ccd78 --- /dev/null +++ b/src/vf_strings.h @@ -0,0 +1,230 @@ +/******************************************************************************* + + (C) Nick Marley, 2001 - + + This software is distributed under the GNU Lesser General Public Licence. + Please read and understand the comments at the top of vf_iface.h before use! + +FILE + $Workfile$ + $Revision: 1.6 $ + $Author: tilda $ + +ORIGINAL AUTHOR + Nick Marley + +DESCRIPTION + String handling functions. The library uses the p_ functions (where hopefully + the 'p' stands for 'portable') and they are provided here in terms of C runtime + functions or implemented explicitly. + +REFERENCES + (none) + +MODIFICATION HISTORY + * $Log: vf_strings.h,v $ + * Revision 1.6 2002/10/26 16:09:23 tilda + * IID629125 - Ensure string functions used are portable. + * + * Revision 1.5 2002/10/08 21:27:20 tilda + * Correct #endif directive. + * + * Revision 1.4 2001/11/05 21:07:19 tilda + * Various changes for initial version of vfedit. + * + * Revision 1.3 2001/10/14 20:42:37 tilda + * Addition of group searching. + * + * Revision 1.2 2001/10/13 14:58:56 tilda + * Tidy up version headers, add vf_strings.h where needed. + * + * Revision 1.1 2001/10/13 14:50:33 tilda + * Add string array code to unify handling of names / values. + * + *******************************************************************************/ + +#ifndef _VF_STRINGS_H_ +#define _VF_STRINGS_H_ + +#ifndef NORCSID +static const char vf_strings_h_vss_id[] = "$Header: /cvsroot/vformat/src/vformat/src/vf_strings.h,v 1.6 2002/10/26 16:09:23 tilda Exp $"; +#endif + +/*=============================================================================* + Public Includes + *============================================================================*/ +/* None */ + +/*=============================================================================* + Public Defines + *============================================================================*/ +/* None */ + +/*=============================================================================* + Public Types + *============================================================================*/ +/* None */ + +/*=============================================================================* + Public Functions + *============================================================================*/ + + +/*----------------------------------------------------------------------------* + * NAME + * p_strlen() + * + * DESCRIPTION + * Find length of string. + * + * RETURNS + * Length of strings. + *----------------------------------------------------------------------------*/ + +extern int p_strlen( + const char *p_string /* String to measure */ + ); + + +/*----------------------------------------------------------------------------* + * NAME + * p_strcpy() + * + * DESCRIPTION + * Copy string to buffer. + * + * RETURNS + * Pointer to buffer. + *----------------------------------------------------------------------------*/ + +extern char *p_strcpy( + char *p_string1, /* Buffer to copy to */ + const char *p_string2 /* String to copy */ + ); + + +/*----------------------------------------------------------------------------* + * NAME + * p_strcmp() + * + * DESCRIPTION + * Case sensitive string comparison. + * + * RETURNS + * 0<=>strings match, !=0 else. + *----------------------------------------------------------------------------*/ + +extern int p_strcmp( + const char *p_string1, + const char *p_string2 + ); + + +/*----------------------------------------------------------------------------* + * NAME + * p_strcat() + * + * DESCRIPTION + * Append one string to another. + * + * RETURNS + * Pointer to resulting string. + *----------------------------------------------------------------------------*/ + +extern char *p_strcat( + char *p_string1, /* String to append to */ + const char *p_string2 /* String to append */ + ); + + +/*----------------------------------------------------------------------------* + * NAME + * p_strstr() + * + * DESCRIPTION + * Case sensitive string searching function. + * + * RETURNS + * Pointer to position "looked for" has been located or NULL if !found. + *----------------------------------------------------------------------------*/ + +extern char *p_strstr( + const char *p_searched, /* Buffer searched */ + const char *p_lookedfor /* String we're looking for */ + ); + + +/*----------------------------------------------------------------------------* + * NAME + * p_stricmp() + * + * DESCRIPTION + * Case insensitive string comparison function. + * + * RETURNS + * 0<=>strings match, !=0 else. + *----------------------------------------------------------------------------*/ + +extern int p_stricmp( + const char *p_string1, /* First string */ + const char *p_string2 /* Second string */ + ); + + +/*----------------------------------------------------------------------------* + * NAME + * p_stristr() + * + * DESCRIPTION + * Case insensitive string searching function. + * + * RETURNS + * Pointer to position "looked for" has been located or NULL if !found. + *----------------------------------------------------------------------------*/ + +extern char *p_stristr( + const char *p_searched, /* Buffer searched */ + const char *p_lookedfor /* String we're looking for */ + ); + +/*----------------------------------------------------------------------------* + * NAME + * p_memcpy() + * + * DESCRIPTION + * Copy characetrs between buffers. No checks on overlap. + * + * RETURNS + * (none) + *----------------------------------------------------------------------------*/ + +extern void p_memcpy( + void *p_destination, /* Pointer to buffer */ + const void *p_source, /* Source of copy */ + uint32_t length /* Number of characters to copy */ + ); + + +/*----------------------------------------------------------------------------* + * NAME + * p_memset() + * + * DESCRIPTION + * Fill buffer with indicated character. + * + * RETURNS + * (none) + *----------------------------------------------------------------------------*/ + +extern void p_memset( + void *p_destination, /* Pointer to buffer */ + uint8_t v, /* Character to fill with */ + uint32_t length /* Length of buffer to set */ + ); + + +/*=============================================================================* + End of file + *============================================================================*/ + +#endif /*_VF_STRINGS_H_*/ diff --git a/src/vf_writer.c b/src/vf_writer.c new file mode 100644 index 0000000..ef3298a --- /dev/null +++ b/src/vf_writer.c @@ -0,0 +1,616 @@ +/****************************************************************************** + + (C) Nick Marley, 2001 - + + This software is distributed under the GNU Lesser General Public Licence. + Please read and understand the comments at the top of vf_iface.h before use! + +FILE + $Workfile$ + $Revision: 1.12 $ + $Author: tilda $ + +ORIGINAL AUTHOR + Nick Marley. + +DESCRIPTION + Code for writing vformat files. This is temporary as it is not based + around a state machine for converting the object to a character stream. + +REFERENCES + (none) + +MODIFICATION HISTORY + * $Log: vf_writer.c,v $ + * Revision 1.12 2002/11/03 18:43:16 tilda + * IID619851 - Update and check headers and function prototypes. + * + * Revision 1.11 2002/11/02 08:56:17 tilda + * Start of internationalisation changes. + * + * Revision 1.10 2002/10/26 16:09:23 tilda + * IID629125 - Ensure string functions used are portable. + * + * Revision 1.9 2002/10/08 21:45:07 tilda + * IID620473 - reduce c-runtime dependencies. + * + * Revision 1.8 2002/10/08 21:11:35 tilda + * Remove common.h. + * + * Revision 1.7 2002/02/24 17:10:34 tilda + * Add API for "is modified" functionality. + * + * Revision 1.6 2001/12/13 06:45:35 tilda + * IID488021 - Various bugs with quoted printable format. + * + * Revision 1.5 2001/11/18 21:45:10 tilda + * Add newline after BASE64 encodings + * + * Revision 1.4 2001/11/14 22:36:55 tilda + * Add parameter to vf_find_prop_qual_index() + * + * Revision 1.3 2001/11/06 22:51:05 tilda + * Supporting access functions for image selection / deletion. + * + * Revision 1.2 2001/10/24 18:56:29 tilda + * Tidy headers after import. Fix include path in release build. + * + * Revision 1.1 2001/10/24 18:34:35 tilda + * Initial Version. + * + *******************************************************************************/ + +#ifndef NORCSID +static const char vf_writer_c_vss_id[] = "$Header: /cvsroot/vformat/src/vformat/src/vf_writer.c,v 1.12 2002/11/03 18:43:16 tilda Exp $"; +#endif + +/*=============================================================================* + ANSI C & System-wide Header Files + *=============================================================================*/ + +#include <common/types.h> + +#include <stdio.h> +#include <ctype.h> + +/*============================================================================* + Interface Header Files + *============================================================================*/ + +#include <vformat/vf_iface.h> + +/*============================================================================* + Local Header File + *============================================================================*/ + +#include "vf_config.h" +#include "vf_internals.h" +#include "vf_malloc.h" +#include "vf_strings.h" + +/*============================================================================* + Public Data + *============================================================================*/ +/* None */ + +/*============================================================================* + Private Defines + *============================================================================*/ + +#define QPMAXPERLINE (76) +#define BASE64PERLINE (64) + +/*============================================================================* + Private Data Types + *============================================================================*/ +/* None */ + +/*============================================================================* + Private Function Prototypes + *============================================================================*/ + +static bool_t write_name_fields( + FILE *fp, + uint32_t *p_charsonline, + VPROP_T *p_prop + ); + +static void write_base64_chars( + FILE *fp, /* File we're writing */ + uint8_t *s, /* Pointer to buffer */ + uint32_t len /* buffer length */ + ); + +static bool_t write_quoted_printable( + FILE *fp, /* File we're writing */ + uint8_t *s, /* Pointer to buffer */ + uint32_t *p_charsonline /* Num on line so far */ + ); + +static char char_to_base64( + uint8_t b /* Byte to convert */ + ); + +static bool_t qp_needs_quoting( + uint8_t c /* Char to test */ + ); + +static bool_t write_vobject_to_file( + FILE *fp, + VOBJECT_T *p_object, + bool_t write_all + ); + +/*============================================================================* + Private Data + *============================================================================*/ + +static const char szEndOfLine[3] = { 0x0D, 0x0A, 0x00 }; + +/*============================================================================* + Public Function Implementations + *============================================================================*/ + + + + +/*----------------------------------------------------------------------------* + * NAME + * vf_write_file() + * + * DESCRIPTION + * Write indicated vobject to file. + * + * RETURNS + * TRUE <=> written OK, FALSE else. + *----------------------------------------------------------------------------*/ + +bool_t vf_write_file( + const char *p_name, /* Outpt filename */ + VF_OBJECT_T *p_object, /* The object to write */ + bool_t write_all /* Should write p_next as well? */ + ) +{ + FILE *fp; + bool_t ret = FALSE; + + fp = fopen(p_name, "wb"); + + if (fp) + { + ret = write_vobject_to_file(fp, (VOBJECT_T *)p_object, write_all); + + if (0 == fclose(fp)) + { + /* as is */ + } + else + { + ret = FALSE; + } + } + + return ret; +} + + + + + + +/*============================================================================* + Private Function Implementations + *============================================================================*/ + + +/*----------------------------------------------------------------------------* + * NAME + * write_vobject_to_file() + * + * DESCRIPTION + * Write each field of the indicated vformat object to the indicated FILE* + * invoking write_vobject_to_file() recursively if a field is found which + * contains a vformat object. + * + * RETURNS + * TRUE <=> file acces OK, FALSE else. + *----------------------------------------------------------------------------*/ + +bool_t write_vobject_to_file( + FILE *fp, + VOBJECT_T *p_object, + bool_t write_all + ) +{ + bool_t ret = TRUE; + + VOBJECT_T *p_obj = (VOBJECT_T *)p_object; + VPROP_T *p_props = p_obj->p_props; + + fprintf(fp, "%s:%s", VFP_BEGIN, p_obj->p_type); + + fprintf(fp, szEndOfLine); + + for (;NULL != p_props;p_props = p_props->p_next) + { + uint32_t charsonline; + + switch (p_props->value.encoding) + { + default: + case VF_ENC_7BIT: + { + ret = write_name_fields(fp, &charsonline, p_props); + + if (ret) + { + uint32_t n; + + for (n = 0;ret && (n < p_props->value.v.s.n_strings);n++) + { + if (n) + fprintf(fp, ";"); + + if (p_props->value.v.s.pp_strings[n]) + { + fprintf(fp, "%s", p_props->value.v.s.pp_strings[n]); + } + } + } + } + break; + + case VF_ENC_BASE64: + { + ret = write_name_fields(fp, &charsonline, p_props); + + if (ret) + { + write_base64_chars(fp, p_props->value.v.b.p_buffer, p_props->value.v.b.n_bufsize); + } + } + break; + + case VF_ENC_QUOTEDPRINTABLE: + { + ret = write_name_fields(fp, &charsonline, p_props); + + if (ret) + { + uint32_t n; + + for (n = 0;ret && (n < p_props->value.v.s.n_strings);n++) + { + if (n) + fprintf(fp, ";"); + + if (p_props->value.v.s.pp_strings[n]) + { + ret = write_quoted_printable(fp, p_props->value.v.s.pp_strings[n], &charsonline); + } + } + } + } + break; + + case VF_ENC_VOBJECT: + { + write_vobject_to_file(fp, p_props->value.v.o.p_object, TRUE); + } + break; + } + + if (VF_ENC_VOBJECT != p_props->value.encoding) + fprintf(fp, szEndOfLine); + } + + fprintf(fp, "%s:%s", VFP_END, p_obj->p_type); + + fprintf(fp, szEndOfLine); + + if (ret && p_obj->p_next && write_all) + { + ret = write_vobject_to_file(fp, p_obj->p_next, TRUE); + } + + p_obj->modified = !ret; + + return ret; +} + + + + + + +/*----------------------------------------------------------------------------* + * NAME + * write_base64_chars() + * + * DESCRIPTION + * Write the indicated binary data stream out to FILE* using BASE64 + * encoding. + * + * RETURNS + * (none) + *----------------------------------------------------------------------------*/ + +static void write_base64_chars( + FILE *fp, /* File we're writing */ + uint8_t *p_buffer, /* Pointer to buffer */ + uint32_t n_chars /* buffer length */ + ) +{ + uint32_t posn; + char quad[5]; + uint8_t b; + + quad[4] = 0; + + for (posn = 0;posn < n_chars;) + { + int i; + uint32_t triplet = 0; + uint8_t bits = 0; + + /* Form triplet from data if available */ + + for (i = 0;i < 3;i++, posn++) + { + triplet = triplet << 8; + + if (posn < n_chars) + { + triplet |= *(p_buffer + posn); + + bits += 8; + } + } + + /* Convert the triplet to text */ + + for (i = 0;i < 4;i++) + { + b = (uint8_t)((0xFC0000 & triplet) >> 18); + + triplet = triplet << 6; + + quad[i] = (i <= (bits/6)) ? char_to_base64(b) : '='; + } + + /* Output the text prefixed by newlines if necessary */ + + if (((posn - 3) % (BASE64PERLINE / 4)) == 0) + { + fprintf(fp, szEndOfLine); + fprintf(fp, " "); + } + + fprintf(fp, "%s", quad); + } + + fprintf(fp, szEndOfLine); +} + + + + + +/*----------------------------------------------------------------------------* + * NAME + * write_quoted_printable() + * + * DESCRIPTION + * Write the indicated field back to the file in quoted printable format. + * + * RETURNS + * (none) + *----------------------------------------------------------------------------*/ + +static bool_t write_quoted_printable( + FILE *fp, /* File we're writing */ + uint8_t *s, /* Pointer to buffer */ + uint32_t *p_charsonline /* Num on line so far */ + ) +{ + uint32_t i; + uint32_t charsonline = *p_charsonline; + + for (i = 0;s;i++) + { + uint8_t c = s[i]; + + if ('\0' == c) + { + break; + } + else + { + if (3 + charsonline > QPMAXPERLINE) + { + fprintf(fp, "="); + fprintf(fp, szEndOfLine); + charsonline = 0; + } + + if (qp_needs_quoting(c)) + { + fprintf(fp, "=%02X", c); + charsonline += 3; + + if (0x0D == c) + { + fprintf(fp, "="); + fprintf(fp, szEndOfLine); + charsonline = 0; + } + } + else + { + fprintf(fp, "%c", c); + charsonline += 1; + } + } + } + + *p_charsonline = charsonline; + + return TRUE; +} + + + + +/*----------------------------------------------------------------------------* + * NAME + * char_to_base64() + * + * DESCRIPTION + * Converts byte to BASE64. + * + * RETURNS + * Character encoded. + *----------------------------------------------------------------------------*/ + +static char char_to_base64( + uint8_t b /* Byte to convert */ + ) +{ + char ret; + + if (b < 26) + { + ret = (char)b + 'A'; + } + else + if (b < 52) + { + ret = (char)(b - 26) + 'a'; + } + else + if (b < 62) + { + ret = (char)(b - 52) + '0'; + } + else + if (b == 62) + { + ret = '+'; + } + else + { + ret = '/'; + } + + return ret; +} + + + + +/*----------------------------------------------------------------------------* + * NAME + * qp_needs_quoting() + * + * DESCRIPTION + * Works out of 'c' needs quoting in quoted printable format. + * + * RETURNS + * TRUE <=> need to quote. + *----------------------------------------------------------------------------*/ + +static bool_t qp_needs_quoting( + uint8_t c /* Char to test */ + ) +{ + /* TBD - look in the RFC?! */ + + bool_t needs_quoting = FALSE; + + switch (c) + { + case ' ': + case ',': + case '-': + case '.': + case '!': + case '?': + case '\'': + return FALSE; + + default: + if (isalnum(c)) + needs_quoting = FALSE; + else + needs_quoting = TRUE; + break; + } + + return needs_quoting; +} + + + + + + +/*----------------------------------------------------------------------------* + * NAME + * write_name_fields() + * + * DESCRIPTION + * Write name fields to file. + * + * RETURNS + * TRUE <=> OK so far. + *----------------------------------------------------------------------------*/ + +bool_t write_name_fields( + FILE *fp, + uint32_t *p_charsonline, + VPROP_T *p_prop + ) +{ + VSTRARRAY_T *p_strarray = &(p_prop->name); + bool_t ret = FALSE; + + *p_charsonline = 0; + + if (p_prop->p_group) + { + *p_charsonline += fprintf(fp, "%s.", p_prop->p_group); + } + + if (p_strarray->pp_strings) + { + uint32_t i; + + for (i = 0;i < p_strarray->n_strings;i++) + { + char *p_name_field = p_strarray->pp_strings[i]; + + if (p_name_field && (0 < p_strlen(p_name_field))) + { + if (0 < i) + { + fprintf(fp, ";"); + *p_charsonline += 1; + } + + *p_charsonline += fprintf(fp, "%s", p_name_field); + } + } + + fprintf(fp, ":"); + *p_charsonline += 1; + + ret = TRUE; + } + + return ret; +} + + +/*============================================================================* + End Of File + *============================================================================*/ |