Hi,

sorry for the waiting time but i'm offline in these days.

I wrote two patches that both fixes this bug without changing
contact_ids.h.

The first is more simple but needs to do a search of the right position
of the fields at any call of add_date/add_string

#define number_ids(c,id)   for (c=0; value_ids[c] != id && c < MAX_ID; c
++);

The changes into the second patch are more numerous but avoid to do the
search.

There is another bug fixed from these patchs, if rra_contact_from_vcard
tries to parse a vcard with two or more fields of the same type (for
example four mobile phones) it creates an object with four entries and
the contact on my ipaq contain the last value and some dirty fields.
With these patches it considers only the first value of any type:

if (propval->propid & CEVT_FLAG_EMPTY)
{
        ...
}

I'm waiting to know if there is something to change into these patch.

Regards
Sergio

Il giorno ven, 28/10/2005 alle 18.57 +0200, David Eriksson ha scritto:
> On Fri, 2005-10-28 at 18:19 +0200, Sergio CERLESI wrote:
> > Hi,
> > 
> > attached patch.
> 
> Hi again!
> 
> It makes me really glad that you try to fix this bug, but I really want
> to keep the IDs in contact_ids.h as constants! 
> 
> I'm sure you can find a way to solve this without changing
> contact_ids.h!

--- ./lib/contact_ids.h.orig	2005-10-27 17:55:18.000000000 +0200
+++ ./lib/contact_ids.h	2005-11-01 14:50:18.000000000 +0100
@@ -59,6 +59,8 @@
 #define ID_EMAIL2       0x4093
 #define ID_EMAIL3       0x40a3
 
+#define MAX_ID 47
+
 #define MAX_TEL_WORK 2
 #define MAX_TEL_HOME 2
 #define MAX_EMAIL 3
--- ./lib/contact.c.orig	2005-10-30 15:57:59.000000000 +0100
+++ ./lib/contact.c	2005-11-01 15:27:21.000000000 +0100
@@ -746,6 +746,59 @@
 	{ID_HOME_COUNTRY,     ID_WORK_COUNTRY,       ID_OTHER_COUNTRY}      /* country */
 };
 
