Hi, Il giorno ven, 04/11/2005 alle 16.48 +0100, David Eriksson ha scritto: > On Wed, 2005-11-02 at 10:47 +0100, Sergio CERLESI wrote: > > Hi, > > > > sorry for the waiting time but i'm offline in these days. > > Hi! > > No problem, I don't always respond so quick myself... :-) > > > 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. > > OK. > > > 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) > > { > > ... > > } > > Good catch! > > > I'm waiting to know if there is something to change into these patch. > > I haven't followed yours and Nabil Sayegh's followups on this 100% but > as long as you agree about that the purpose and solution is good, I'll > comment the code... :-) > > I think I like synce-rra-0.9.1-vcard-empty-fields.2.diff better, but > these are some things that I think would make your patch a little > better. Please note that I really enjoy getting your patches so this is > just nitpicking! > > o Don't #define MAX_ID in contact_ids.h. Instead put MAX_ID last in the > field_ids enum and it will get the right value. (I would probably have > used the name ID_COUNT instead of MAX_ID, field_index instead of > field_ids and field_id instead of value_ids, but that's not so > important.) > > o Change the name_ids array and the id parameter to add_date and > add_string to be of the enum type (field_ids in your patch). Rename the > id parameter to "index" or something, because it is not an id as in ID_* > anymore. > > o I use 2 spaces instead of tab characters for SynCE nowadays, but I > know it is not consistent throughout SynCE > Do it!
I split the patch so there is one for "empty field" and one for "duplicate value" (that require the first). Regards Sergio
--- ./lib/contact.c.orig 2005-11-07 10:25:53.000000000 +0100 +++ ./lib/contact.c 2005-11-07 10:29:36.000000000 +0100 @@ -945,8 +945,11 @@ if (date_to_struct(value, &time_fields)) { CEPROPVAL* propval = &parser->fields[index]; - propval->propid = (field_id[index] << 16) | CEVT_FILETIME; - time_fields_to_filetime(&time_fields, &propval->val.filetime); + if (propval->propid & CEVT_FLAG_EMPTY) + { + propval->propid = (field_id[index] << 16) | CEVT_FILETIME; + time_fields_to_filetime(&time_fields, &propval->val.filetime); + } } } @@ -957,26 +960,29 @@ assert(value); - field->propid = (field_id[index] << 16) | CEVT_LPWSTR; - - if (STR_IN_STR(type, "QUOTED-PRINTABLE")) + if (field->propid & CEVT_FLAG_EMPTY) { - value = converted = strdup_quoted_printable(value); + field->propid = (field_id[index] << 16) | CEVT_LPWSTR; + + if (STR_IN_STR(type, "QUOTED-PRINTABLE")) + { + value = converted = strdup_quoted_printable(value); + assert(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); + + if (converted) + free(converted); } - - 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); - - if (converted) - free(converted); }/*}}}*/ static bool parser_handle_field(/*{{{*/
--- ./lib/contact.c.orig 2005-11-07 09:35:46.000000000 +0100 +++ ./lib/contact.c 2005-11-07 10:19:01.000000000 +0100 @@ -718,15 +718,67 @@ bool utf8; /* default charset is utf8 */ } Parser; +typedef enum _field_index +{ + INDEX_NOTE, + INDEX_SUFFIX, + INDEX_FIRST_NAME, + INDEX_WORK_TEL, + INDEX_HOME_TEL, + INDEX_LAST_NAME, + INDEX_COMPANY, + INDEX_JOB_TITLE, + INDEX_DEPARTMENT, + INDEX_OFFICE_LOC, + INDEX_MOBILE_TEL, + INDEX_RADIO_TEL, + INDEX_CAR_TEL, + INDEX_WORK_FAX, + INDEX_HOME_FAX, + INDEX_HOME2_TEL, + INDEX_BIRTHDAY, + INDEX_ANNIVERSARY, + INDEX_CATEGORY, + INDEX_ASSISTANT, + INDEX_ASSISTANT_TEL, + INDEX_CHILDREN, + INDEX_WORK2_TEL, + INDEX_WEB_PAGE, + INDEX_PAGER, + INDEX_SPOUSE, + INDEX_FULL_NAME, + INDEX_TITLE, + INDEX_MIDDLE_NAME, + INDEX_HOME_STREET, + INDEX_HOME_LOCALITY, + INDEX_HOME_REGION, + INDEX_HOME_POSTAL_CODE, + INDEX_HOME_COUNTRY, + INDEX_WORK_STREET, + INDEX_WORK_LOCALITY, + INDEX_WORK_REGION, + INDEX_WORK_POSTAL_CODE, + INDEX_WORK_COUNTRY, + INDEX_OTHER_STREET, + INDEX_OTHER_LOCALITY, + INDEX_OTHER_REGION, + INDEX_OTHER_POSTAL_CODE, + INDEX_OTHER_COUNTRY, + INDEX_EMAIL, + INDEX_EMAIL2, + INDEX_EMAIL3, + ID_COUNT +} field_index; + #define NAME_FIELD_COUNT 5 -static uint32_t name_ids[NAME_FIELD_COUNT] = +static uint32_t name_index[NAME_FIELD_COUNT] = { - ID_LAST_NAME, - ID_FIRST_NAME, - ID_MIDDLE_NAME, - ID_TITLE, - ID_SUFFIX + INDEX_LAST_NAME, + INDEX_FIRST_NAME, + INDEX_MIDDLE_NAME, + INDEX_TITLE, + INDEX_SUFFIX }; #define HOME 0 @@ -735,15 +787,66 @@ #define ADDRESS_FIELD_COUNT 7 -static uint32_t address_ids[ADDRESS_FIELD_COUNT][3] = +static uint32_t address_index[ADDRESS_FIELD_COUNT][3] = +{ + {0, 0}, /* post office box */ + {0, 0}, /* extended address */ + {INDEX_HOME_STREET, INDEX_WORK_STREET, INDEX_OTHER_STREET}, /* street */ + {INDEX_HOME_LOCALITY, INDEX_WORK_LOCALITY, INDEX_OTHER_LOCALITY}, /* locality */ + {INDEX_HOME_REGION, INDEX_WORK_REGION, INDEX_OTHER_REGION}, /* region */ + {INDEX_HOME_POSTAL_CODE, INDEX_WORK_POSTAL_CODE, INDEX_OTHER_POSTAL_CODE}, /* postal code */ + {INDEX_HOME_COUNTRY, INDEX_WORK_COUNTRY, INDEX_OTHER_COUNTRY} /* country */ +}; + +static const uint32_t field_id[ID_COUNT] = { - {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 */ + 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)/*{{{*/ @@ -833,7 +936,7 @@ return true; }/*}}}*/ -static void add_date(Parser* parser, uint32_t id, const char* type, char* value) +static void add_date(Parser* parser, uint32_t index, const char* type, char* value) { TIME_FIELDS time_fields; @@ -841,39 +944,39 @@ if (date_to_struct(value, &time_fields)) { - CEPROPVAL* propval = &parser->fields[parser->field_index++]; - propval->propid = (id << 16) | CEVT_FILETIME; + CEPROPVAL* propval = &parser->fields[index]; + propval->propid = (field_id[index] << 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)/*{{{*/ +static void add_string(Parser* parser, uint32_t index, const char* type, char* value)/*{{{*/ { - char* converted = NULL; - CEPROPVAL* field = &parser->fields[parser->field_index++]; + char* converted = NULL; + CEPROPVAL* field = &parser->fields[index]; - assert(value); + assert(value); - field->propid = (id << 16) | CEVT_LPWSTR; + field->propid = (field_id[index] << 16) | CEVT_LPWSTR; - if (STR_IN_STR(type, "QUOTED-PRINTABLE")) - { - value = converted = strdup_quoted_printable(value); - assert(value); - } + if (STR_IN_STR(type, "QUOTED-PRINTABLE")) + { + value = converted = strdup_quoted_printable(value); + assert(value); + } - unescape_string(value); - assert(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); + 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(/*{{{*/ @@ -941,7 +1044,7 @@ }/*}}}*/ else if (STR_EQUAL(name, "FN"))/*{{{*/ { - add_string(parser, ID_FULL_NAME, type, value); + add_string(parser, INDEX_FULL_NAME, type, value); }/*}}}*/ else if (STR_EQUAL(name, "N"))/*{{{*/ { @@ -952,7 +1055,7 @@ { if (*name[i]) { - add_string(parser, name_ids[i], type, name[i]); + add_string(parser, name_index[i], type, name[i]); } } @@ -980,9 +1083,9 @@ for (i = 0; i < ADDRESS_FIELD_COUNT && address[i]; i++) { - if (address_ids[i][where] && *address[i]) + if (address_index[i][where] && *address[i]) { - add_string(parser, address_ids[i][where], type, address[i]); + add_string(parser, address_index[i][where], type, address[i]); } } @@ -996,36 +1099,36 @@ 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 ? INDEX_HOME_FAX : INDEX_HOME_TEL, type, value); else - add_string(parser, ID_HOME2_TEL, type, value); + add_string(parser, INDEX_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 ? INDEX_WORK_FAX : INDEX_WORK_TEL, type, value); else - add_string(parser, ID_WORK2_TEL, type, value); + add_string(parser, INDEX_WORK2_TEL, type, value); } else if (STR_IN_STR(type, "CELL")) { - add_string(parser, ID_MOBILE_TEL, type, value); + add_string(parser, INDEX_MOBILE_TEL, type, value); } else if (STR_IN_STR(type, "X-EVOLUTION-ASSISTANT")) { - add_string(parser, ID_ASSISTANT_TEL, type, value); + add_string(parser, INDEX_ASSISTANT_TEL, type, value); } else if (STR_IN_STR(type, "X-EVOLUTION-RADIO")) { - add_string(parser, ID_RADIO_TEL, type, value); + add_string(parser, INDEX_RADIO_TEL, type, value); } else if (STR_IN_STR(type, "CAR")) { - add_string(parser, ID_CAR_TEL, type, value); + add_string(parser, INDEX_CAR_TEL, type, value); } else if (STR_IN_STR(type, "PAGER")) { - add_string(parser, ID_PAGER, type, value); + add_string(parser, INDEX_PAGER, type, value); } else { @@ -1046,19 +1149,19 @@ switch (nth) { case 1: - add_string(parser, ID_EMAIL, type, value); + add_string(parser, INDEX_EMAIL, type, value); break; case 2: - add_string(parser, ID_EMAIL2, type, value); + add_string(parser, INDEX_EMAIL2, type, value); break; case 3: - add_string(parser, ID_EMAIL3, type, value); + add_string(parser, INDEX_EMAIL3, type, value); break; } }/*}}}*/ else if (STR_EQUAL(name, "URL"))/*{{{*/ { - add_string(parser, ID_WEB_PAGE, type, value); + add_string(parser, INDEX_WEB_PAGE, type, value); }/*}}}*/ else if (STR_EQUAL(name, "ORG"))/*{{{*/ { @@ -1066,19 +1169,19 @@ if (separator) { if (separator[1]) { - add_string(parser, ID_DEPARTMENT, type, separator + 1); + add_string(parser, INDEX_DEPARTMENT, type, separator + 1); } *separator = '\0'; } if (value[0]) { - add_string(parser, ID_COMPANY, type, value); + add_string(parser, INDEX_COMPANY, type, value); } }/*}}}*/ else if (STR_EQUAL(name, "TITLE"))/*{{{*/ { - add_string(parser, ID_JOB_TITLE, type, value); + add_string(parser, INDEX_JOB_TITLE, type, value); }/*}}}*/ else if (STR_EQUAL(name, "X-EVOLUTION-FILE-AS"))/*{{{*/ { @@ -1096,27 +1199,27 @@ }/*}}}*/ else if (STR_EQUAL(name, "CATEGORIES")) { - add_string(parser, ID_CATEGORY, type, value); + add_string(parser, INDEX_CATEGORY, type, value); } else if (STR_EQUAL(name, "BDAY")) { - add_date(parser, ID_BIRTHDAY, type, value); + add_date(parser, INDEX_BIRTHDAY, type, value); } else if (STR_EQUAL(name, "X-EVOLUTION-ANNIVERSARY")) { - add_date(parser, ID_ANNIVERSARY, type, value); + add_date(parser, INDEX_ANNIVERSARY, type, value); } else if (STR_EQUAL(name, "X-EVOLUTION-SPOUSE")) { - add_string(parser, ID_SPOUSE, type, value); + add_string(parser, INDEX_SPOUSE, type, value); } else if (STR_EQUAL(name, "X-EVOLUTION-ASSISTANT")) { - add_string(parser, ID_ASSISTANT, type, value); + add_string(parser, INDEX_ASSISTANT, type, value); } else if (STR_EQUAL(name, "X-EVOLUTION-OFFICE")) { - add_string(parser, ID_OFFICE_LOC, type, value); + add_string(parser, INDEX_OFFICE_LOC, type, value); } #if 0 @@ -1250,6 +1353,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; @@ -1271,6 +1375,19 @@ parser.field_index = 0; parser.utf8 = flags & RRA_CONTACT_UTF8; + for (count=0; count < ID_COUNT; count++) + { + CEPROPVAL* field = &parser.fields[parser.field_index++]; + + if ( count == INDEX_BIRTHDAY || + count == INDEX_ANNIVERSARY) + field->propid = (field_id[count] << 16) | + CEVT_FLAG_EMPTY | CEVT_FILETIME; + else + field->propid = (field_id[count] << 16) | + CEVT_FLAG_EMPTY | CEVT_LPWSTR; + } + while (*p && parser.field_index < max_field_count) { switch (state)