From 24c08b47d65eb7a7174b04852a94578beeea05be Mon Sep 17 00:00:00 2001 From: cdfrey Date: Fri, 26 Oct 2007 22:21:02 +0000 Subject: [PATCH] - opensync plugin fixes: - fixed memory leak in vBase::GetAttr() - added support in vformat parser to parse "blocks" and keep track of the hierarchy when parsing an iCalendar, etc. - added support for searching for attributes only inside certain blocks (i.e. find first DTSTART in VEVENT block, not VTIMEZONE block) --- ChangeLog | 9 ++++ opensync-plugin/src/vbase.cc | 14 ++++-- opensync-plugin/src/vbase.h | 4 +- opensync-plugin/src/vevent.cc | 8 ++-- opensync-plugin/src/vformat.c | 102 +++++++++++++++++++++++++++++++++++++++--- opensync-plugin/src/vformat.h | 5 ++- 6 files changed, 125 insertions(+), 17 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5db3d038..4920e9f5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,14 @@ Release: version 0.10 - 2007/10/12 ------------------------------------------------------------------------------ +2007/10/26 + - opensync plugin fixes: + - fixed memory leak in vBase::GetAttr() + - added support in vformat parser to parse "blocks" + and keep track of the hierarchy when + parsing an iCalendar, etc. + - added support for searching for attributes only + inside certain blocks (i.e. find first + DTSTART in VEVENT block, not VTIMEZONE block) 2007/10/25 - fixed bug in Calendar::Clear, missing the Free / Class member variables, leaving them uninitialized diff --git a/opensync-plugin/src/vbase.cc b/opensync-plugin/src/vbase.cc index 662a11f4..647ace44 100644 --- a/opensync-plugin/src/vbase.cc +++ b/opensync-plugin/src/vbase.cc @@ -197,7 +197,7 @@ void vBase::AddParam(vAttrPtr &attr, const char *name, const char *value) vformat_attribute_add_param(attr.Get(), pParam); } -std::string vBase::GetAttr(const char *attrname) +std::string vBase::GetAttr(const char *attrname, const char *block) { Trace trace("vBase::GetAttr"); trace.logf("getting attr: %s", attrname); @@ -205,10 +205,13 @@ std::string vBase::GetAttr(const char *attrname) std::string ret; const char *value = 0; - VFormatAttribute *attr = vformat_find_attribute(m_format, attrname, 0); + bool needs_freeing = false; + + VFormatAttribute *attr = vformat_find_attribute(m_format, attrname, 0, block); if( attr ) { if( vformat_attribute_is_single_valued(attr) ) { value = vformat_attribute_get_value(attr); + needs_freeing = true; } else { // FIXME, this is hardcoded @@ -219,15 +222,18 @@ std::string vBase::GetAttr(const char *attrname) if( value ) ret = value; + if( needs_freeing ) + g_free((char *)value); + trace.logf("attr value: %s", ret.c_str()); return ret; } -vAttr vBase::GetAttrObj(const char *attrname, int nth) +vAttr vBase::GetAttrObj(const char *attrname, int nth, const char *block) { Trace trace("vBase::GetAttrObj"); trace.logf("getting attr: %s", attrname); - return vAttr(vformat_find_attribute(m_format, attrname, nth)); + return vAttr(vformat_find_attribute(m_format, attrname, nth, block)); } diff --git a/opensync-plugin/src/vbase.h b/opensync-plugin/src/vbase.h index a5e4b91c..8eaa434a 100644 --- a/opensync-plugin/src/vbase.h +++ b/opensync-plugin/src/vbase.h @@ -189,8 +189,8 @@ protected: void AddValue(vAttrPtr &attr, const char *value); void AddParam(vAttrPtr &attr, const char *name, const char *value); - std::string GetAttr(const char *attrname); - vAttr GetAttrObj(const char *attrname, int nth = 0); + std::string GetAttr(const char *attrname, const char *block = 0); + vAttr GetAttrObj(const char *attrname, int nth = 0, const char *block = 0); }; #endif diff --git a/opensync-plugin/src/vevent.cc b/opensync-plugin/src/vevent.cc index 3a31de3d..a52741eb 100644 --- a/opensync-plugin/src/vevent.cc +++ b/opensync-plugin/src/vevent.cc @@ -308,17 +308,17 @@ const Barry::Calendar& vCalendar::ToBarry(const char *vcal, uint32_t RecordId) if( !Format() ) throw ConvertError("resource error allocating vformat"); - string start = GetAttr("DTSTART"); + string start = GetAttr("DTSTART", "/vevent"); trace.logf("DTSTART attr retrieved: %s", start.c_str()); - string end = GetAttr("DTEND"); + string end = GetAttr("DTEND", "/vevent"); trace.logf("DTEND attr retrieved: %s", end.c_str()); - string subject = GetAttr("SUMMARY"); + string subject = GetAttr("SUMMARY", "/vevent"); trace.logf("SUMMARY attr retrieved: %s", subject.c_str()); if( subject.size() == 0 ) { subject = ""; trace.logf("ERROR: bad data, blank SUMMARY: %s", vcal); } - vAttr trigger_obj = GetAttrObj("TRIGGER"); + vAttr trigger_obj = GetAttrObj("TRIGGER", 0, "/valarm"); diff --git a/opensync-plugin/src/vformat.c b/opensync-plugin/src/vformat.c index e039f328..6161dd6a 100644 --- a/opensync-plugin/src/vformat.c +++ b/opensync-plugin/src/vformat.c @@ -675,6 +675,36 @@ static VFormatAttribute *_read_attribute (char **p) return NULL; } +void open_block(char **block, const char *block_name) +{ + char *start = *block ? *block : ""; + char *result = NULL; + + result = g_strconcat(start, "/", block_name, NULL); + if( *block ) + g_free(*block); + *block = result; +} + +void close_block(char **block, const char *block_name) +{ + int name_len = strlen(block_name); + int block_len = *block ? strlen(*block) : 0; + char *cmp_start = NULL; + + if( block_len < name_len + 1 ) + return; + + cmp_start = *block + (block_len - name_len - 1); + if( cmp_start[0] == '/' && strcmp(cmp_start+1, block_name) == 0 ) { + // end of block hierarchy contains block name, + // so safe to remove + + // cut off the end of the string... no need to free/realloc + *cmp_start = '\0'; + } +} + /* we try to be as forgiving as we possibly can here - this isn't a * validator. Almost nothing is considered a fatal error. We always * try to return *something*. @@ -708,12 +738,31 @@ static void _parse(VFormat *evc, const char *str) else if (attr) vformat_add_attribute (evc, attr); + char *block = NULL; while (*p) { VFormatAttribute *next_attr = _read_attribute (&p); if (next_attr) { - //if (g_ascii_strcasecmp (next_attr->name, "end")) - vformat_add_attribute (evc, next_attr); + if( g_ascii_strcasecmp(next_attr->name, "begin") == 0 ) { + // add to block hierarchy string + char *value = vformat_attribute_get_value(next_attr); + open_block(&block, value); + //osync_trace(TRACE_INTERNAL, "open block: %s", block); + g_free(value); + } + else if( g_ascii_strcasecmp(next_attr->name, "end") == 0 ) { + // close off the block + char *value = vformat_attribute_get_value(next_attr); + close_block(&block, value); + //osync_trace(TRACE_INTERNAL, "close block: %s", block); + g_free(value); + } + + // apply the block to the attr + next_attr->block = g_strdup(block); + + // add! + vformat_add_attribute (evc, next_attr); attr = next_attr; } } @@ -723,6 +772,7 @@ static void _parse(VFormat *evc, const char *str) } g_free (buf); + g_free (block); } char *vformat_escape_string (const char *s, VFormatType type) @@ -846,7 +896,36 @@ VFormat *vformat_new(void) return vformat_new_from_string (""); } -VFormatAttribute *vformat_find_attribute(VFormat *vcard, const char *name, int nth) +int _block_match(VFormatAttribute *attr, const char *block) +{ + // a block matches if the end of the attribute's block + // string matches a case insensitive compare with block + // + // for example, a calendar may or may not start with a + // BEGIN: VCALENDAR, so DTSTART's block string could be + // "/vcalendar/vevent" or just "/vevent". By passing + // "/vevent" or even "vevent" as the block argument above, + // we should get a match for any of the above. + + int attr_len = attr->block ? strlen(attr->block) : 0; + int block_len = block ? strlen(block) : 0; + + if( block == NULL ) + return 1; // if block is null, match everything + + if( attr_len < block_len ) + return 0; // not enough string to compare + + if( attr_len == 0 && block_len == 0 ) + return 1; // empty and null strings match + + if( attr->block == NULL ) + return 0; // don't compare if one side is null + + return g_ascii_strcasecmp(&attr->block[attr_len - block_len], block) == 0; +} + +VFormatAttribute *vformat_find_attribute(VFormat *vcard, const char *name, int nth, const char *block) { GList *attributes = vformat_get_attributes(vcard); GList *a = NULL; @@ -854,9 +933,11 @@ VFormatAttribute *vformat_find_attribute(VFormat *vcard, const char *name, int n for (a = attributes; a; a = a->next) { VFormatAttribute *attr = a->data; if (!g_ascii_strcasecmp(vformat_attribute_get_name(attr), name)) { - if( i == nth ) - return attr; - i++; + if( block == NULL || _block_match(attr, block) ) { + if( i == nth ) + return attr; + i++; + } } } return NULL; @@ -1162,6 +1243,7 @@ vformat_attribute_free (VFormatAttribute *attr) { g_return_if_fail (attr != NULL); + g_free (attr->block); g_free (attr->group); g_free (attr->name); @@ -1563,6 +1645,14 @@ vformat_attribute_get_name (VFormatAttribute *attr) return attr->name; } +const char* +vformat_attribute_get_block (VFormatAttribute *attr) +{ + g_return_val_if_fail (attr != NULL, NULL); + + return attr->block; +} + GList* vformat_attribute_get_values (VFormatAttribute *attr) { diff --git a/opensync-plugin/src/vformat.h b/opensync-plugin/src/vformat.h index 75e1e606..c81c4c58 100644 --- a/opensync-plugin/src/vformat.h +++ b/opensync-plugin/src/vformat.h @@ -57,6 +57,8 @@ typedef enum { } VFormatEncoding; typedef struct VFormatAttribute { + char *block; /* "vtimezone/standard", or "vevent", depending on + current begin/end location... may be null */ char *group; char *name; GList *params; /* VFormatParam */ @@ -112,7 +114,7 @@ void vformat_attribute_add_value_decoded (VFormatAttribute *attr, co void vformat_attribute_add_values (VFormatAttribute *attr, ...); void vformat_attribute_remove_values (VFormatAttribute *attr); void vformat_attribute_remove_params (VFormatAttribute *attr); -VFormatAttribute *vformat_find_attribute (VFormat *evc, const char *name, int nth); +VFormatAttribute *vformat_find_attribute (VFormat *evc, const char *name, int nth, const char *block); /* attribute parameters */ VFormatParam* vformat_attribute_param_new (const char *param_name); @@ -136,6 +138,7 @@ gboolean vformat_attribute_has_param(VFormatAttribute *attr, const char *name); GList* vformat_get_attributes (VFormat *vformat); const char* vformat_attribute_get_group (VFormatAttribute *attr); const char* vformat_attribute_get_name (VFormatAttribute *attr); +const char* vformat_attribute_get_block (VFormatAttribute *attr); GList* vformat_attribute_get_values (VFormatAttribute *attr); /* GList elements are of type char* */ GList* vformat_attribute_get_values_decoded (VFormatAttribute *attr); /* GList elements are of type GString* */ const char *vformat_attribute_get_nth_value(VFormatAttribute *attr, int nth); -- 2.11.4.GIT