+static const uint32_t value_ids[MAX_ID] =
+{
+	ID_NOTE,
+	ID_SUFFIX,
+	ID_FIRST_NAME,
+	ID_WORK_TEL,
+	ID_HOME_TEL,
+	ID_LAST_NAME,
+	ID_COMPANY,
+	ID_JOB_TITLE,
+	ID_DEPARTMENT,
+	ID_OFFICE_LOC,
+	ID_MOBILE_TEL,
+	ID_RADIO_TEL,
+	ID_CAR_TEL,
+	ID_WORK_FAX,
+	ID_HOME_FAX,
+	ID_HOME2_TEL,
+	ID_BIRTHDAY,
+	ID_ANNIVERSARY,
+	ID_CATEGORY,
+	ID_ASSISTANT,
+	ID_ASSISTANT_TEL,
+	ID_CHILDREN,
+	ID_WORK2_TEL,
+	ID_WEB_PAGE,
+	ID_PAGER,
+	ID_SPOUSE,
+	ID_FULL_NAME,
+	ID_TITLE,
+	ID_MIDDLE_NAME,
+	ID_HOME_STREET,
+	ID_HOME_LOCALITY,
+	ID_HOME_REGION,
+	ID_HOME_POSTAL_CODE,
+	ID_HOME_COUNTRY,
+	ID_WORK_STREET,
+	ID_WORK_LOCALITY,
+	ID_WORK_REGION,
+	ID_WORK_POSTAL_CODE,
+	ID_WORK_COUNTRY,
+	ID_OTHER_STREET,
+	ID_OTHER_LOCALITY,
+	ID_OTHER_REGION,
+	ID_OTHER_POSTAL_CODE,
+	ID_OTHER_COUNTRY,
+	ID_EMAIL,
+	ID_EMAIL2,
+	ID_EMAIL3
+};
+
+#define number_ids(c,id)	for (c=0; value_ids[c] != id && c < MAX_ID; c++);
+
 static char* strdup_quoted_printable(const unsigned char* source)/*{{{*/
 {
 	char* result = malloc(strlen(source) + 1);
@@ -841,39 +894,54 @@
 
   if (date_to_struct(value, &time_fields))
   {
-    CEPROPVAL* propval = &parser->fields[parser->field_index++];
-    propval->propid = (id << 16) | CEVT_FILETIME;
-    time_fields_to_filetime(&time_fields, &propval->val.filetime);
+	int count;
+
+	number_ids(count, id);
+
+	CEPROPVAL* propval = &parser->fields[count];
+
+	if (propval->propid & CEVT_FLAG_EMPTY)
+	{
+		propval->propid = (id << 16) | CEVT_FILETIME;
+		time_fields_to_filetime(&time_fields, &propval->val.filetime);
+	}
   }
 }
 
 static void add_string(Parser* parser, uint32_t id, const char* type, char* value)/*{{{*/
 {
 	char* converted = NULL;
-	CEPROPVAL* field = &parser->fields[parser->field_index++];
+	int count;
+
+	number_ids(count, id);
+
+	CEPROPVAL* field = &parser->fields[count];
 
 	assert(value);
-	
-	field->propid = (id << 16) | CEVT_LPWSTR;
 
-	if (STR_IN_STR(type, "QUOTED-PRINTABLE"))
+	if (field->propid & CEVT_FLAG_EMPTY)
 	{
-		value = converted = strdup_quoted_printable(value);
-		assert(value);
-	}
+		field->propid = (id << 16) | CEVT_LPWSTR;
 
-	unescape_string(value);
-	assert(value);
+		if (STR_IN_STR(type, "QUOTED-PRINTABLE"))
+		{
+			value = converted = strdup_quoted_printable(value);
+			assert(value);
+		}
 
-	if (parser->utf8 || STR_IN_STR(type, "UTF-8"))
-		field->val.lpwstr = wstr_from_utf8(value);
-	else
-		field->val.lpwstr = wstr_from_ascii(value);
+		unescape_string(value);
+		assert(value);
+
+		if (parser->utf8 || STR_IN_STR(type, "UTF-8"))
+			field->val.lpwstr = wstr_from_utf8(value);
+		else
+			field->val.lpwstr = wstr_from_ascii(value);
 
-	assert(field->val.lpwstr);
+		assert(field->val.lpwstr);
 
-	if (converted)
-		free(converted);
+		if (converted)
+			free(converted);
+	}
 }/*}}}*/
 
 static bool parser_handle_field(/*{{{*/
@@ -1242,6 +1310,7 @@
 	size_t max_field_count = *field_count;
 	const char* p = vcard;
 	int state = VCARD_STATE_NEWLINE;
+	int count;
 	const char* name = NULL;
 	const char* name_end = NULL;
 	const char* type = NULL;
@@ -1263,6 +1332,19 @@
 	parser.field_index    = 0;
 	parser.utf8           = flags & RRA_CONTACT_UTF8;
 
+	for (count=0; count < MAX_ID; count++)
+	{
+		CEPROPVAL* field = &parser.fields[parser.field_index++];
+
+		if (	value_ids[count] == ID_BIRTHDAY ||
+				value_ids[count] == ID_ANNIVERSARY)
+			field->propid = (value_ids[count] << 16) |
+					CEVT_FLAG_EMPTY | CEVT_FILETIME;
+		else
+			field->propid = (value_ids[count] << 16) |
+					CEVT_FLAG_EMPTY | CEVT_LPWSTR;
+	}
+
 	while (*p && parser.field_index < max_field_count)
 	{
 		switch (state)
--- ./lib/contact_ids.h.orig	2005-10-27 17:55:18.000000000 +0200
+++ ./lib/contact_ids.h	2005-11-01 14:50:18.000000000 +0100
@@ -59,6 +59,8 @@
 #define ID_EMAIL2       0x4093
 #define ID_EMAIL3       0x40a3
 
+#define MAX_ID 47
+
 #define MAX_TEL_WORK 2
 #define MAX_TEL_HOME 2
 #define MAX_EMAIL 3
--- ./lib/contact.c.orig	2005-10-30 15:57:59.000000000 +0100
+++ ./lib/contact.c	2005-11-01 15:50:26.000000000 +0100
@@ -718,15 +718,66 @@
 	bool utf8;	/* default charset is utf8 */
 } Parser;
 
+typedef enum _field_ids
+{
+	ENUM_NOTE,
+	ENUM_SUFFIX,
+	ENUM_FIRST_NAME,
+	ENUM_WORK_TEL,
+	ENUM_HOME_TEL,
+	ENUM_LAST_NAME,
+	ENUM_COMPANY,
+	ENUM_JOB_TITLE,
+	ENUM_DEPARTMENT,
+	ENUM_OFFICE_LOC,
+	ENUM_MOBILE_TEL,
+	ENUM_RADIO_TEL,
+	ENUM_CAR_TEL,
+	ENUM_WORK_FAX,
+	ENUM_HOME_FAX,
+	ENUM_HOME2_TEL,
+	ENUM_BIRTHDAY,
+	ENUM_ANNIVERSARY,
+	ENUM_CATEGORY,
+	ENUM_ASSISTANT,
+	ENUM_ASSISTANT_TEL,
+	ENUM_CHILDREN,
+	ENUM_WORK2_TEL,
+	ENUM_WEB_PAGE,
+	ENUM_PAGER,
+	ENUM_SPOUSE,
+	ENUM_FULL_NAME,
+	ENUM_TITLE,
+	ENUM_MIDDLE_NAME,
+	ENUM_HOME_STREET,
+	ENUM_HOME_LOCALITY,
+	ENUM_HOME_REGION,
+	ENUM_HOME_POSTAL_CODE,
+	ENUM_HOME_COUNTRY,
+	ENUM_WORK_STREET,
+	ENUM_WORK_LOCALITY,
+	ENUM_WORK_REGION,
+	ENUM_WORK_POSTAL_CODE,
+	ENUM_WORK_COUNTRY,
+	ENUM_OTHER_STREET,
+	ENUM_OTHER_LOCALITY,
+	ENUM_OTHER_REGION,
+	ENUM_OTHER_POSTAL_CODE,
+	ENUM_OTHER_COUNTRY,
+	ENUM_EMAIL,
+	ENUM_EMAIL2,
+	ENUM_EMAIL3
+} field_ids;
+
 #define NAME_FIELD_COUNT 5
 
 static uint32_t name_ids[NAME_FIELD_COUNT] =
 {
-	ID_LAST_NAME,
-	ID_FIRST_NAME,
-	ID_MIDDLE_NAME,
-	ID_TITLE,
-	ID_SUFFIX
+	ENUM_LAST_NAME,
+	ENUM_FIRST_NAME,
+	ENUM_MIDDLE_NAME,
+	ENUM_TITLE,
+	ENUM_SUFFIX
 };
 
 #define HOME 0
@@ -739,11 +790,62 @@
 {
 	{0, 0}, /* post office box */
 	{0, 0}, /* extended address */
-	{ID_HOME_STREET,      ID_WORK_STREET,        ID_OTHER_STREET},      /* street */
-	{ID_HOME_LOCALITY,    ID_WORK_LOCALITY,      ID_OTHER_LOCALITY},    /* locality */
-	{ID_HOME_REGION,      ID_WORK_REGION,        ID_OTHER_REGION},      /* region */
-	{ID_HOME_POSTAL_CODE, ID_WORK_POSTAL_CODE,   ID_OTHER_POSTAL_CODE}, /* postal code */
-	{ID_HOME_COUNTRY,     ID_WORK_COUNTRY,       ID_OTHER_COUNTRY}      /* country */
+	{ENUM_HOME_STREET,      ENUM_WORK_STREET,        ENUM_OTHER_STREET},      /* street */
+	{ENUM_HOME_LOCALITY,    ENUM_WORK_LOCALITY,      ENUM_OTHER_LOCALITY},    /* locality */
+	{ENUM_HOME_REGION,      ENUM_WORK_REGION,        ENUM_OTHER_REGION},      /* region */
+	{ENUM_HOME_POSTAL_CODE, ENUM_WORK_POSTAL_CODE,   ENUM_OTHER_POSTAL_CODE}, /* postal code */
+	{ENUM_HOME_COUNTRY,     ENUM_WORK_COUNTRY,       ENUM_OTHER_COUNTRY}      /* country */
+};
+
+static const uint32_t value_ids[MAX_ID] =
+{
+	ID_NOTE,
+	ID_SUFFIX,
+	ID_FIRST_NAME,
+	ID_WORK_TEL,
+	ID_HOME_TEL,
+	ID_LAST_NAME,
+	ID_COMPANY,
+	ID_JOB_TITLE,
+	ID_DEPARTMENT,
+	ID_OFFICE_LOC,
+	ID_MOBILE_TEL,
+	ID_RADIO_TEL,
+	ID_CAR_TEL,
+	ID_WORK_FAX,
+	ID_HOME_FAX,
+	ID_HOME2_TEL,
+	ID_BIRTHDAY,
+	ID_ANNIVERSARY,
+	ID_CATEGORY,
+	ID_ASSISTANT,
+	ID_ASSISTANT_TEL,
+	ID_CHILDREN,
+	ID_WORK2_TEL,
+	ID_WEB_PAGE,
+	ID_PAGER,
+	ID_SPOUSE,
+	ID_FULL_NAME,
+	ID_TITLE,
+	ID_MIDDLE_NAME,
+	ID_HOME_STREET,
+	ID_HOME_LOCALITY,
+	ID_HOME_REGION,
+	ID_HOME_POSTAL_CODE,
+	ID_HOME_COUNTRY,
+	ID_WORK_STREET,
+	ID_WORK_LOCALITY,
+	ID_WORK_REGION,
+	ID_WORK_POSTAL_CODE,
+	ID_WORK_COUNTRY,
+	ID_OTHER_STREET,
+	ID_OTHER_LOCALITY,
+	ID_OTHER_REGION,
+	ID_OTHER_POSTAL_CODE,
+	ID_OTHER_COUNTRY,
+	ID_EMAIL,
+	ID_EMAIL2,
+	ID_EMAIL3
 };
 
 static char* strdup_quoted_printable(const unsigned char* source)/*{{{*/
@@ -841,39 +943,47 @@
 
   if (date_to_struct(value, &time_fields))
   {
-    CEPROPVAL* propval = &parser->fields[parser->field_index++];
-    propval->propid = (id << 16) | CEVT_FILETIME;
-    time_fields_to_filetime(&time_fields, &propval->val.filetime);
+	CEPROPVAL* propval = &parser->fields[id];
+
+	if (propval->propid & CEVT_FLAG_EMPTY)
+	{
+		propval->propid = (value_ids[id] << 16) | CEVT_FILETIME;
+		time_fields_to_filetime(&time_fields, &propval->val.filetime);
+	}
   }
 }
 
 static void add_string(Parser* parser, uint32_t id, const char* type, char* value)/*{{{*/
 {
 	char* converted = NULL;
-	CEPROPVAL* field = &parser->fields[parser->field_index++];
+
+	CEPROPVAL* field = &parser->fields[id];
 
 	assert(value);
-	
-	field->propid = (id << 16) | CEVT_LPWSTR;
 
-	if (STR_IN_STR(type, "QUOTED-PRINTABLE"))
+	if (field->propid & CEVT_FLAG_EMPTY)
 	{
-		value = converted = strdup_quoted_printable(value);
-		assert(value);
-	}
+		field->propid = (value_ids[id] << 16) | CEVT_LPWSTR;
 
-	unescape_string(value);
-	assert(value);
+		if (STR_IN_STR(type, "QUOTED-PRINTABLE"))
+		{
+			value = converted = strdup_quoted_printable(value);
+			assert(value);
+		}
 
-	if (parser->utf8 || STR_IN_STR(type, "UTF-8"))
-		field->val.lpwstr = wstr_from_utf8(value);
-	else
-		field->val.lpwstr = wstr_from_ascii(value);
+		unescape_string(value);
+		assert(value);
 
-	assert(field->val.lpwstr);
+		if (parser->utf8 || STR_IN_STR(type, "UTF-8"))
+			field->val.lpwstr = wstr_from_utf8(value);
+		else
+			field->val.lpwstr = wstr_from_ascii(value);
+
+		assert(field->val.lpwstr);
 
-	if (converted)
-		free(converted);
+		if (converted)
+			free(converted);
+	}
 }/*}}}*/
 
 static bool parser_handle_field(/*{{{*/
@@ -941,7 +1051,7 @@
 	}/*}}}*/
 	else if (STR_EQUAL(name, "FN"))/*{{{*/
 	{
-		add_string(parser, ID_FULL_NAME, type, value);
+		add_string(parser, ENUM_FULL_NAME, type, value);
 	}/*}}}*/
 	else if (STR_EQUAL(name, "N"))/*{{{*/
 	{
@@ -996,28 +1106,28 @@
 		if (STR_IN_STR(type, "HOME"))
 		{
 			if (nth==1)
-			add_string(parser, fax ? ID_HOME_FAX : ID_HOME_TEL, type, value);
+			add_string(parser, fax ? ENUM_HOME_FAX : ENUM_HOME_TEL, type, value);
 			else
-				add_string(parser, ID_HOME2_TEL, type, value);
+				add_string(parser, ENUM_HOME2_TEL, type, value);
 		}
 		else if (STR_IN_STR(type, "WORK"))
 		{
 			if (nth==1)
-			add_string(parser, fax ? ID_WORK_FAX : ID_WORK_TEL, type, value);
+			add_string(parser, fax ? ENUM_WORK_FAX : ENUM_WORK_TEL, type, value);
 			else
-				add_string(parser, ID_WORK2_TEL, type, value);
+				add_string(parser, ENUM_WORK2_TEL, type, value);
 		}
 		else if (STR_IN_STR(type, "CELL"))
 		{
-			add_string(parser, ID_MOBILE_TEL, type, value);
+			add_string(parser, ENUM_MOBILE_TEL, type, value);
 		}
 		else if (STR_IN_STR(type, "X-EVOLUTION-ASSISTANT"))
 		{
-			add_string(parser, ID_ASSISTANT_TEL, type, value);
+			add_string(parser, ENUM_ASSISTANT_TEL, type, value);
 		}
 		else if (STR_IN_STR(type, "X-EVOLUTION-RADIO"))
 		{
-			add_string(parser, ID_RADIO_TEL, type, value);
+			add_string(parser, ENUM_RADIO_TEL, type, value);
 		}
 		else
 		{
@@ -1038,19 +1148,19 @@
 		switch (nth)
 		{
 			case 1:
-		add_string(parser, ID_EMAIL, type, value);
+		add_string(parser, ENUM_EMAIL, type, value);
 				break;
 			case 2:
-				add_string(parser, ID_EMAIL2, type, value);
+				add_string(parser, ENUM_EMAIL2, type, value);
 				break;
 			case 3:
-				add_string(parser, ID_EMAIL3, type, value);
+				add_string(parser, ENUM_EMAIL3, type, value);
 				break;
 		}
 	}/*}}}*/
 	else if (STR_EQUAL(name, "URL"))/*{{{*/
 	{
-		add_string(parser, ID_WEB_PAGE, type, value);
+		add_string(parser, ENUM_WEB_PAGE, type, value);
 	}/*}}}*/
 	else if (STR_EQUAL(name, "ORG"))/*{{{*/
 	{
@@ -1058,19 +1168,19 @@
 		if (separator)
 		{
 			if (separator[1]) {
-				add_string(parser, ID_DEPARTMENT, type, separator + 1);
+				add_string(parser, ENUM_DEPARTMENT, type, separator + 1);
 			}
 			*separator = '\0';
 		}
 
 		if (value[0])
 		{
-			add_string(parser, ID_COMPANY, type, value);
+			add_string(parser, ENUM_COMPANY, type, value);
 		}
 	}/*}}}*/
 	else if (STR_EQUAL(name, "TITLE"))/*{{{*/
 	{
-		add_string(parser, ID_JOB_TITLE, type, value);
+		add_string(parser, ENUM_JOB_TITLE, type, value);
 	}/*}}}*/
 	else if (STR_EQUAL(name, "X-EVOLUTION-FILE-AS"))/*{{{*/
 	{
@@ -1088,27 +1198,27 @@
 	}/*}}}*/
   else if (STR_EQUAL(name, "CATEGORIES"))
   {
-    add_string(parser, ID_CATEGORY, type, value);
+    add_string(parser, ENUM_CATEGORY, type, value);
   }
   else if (STR_EQUAL(name, "BDAY"))
   {
-    add_date(parser, ID_BIRTHDAY, type, value);
+    add_date(parser, ENUM_BIRTHDAY, type, value);
   }
   else if (STR_EQUAL(name, "X-EVOLUTION-ANNIVERSARY"))
   {
-    add_date(parser, ID_ANNIVERSARY, type, value);
+    add_date(parser, ENUM_ANNIVERSARY, type, value);
   }
   else if (STR_EQUAL(name, "X-EVOLUTION-SPOUSE"))
   {
-    add_string(parser, ID_SPOUSE, type, value);
+    add_string(parser, ENUM_SPOUSE, type, value);
   }
   else if (STR_EQUAL(name, "X-EVOLUTION-ASSISTANT"))
   {
-    add_string(parser, ID_ASSISTANT, type, value);
+    add_string(parser, ENUM_ASSISTANT, type, value);
   }
   else if (STR_EQUAL(name, "X-EVOLUTION-OFFICE"))
   {
-    add_string(parser, ID_OFFICE_LOC, type, value);
+    add_string(parser, ENUM_OFFICE_LOC, type, value);
   }
 
 #if 0
@@ -1242,6 +1352,7 @@
 	size_t max_field_count = *field_count;
 	const char* p = vcard;
 	int state = VCARD_STATE_NEWLINE;
+	int count;
 	const char* name = NULL;
 	const char* name_end = NULL;
 	const char* type = NULL;
@@ -1263,6 +1374,19 @@
 	parser.field_index    = 0;
 	parser.utf8           = flags & RRA_CONTACT_UTF8;
 
+	for (count=0; count < MAX_ID; count++)
+	{
+		CEPROPVAL* field = &parser.fields[parser.field_index++];
+
+		if (	value_ids[count] == ID_BIRTHDAY ||
+				value_ids[count] == ID_ANNIVERSARY)
+			field->propid = (value_ids[count] << 16) |
+					CEVT_FLAG_EMPTY | CEVT_FILETIME;
+		else
+			field->propid = (value_ids[count] << 16) |
+					CEVT_FLAG_EMPTY | CEVT_LPWSTR;
+	}
+
 	while (*p && parser.field_index < max_field_count)
 	{
 		switch (state)

Reply via email to