Il giorno lun, 07/11/2005 alle 16.00 +0100, Nabil Sayegh ha scritto: > Am Montag 07 November 2005 15:30 schrieb Sergio CERLESI: > > Hi, > > > > > All fields that have to be dropped should be saved in additional fields, > > > so that they don't get lost when re-syncing, but you don't need to take > > > care of this ATM, I'm working on this already. > > > > Can I help you to do it ? Or, if you already have a pre-release patch > > can I test it on my system ? > > Of course! > Help is always apreciated. > > see attachement. > > The patch does not yet involve storing of dropped values like 4th email etc. > ATM it stores fields that can't be handled by the device at all, namely > Instant Messaging (ICQ). > > Unfortunately evolution and kabc (kaddressbook) have their own X-special > fields, so we need to find a mechanism, that these aren't duplicated/mixed up > leading to the known data corruption. > > I implemented X-messaging/PROTOCOL:VALUE; for kde so far. > What shall we do for evolution? > It would be nice, if we could use the same ID_MESSAGING_* > > > > if you use IRC you can join us in channel #synce at freenode. > > > > I'm conneting as cerly. > > see you there
Hi, I looked into you patch and I tried to do the same thing for evolution but I stopped myself. Evolution allows to create a vcard that can contain: - 8 phone entrys for 17 different types (136 differents combinations) - 4 instant message entrys for 6 different types (24 differents combinations) - approximately other 10 entrys that my ipaq not handles So, if I don't want to lost date I think that I have more possible solutions: 1) Add approximately 170 new entrys (only for evolution, others software can require others entrys). 2) Accept, in some cases, to lost the type of the entrys so I must to add only approximately 22 new entrys. 3) Try to store the entire entry (for example "X-AIM;TYPE=HOME;X-EVOLUTION-UI-SLOT=1:aim" ) into an field and attach it to the vcard without parse it. This require approximately 22 new entrys. 4) Try to store any unknown entire entry into one fields and attach it to the vcard without parse it. This require approximately 1 new entrys. There is others possible solutions ? I tried to implement the solution n°3 and I wrote a patch that seem works. It's not complete and requires more works. I create 6 new entry for extended address and post office box value of home, work and others address. I create more generic fields +#define ID_GENERIC (SYNCE_ID_BASE+6) + +#define MAX_GENERIC 32 /* this is a test value */ and I store any entire not handle fields into one generic fields (ID_GENERIC, ID_GENERIC+1, ID_GENERIC+2 ...) with the add_generic function. To enable a new entry you must only to add into parser_handle_field function something like this: else if (STR_EQUAL(name, "X-AIM")) { add_generic(parser, name, type, value); } Not modify is require for rra_contact_to_vcard2 function. The patch require my two patch rra-vcard-empty-fields.3.diff and rra-vcard-duplicate-fields.diff ,I hope that twogood put they into cvs. Apply order is: empty-fields.3 duplicate-fields additional-fields I think that this patch is the beginning of discussion and I ready to trash she. If you think that I'm crazy or that is a good idea, don't hesitate to tell me! I'm waiting to known your opinion! Regards Sergio
--- ./lib/synce_ids.h.orig 1970-01-01 01:00:00.000000000 +0100 +++ ./lib/synce_ids.h 2005-11-08 12:48:06.000000000 +0100 @@ -0,0 +1,18 @@ +/* */ +#ifndef __synce_ids_h__ +#define __synce_ids_h__ + +#define SYNCE_ID_BASE 0xd000 + +#define ID_HOME_EXTENDED (SYNCE_ID_BASE+0) /* Extended address */ +#define ID_HOME_POSTOFF (SYNCE_ID_BASE+1) /* Post office box */ +#define ID_WORK_EXTENDED (SYNCE_ID_BASE+2) /* Extended address */ +#define ID_WORK_POSTOFF (SYNCE_ID_BASE+3) /* Post office box */ +#define ID_OTHER_EXTENDED (SYNCE_ID_BASE+4) /* Extended address */ +#define ID_OTHER_POSTOFF (SYNCE_ID_BASE+5) /* Post office box */ + +#define ID_GENERIC (SYNCE_ID_BASE+6) + +#define MAX_GENERIC 32 + +#endif --- ./lib/contact.c.orig 2005-11-08 09:08:42.000000000 +0100 +++ ./lib/contact.c 2005-11-08 14:41:20.000000000 +0100 @@ -2,6 +2,7 @@ #define _GNU_SOURCE 1 #include "contact.h" #include "contact_ids.h" +#include "synce_ids.h" #include "strbuf.h" #include "dbstream.h" #include "strv.h" @@ -22,7 +23,7 @@ * the theoretical field count maximum is about 50, * and we add 10 to be safe */ -#define MAX_FIELD_COUNT 60 +#define MAX_FIELD_COUNT 90 /* ESCAPED-CHAR = "\\" / "\;" / "\," / "\n" / "\N") @@ -223,6 +224,8 @@ WCHAR* department = NULL; /* home address parts */ + WCHAR* home_extended = NULL; + WCHAR* home_postoff = NULL; WCHAR* home_street = NULL; WCHAR* home_locality = NULL; WCHAR* home_region = NULL; @@ -230,6 +233,8 @@ WCHAR* home_country = NULL; /* work address parts */ + WCHAR* work_extended = NULL; + WCHAR* work_postoff = NULL; WCHAR* work_street = NULL; WCHAR* work_locality = NULL; WCHAR* work_region = NULL; @@ -237,6 +242,8 @@ WCHAR* work_country = NULL; /* other address parts */ + WCHAR* other_extended = NULL; + WCHAR* other_postoff = NULL; WCHAR* other_street = NULL; WCHAR* other_locality = NULL; WCHAR* other_region = NULL; @@ -412,6 +419,14 @@ middle_name = pFields[i].val.lpwstr; break; + case ID_HOME_EXTENDED: + home_extended = pFields[i].val.lpwstr; + break; + + case ID_HOME_POSTOFF: + home_postoff = pFields[i].val.lpwstr; + break; + case ID_HOME_STREET: home_street = pFields[i].val.lpwstr; break; @@ -432,6 +447,14 @@ home_country = pFields[i].val.lpwstr; break; + case ID_WORK_EXTENDED: + work_extended = pFields[i].val.lpwstr; + break; + + case ID_WORK_POSTOFF: + work_postoff = pFields[i].val.lpwstr; + break; + case ID_WORK_STREET: work_street = pFields[i].val.lpwstr; break; @@ -452,6 +475,14 @@ work_country = pFields[i].val.lpwstr; break; + case ID_OTHER_EXTENDED: + other_extended = pFields[i].val.lpwstr; + break; + + case ID_OTHER_POSTOFF: + other_postoff = pFields[i].val.lpwstr; + break; + case ID_OTHER_STREET: other_street = pFields[i].val.lpwstr; break; @@ -516,7 +547,14 @@ break; default: - synce_warning("Did not handle field with ID %04x", pFields[i].propid >> 16); + if ((ID_GENERIC <= (pFields[i].propid >> 16)) && + ((pFields[i].propid >> 16) < (ID_GENERIC + MAX_GENERIC))) + { + strbuf_append(vcard, wstr_to_ascii(pFields[i].val.lpwstr)); + strbuf_append_crlf(vcard); + } + else + synce_warning("Did not handle field with ID %04x", pFields[i].propid >> 16); break; } } @@ -556,12 +594,13 @@ * the region (e.g., state or province); the postal code; the country name. */ - if (home_street || home_locality || home_postal_code || home_country) + if ( home_extended || home_postoff || home_street || home_locality || + home_region || home_postal_code || home_country) { strbuf_append_type(vcard, "ADR", "HOME", flags); - strbuf_append_escaped_wstr (vcard, NULL, flags); /* post office box */ + strbuf_append_escaped_wstr (vcard, home_extended, flags); strbuf_append_c (vcard, ';'); - strbuf_append_escaped_wstr (vcard, NULL, flags); /* extended address */ + strbuf_append_escaped_wstr (vcard, home_postoff, flags); strbuf_append_c (vcard, ';'); strbuf_append_escaped_wstr (vcard, home_street, flags); strbuf_append_c (vcard, ';'); @@ -575,12 +614,13 @@ strbuf_append_crlf (vcard); } - if (work_street || work_locality || work_postal_code || work_country) + if ( work_extended || work_postoff || work_street || work_locality || + work_region || work_postal_code || work_country) { strbuf_append_type(vcard, "ADR", "WORK", flags); - strbuf_append_escaped_wstr (vcard, NULL, flags); /* post office box */ + strbuf_append_escaped_wstr (vcard, work_extended, flags); strbuf_append_c (vcard, ';'); - strbuf_append_escaped_wstr (vcard, NULL, flags); /* extended address */ + strbuf_append_escaped_wstr (vcard, work_postoff, flags); strbuf_append_c (vcard, ';'); strbuf_append_escaped_wstr (vcard, work_street, flags); strbuf_append_c (vcard, ';'); @@ -594,12 +634,13 @@ strbuf_append_crlf (vcard); } - if (other_street || other_locality || other_postal_code || other_country) + if ( other_extended || other_postoff || other_street || other_locality || + other_region || other_postal_code || other_country) { strbuf_append_type(vcard, "ADR", "POSTAL", flags); - strbuf_append_escaped_wstr (vcard, NULL, flags); /* post office box */ + strbuf_append_escaped_wstr (vcard, other_extended, flags); strbuf_append_c (vcard, ';'); - strbuf_append_escaped_wstr (vcard, NULL, flags); /* extended address */ + strbuf_append_escaped_wstr (vcard, other_postoff, flags); strbuf_append_c (vcard, ';'); strbuf_append_escaped_wstr (vcard, other_street, flags); strbuf_append_c (vcard, ';'); @@ -715,6 +756,7 @@ int level; CEPROPVAL* fields; size_t field_index; + size_t generic_index; bool utf8; /* default charset is utf8 */ } Parser; @@ -767,9 +809,17 @@ INDEX_EMAIL, INDEX_EMAIL2, INDEX_EMAIL3, - ID_COUNT + INDEX_HOME_EXTENDED, + INDEX_HOME_POSTOFF, + INDEX_WORK_EXTENDED, + INDEX_WORK_POSTOFF, + INDEX_OTHER_EXTENDED, + INDEX_OTHER_POSTOFF, + INDEX_GENERIC } field_index; +#define ID_COUNT INDEX_GENERIC + #define NAME_FIELD_COUNT 5 static uint32_t name_index[NAME_FIELD_COUNT] = @@ -789,8 +839,8 @@ static uint32_t address_index[ADDRESS_FIELD_COUNT][3] = { - {0, 0}, /* post office box */ - {0, 0}, /* extended address */ + {INDEX_HOME_EXTENDED, INDEX_WORK_EXTENDED, INDEX_OTHER_EXTENDED}, /* post office box */ + {INDEX_HOME_POSTOFF, INDEX_WORK_POSTOFF, INDEX_OTHER_POSTOFF}, /* 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 */ @@ -846,7 +896,13 @@ ID_OTHER_COUNTRY, ID_EMAIL, ID_EMAIL2, - ID_EMAIL3 + ID_EMAIL3, + ID_HOME_EXTENDED, + ID_HOME_POSTOFF, + ID_WORK_EXTENDED, + ID_WORK_POSTOFF, + ID_OTHER_EXTENDED, + ID_OTHER_POSTOFF }; static char* strdup_quoted_printable(const unsigned char* source)/*{{{*/ @@ -936,7 +992,56 @@ return true; }/*}}}*/ -static void add_date(Parser* parser, uint32_t index, const char* type, char* value) +static void add_generic(Parser* parser, const char* name, const char* type, char* value)/*{{{*/ +{ + char* converted = NULL; + char* line = NULL; + CEPROPVAL* field = &parser->fields[parser->generic_index]; + + assert(value); + + if (parser->generic_index < MAX_GENERIC) + { + field->propid = ((ID_GENERIC + parser->generic_index++ ) << 16) | + CEVT_LPWSTR; + + line = malloc(strlen(name) + strlen(type) + strlen(value) + 3); + line[0] = '\0'; + + if (strlen(name)) + strncat(line, name, strlen(name)); + if (strlen(type)) { + strncat(line, strdup(";"), strlen(line) + 1); + strncat(line, type, strlen(line) + strlen(type)); + } + strncat(line, strdup(":"), strlen(line) + 1); + strncat(line, value, strlen(line) + strlen(value)); + + if (STR_IN_STR(type, "QUOTED-PRINTABLE")) + { + line = converted = strdup_quoted_printable(line); + assert(line); + } + + unescape_string(line); + assert(line); + + fprintf(stderr, "CERLY line[%s]\n", line); + if (parser->utf8 || STR_IN_STR(type, "UTF-8")) + field->val.lpwstr = wstr_from_utf8(line); + else + field->val.lpwstr = wstr_from_ascii(line); + + assert(field->val.lpwstr); + + if (line) + free(line); + if (converted) + free(converted); + } +} + +static void add_date(Parser* parser, uint32_t index, const char* name, const char* type, char* value) { TIME_FIELDS time_fields; @@ -950,10 +1055,12 @@ propval->propid = (field_id[index] << 16) | CEVT_FILETIME; time_fields_to_filetime(&time_fields, &propval->val.filetime); } + else + add_generic(parser, name, type, value); } } -static void add_string(Parser* parser, uint32_t index, const char* type, char* value)/*{{{*/ +static void add_string(Parser* parser, uint32_t index, const char* name, const char* type, char* value)/*{{{*/ { char* converted = NULL; CEPROPVAL* field = &parser->fields[index]; @@ -983,6 +1090,8 @@ if (converted) free(converted); } + else + add_generic(parser, name, type, value); }/*}}}*/ static bool parser_handle_field(/*{{{*/ @@ -1050,22 +1159,22 @@ }/*}}}*/ else if (STR_EQUAL(name, "FN"))/*{{{*/ { - add_string(parser, INDEX_FULL_NAME, type, value); + add_string(parser, INDEX_FULL_NAME, name, type, value); }/*}}}*/ else if (STR_EQUAL(name, "N"))/*{{{*/ { int i; - char** name = strsplit(value, ';'); + char** tmp_name = strsplit(value, ';'); - for (i = 0; i < NAME_FIELD_COUNT && name[i]; i++) + for (i = 0; i < NAME_FIELD_COUNT && tmp_name[i]; i++) { - if (*name[i]) + if (*tmp_name[i]) { - add_string(parser, name_index[i], type, name[i]); + add_string(parser, name_index[i], name, type, tmp_name[i]); } } - strv_free(name); + strv_free(tmp_name); }/*}}}*/ else if (STR_EQUAL(name, "ADR"))/*{{{*/ { @@ -1091,7 +1200,7 @@ { if (address_index[i][where] && *address[i]) { - add_string(parser, address_index[i][where], type, address[i]); + add_string(parser, address_index[i][where], name, type, address[i]); } } @@ -1105,36 +1214,36 @@ if (STR_IN_STR(type, "HOME")) { if (nth==1) - add_string(parser, fax ? INDEX_HOME_FAX : INDEX_HOME_TEL, type, value); + add_string(parser, fax ? INDEX_HOME_FAX : INDEX_HOME_TEL, name, type, value); else - add_string(parser, INDEX_HOME2_TEL, type, value); + add_string(parser, INDEX_HOME2_TEL, name, type, value); } else if (STR_IN_STR(type, "WORK")) { if (nth==1) - add_string(parser, fax ? INDEX_WORK_FAX : INDEX_WORK_TEL, type, value); + add_string(parser, fax ? INDEX_WORK_FAX : INDEX_WORK_TEL, name, type, value); else - add_string(parser, INDEX_WORK2_TEL, type, value); + add_string(parser, INDEX_WORK2_TEL, name, type, value); } else if (STR_IN_STR(type, "CELL")) { - add_string(parser, INDEX_MOBILE_TEL, type, value); + add_string(parser, INDEX_MOBILE_TEL, name, type, value); } else if (STR_IN_STR(type, "X-EVOLUTION-ASSISTANT")) { - add_string(parser, INDEX_ASSISTANT_TEL, type, value); + add_string(parser, INDEX_ASSISTANT_TEL, name, type, value); } else if (STR_IN_STR(type, "X-EVOLUTION-RADIO")) { - add_string(parser, INDEX_RADIO_TEL, type, value); + add_string(parser, INDEX_RADIO_TEL, name, type, value); } else if (STR_IN_STR(type, "CAR")) { - add_string(parser, INDEX_CAR_TEL, type, value); + add_string(parser, INDEX_CAR_TEL, name, type, value); } else if (STR_IN_STR(type, "PAGER")) { - add_string(parser, INDEX_PAGER, type, value); + add_string(parser, INDEX_PAGER, name, type, value); } else { @@ -1155,19 +1264,19 @@ switch (nth) { case 1: - add_string(parser, INDEX_EMAIL, type, value); + add_string(parser, INDEX_EMAIL, name, type, value); break; case 2: - add_string(parser, INDEX_EMAIL2, type, value); + add_string(parser, INDEX_EMAIL2, name, type, value); break; case 3: - add_string(parser, INDEX_EMAIL3, type, value); + add_string(parser, INDEX_EMAIL3, name, type, value); break; } }/*}}}*/ else if (STR_EQUAL(name, "URL"))/*{{{*/ { - add_string(parser, INDEX_WEB_PAGE, type, value); + add_string(parser, INDEX_WEB_PAGE, name, type, value); }/*}}}*/ else if (STR_EQUAL(name, "ORG"))/*{{{*/ { @@ -1175,19 +1284,19 @@ if (separator) { if (separator[1]) { - add_string(parser, INDEX_DEPARTMENT, type, separator + 1); + add_string(parser, INDEX_DEPARTMENT, name, type, separator + 1); } *separator = '\0'; } if (value[0]) { - add_string(parser, INDEX_COMPANY, type, value); + add_string(parser, INDEX_COMPANY, name, type, value); } }/*}}}*/ else if (STR_EQUAL(name, "TITLE"))/*{{{*/ { - add_string(parser, INDEX_JOB_TITLE, type, value); + add_string(parser, INDEX_JOB_TITLE, name, type, value); }/*}}}*/ else if (STR_EQUAL(name, "X-EVOLUTION-FILE-AS"))/*{{{*/ { @@ -1205,27 +1314,31 @@ }/*}}}*/ else if (STR_EQUAL(name, "CATEGORIES")) { - add_string(parser, INDEX_CATEGORY, type, value); + add_string(parser, INDEX_CATEGORY, name, type, value); } else if (STR_EQUAL(name, "BDAY")) { - add_date(parser, INDEX_BIRTHDAY, type, value); + add_date(parser, INDEX_BIRTHDAY, name, type, value); } else if (STR_EQUAL(name, "X-EVOLUTION-ANNIVERSARY")) { - add_date(parser, INDEX_ANNIVERSARY, type, value); + add_date(parser, INDEX_ANNIVERSARY, name, type, value); } else if (STR_EQUAL(name, "X-EVOLUTION-SPOUSE")) { - add_string(parser, INDEX_SPOUSE, type, value); + add_string(parser, INDEX_SPOUSE, name, type, value); } else if (STR_EQUAL(name, "X-EVOLUTION-ASSISTANT")) { - add_string(parser, INDEX_ASSISTANT, type, value); + add_string(parser, INDEX_ASSISTANT, name, type, value); } else if (STR_EQUAL(name, "X-EVOLUTION-OFFICE")) { - add_string(parser, INDEX_OFFICE_LOC, type, value); + add_string(parser, INDEX_OFFICE_LOC, name, type, value); + } + else if (STR_EQUAL(name, "X-AIM")) + { + add_generic(parser, name, type, value); } #if 0 @@ -1379,9 +1492,10 @@ parser.level = 0; parser.fields = fields; parser.field_index = 0; + parser.generic_index = 0; parser.utf8 = flags & RRA_CONTACT_UTF8; - for (count=0; count < ID_COUNT; count++) + for (count=0; count < (ID_COUNT + MAX_GENERIC); count++) { CEPROPVAL* field = &parser.fields[parser.field_index++]; @@ -1390,8 +1504,12 @@ field->propid = (field_id[count] << 16) | CEVT_FLAG_EMPTY | CEVT_FILETIME; else - field->propid = (field_id[count] << 16) | - CEVT_FLAG_EMPTY | CEVT_LPWSTR; + if (count < ID_COUNT) + field->propid = (field_id[count] << 16) | + CEVT_FLAG_EMPTY | CEVT_LPWSTR; + else + field->propid = ((ID_GENERIC + (count - ID_COUNT)) << 16) | + CEVT_FLAG_EMPTY | CEVT_LPWSTR; } while (*p && parser.field_index < max_field_count)
--- ./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)