Il giorno ven, 24/02/2006 alle 16.26 +0100, Nabil Sayegh ha scritto: > Am Freitag, 24. Februar 2006 15:00 schrieb Sergio CERLESi: > > If you are interesting I wrote a sequence of patch that I and others > > people on my office used:
> Great, could you please attach them? > rgds Hi Nabil, I'm very happy to known that you are interesting! Don't hesitate to call me for anything. Now, I'm going offline, have a nice week. Regards Sergio
--- ./lib/contact.c.Orig 2006-01-17 18:50:13.000000000 +0100 +++ ./lib/contact.c 2006-01-18 09:33:21.000000000 +0100 @@ -718,15 +718,71 @@ 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 +791,70 @@ #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 */ - {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 */ + {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] = +{ +/* + 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 +944,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 +952,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 +1052,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 +1063,7 @@ { if (*name[i]) { - add_string(parser, name_ids[i], type, name[i]); + add_string(parser, name_index[i], type, name[i]); } } @@ -980,9 +1091,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 +1107,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 +1157,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 +1177,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 +1207,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 +1361,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 +1383,24 @@ parser.field_index = 0; parser.utf8 = flags & RRA_CONTACT_UTF8; + for (count=0; count < ID_COUNT; count++) + { + CEPROPVAL* field = &parser.fields[parser.field_index++]; + + switch(count) + { + case INDEX_BIRTHDAY: + case INDEX_ANNIVERSARY: + field->propid = (field_id[count] << 16) | + CEVT_FLAG_EMPTY | CEVT_FILETIME; + break; + default: + field->propid = (field_id[count] << 16) | + CEVT_FLAG_EMPTY | CEVT_LPWSTR; + break; + } + } + while (*p && parser.field_index < max_field_count) { switch (state)
--- ./lib/contact.c.Orig 2006-01-18 09:36:16.000000000 +0100 +++ ./lib/contact.c 2006-01-18 09:36:45.000000000 +0100 @@ -953,8 +953,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); + } } } @@ -965,26 +968,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 2006-01-18 09:40:31.000000000 +0100 +++ ./lib/contact.c 2006-01-18 09:40:38.000000000 +0100 @@ -716,6 +716,9 @@ CEPROPVAL* fields; size_t field_index; bool utf8; /* default charset is utf8 */ + int count_email; + int count_tel_work; + int count_tel_home; } Parser; typedef enum _field_index @@ -997,8 +1000,7 @@ Parser* parser, char* name, char* type, - char* value, - int nth) + char* value) { bool success = false; @@ -1029,7 +1031,7 @@ } }/*}}}*/ - if (parser->level != 1 && nth==0) + if (parser->level != 1) { synce_error("Not within BEGIN:VCARD / END:VCARD"); goto exit; @@ -1112,17 +1114,35 @@ /* TODO: make type uppercase */ if (STR_IN_STR(type, "HOME")) { - if (nth==1) - add_string(parser, fax ? INDEX_HOME_FAX : INDEX_HOME_TEL, type, value); - else - add_string(parser, INDEX_HOME2_TEL, type, value); + if (fax) { + add_string(parser, INDEX_HOME_FAX, type, value); + } else { + switch (parser->count_tel_home++) + { + case 0: + add_string(parser, INDEX_HOME_TEL, type, value); + break; + case 1: + add_string(parser, INDEX_HOME2_TEL, type, value); + break; + } + } } else if (STR_IN_STR(type, "WORK")) { - if (nth==1) - add_string(parser, fax ? INDEX_WORK_FAX : INDEX_WORK_TEL, type, value); - else - add_string(parser, INDEX_WORK2_TEL, type, value); + if (fax) { + add_string(parser, INDEX_WORK_FAX, type, value); + } else { + switch (parser->count_tel_work++) + { + case 0: + add_string(parser, INDEX_WORK_TEL, type, value); + break; + case 1: + add_string(parser, INDEX_WORK2_TEL, type, value); + break; + } + } } else if (STR_IN_STR(type, "CELL")) { @@ -1159,19 +1179,19 @@ synce_trace("Unexpected type '%s' for field '%s', assuming 'INTERNET'", type, name); } - - switch (nth) - { - case 1: - add_string(parser, INDEX_EMAIL, type, value); - break; - case 2: - add_string(parser, INDEX_EMAIL2, type, value); - break; - case 3: - add_string(parser, INDEX_EMAIL3, type, value); - break; - } + + switch (parser->count_email++) + { + case 0: + add_string(parser, INDEX_EMAIL, type, value); + break; + case 1: + add_string(parser, INDEX_EMAIL2, type, value); + break; + case 2: + add_string(parser, INDEX_EMAIL3, type, value); + break; + } }/*}}}*/ else if (STR_EQUAL(name, "URL"))/*{{{*/ { @@ -1270,27 +1290,33 @@ }/*}}}*/ /* + * we add 40 for additional fields + * that are been handled by others application, + * evolution have about 28 additional fields + */ +#define MAX_ENQUEUE_FIELD (MAX_FIELD_COUNT + 40) + +/* * all tel_work, tel_home and email must be considered before * deciding which will get a slot, as there may be too many */ void enqueue_field(/*{{{*/ struct FieldStrings *fs, int *count, - int max, struct FieldStrings *data) { int slot=-1; int i; /* if there are free slots, there is no problem */ - if ((*count)<max) + if ((*count)<MAX_ENQUEUE_FIELD) slot=(*count); else if (data->pref) /* so there is no free slot, but a(nother) preferred one is coming kick out a non-preferred one, if possible */ - for (i=0; i<max; i++) - if (!fs[i].pref) { + for (i=0; i<MAX_ENQUEUE_FIELD; i++) + if (!fs[i].pref && !strcmp(fs[i].type, data->type)) { slot=i; break; } @@ -1312,21 +1338,18 @@ int count) { int i; - int j=1; char *loc; /* Get the first preferred and make it the preferred one on the device */ for (i=0; i<count; i++) { - if (fs[i].pref || count==(i+1)) { + if (fs[i].pref || i == 0) { parser_handle_field( parser, fs[i].name, fs[i].type, - fs[i].value, - 1); + fs[i].value); /* mark this as already processed */ fs[i].name=NULL; - break; } } @@ -1345,9 +1368,7 @@ parser, fs[i].name, fs[i].type, - fs[i].value, - j+1); - j++; + fs[i].value); } } }/*}}}*/ @@ -1375,13 +1396,10 @@ const char* value = NULL; const char* value_end = NULL; - struct FieldStrings *tel_work = malloc( MAX_TEL_WORK * sizeof( struct FieldStrings ) ); - struct FieldStrings *tel_home = malloc( MAX_TEL_HOME * sizeof( struct FieldStrings ) ); - struct FieldStrings *email = malloc( MAX_EMAIL * sizeof( struct FieldStrings ) ); + struct FieldStrings *queue_field = malloc( MAX_ENQUEUE_FIELD * sizeof( struct FieldStrings ) ); struct FieldStrings *tmp_field = malloc( 1 * sizeof( struct FieldStrings ) ); - int count_tel_work = 0; - int count_tel_home = 0; - int count_email = 0; + + int count_field = 0; parser.vcard_version = RRA_CONTACT_VERSION_UNKNOWN; parser.level = 0; @@ -1389,6 +1407,10 @@ parser.field_index = 0; parser.utf8 = flags & RRA_CONTACT_UTF8; + parser.count_email = 0; + parser.count_tel_work = 0; + parser.count_tel_home = 0; + for (count=0; count < ID_COUNT; count++) { CEPROPVAL* field = &parser.fields[parser.field_index++]; @@ -1466,33 +1488,13 @@ { value_end = p; - /* We have to queue tel and email fields, as there may be more than one, - and we have to find out, which one is the preferred. - Unfortunately there may be none, or many preferred fields :( - */ - tmp_field->name = strndup(name, name_end - name); tmp_field->type = type ? strndup(type, type_end - type) : strdup(""); tmp_field->value = strndup(value, value_end - value); tmp_field->pref = STR_IN_STR(tmp_field->type, "PREF"); - if (STR_IN_STR(tmp_field->name, "TEL") && STR_IN_STR(tmp_field->type, "WORK")) { - enqueue_field(tel_work, &count_tel_work, MAX_TEL_WORK, tmp_field); - } - else if (STR_IN_STR(tmp_field->name, "TEL") && STR_IN_STR(tmp_field->type, "HOME")) { - enqueue_field(tel_home, &count_tel_home, MAX_TEL_HOME, tmp_field); - } - else if (STR_IN_STR(tmp_field->name, "EMAIL")) { - enqueue_field(email, &count_email, MAX_EMAIL, tmp_field); - } - else { - parser_handle_field( - &parser, - tmp_field->name, - tmp_field->type, - tmp_field->value, - 0); - } + enqueue_field(queue_field, &count_field, tmp_field); + state = VCARD_STATE_NEWLINE; } p++; @@ -1504,9 +1506,7 @@ } } - process_queue(&parser, tel_work, count_tel_work); - process_queue(&parser, tel_home, count_tel_home); - process_queue(&parser, email, count_email); + process_queue(&parser, queue_field, count_field); *field_count = parser.field_index;
--- ./lib/contact.c.Orig 2006-01-18 09:41:46.000000000 +0100 +++ ./lib/contact.c 2006-01-18 09:44:44.000000000 +0100 @@ -700,6 +700,7 @@ VCARD_STATE_NAME, VCARD_STATE_TYPE, VCARD_STATE_VALUE, + VCARD_STATE_MULTILINE, } VcardState; #define myisblank(c) ((c) == ' ' || (c) == '\t') @@ -1395,6 +1396,7 @@ const char* type_end = NULL; const char* value = NULL; const char* value_end = NULL; + char* value_ml = NULL; struct FieldStrings *queue_field = malloc( MAX_ENQUEUE_FIELD * sizeof( struct FieldStrings ) ); struct FieldStrings *tmp_field = malloc( 1 * sizeof( struct FieldStrings ) ); @@ -1436,7 +1438,7 @@ case VCARD_STATE_NEWLINE:/*{{{*/ if (myisblank(*p)) { - synce_error("Can't handle multiline values"); + synce_error("Failed to handle multiline values"); goto exit; } @@ -1452,6 +1454,7 @@ type_end = NULL; value = NULL; value_end = NULL; + value_ml = NULL; state = VCARD_STATE_NAME; } @@ -1488,6 +1491,21 @@ { value_end = p; + if (*(p+2) && myisblank(*(p+2))) + { + value_ml = malloc(strlen(vcard) - (value - vcard)); + value_ml[0] = '\0'; + + strncat(value_ml, value, value_end - value); + + p = p + 3; + value = p; + + state = VCARD_STATE_MULTILINE; + + break; + } + tmp_field->name = strndup(name, name_end - name); tmp_field->type = type ? strndup(type, type_end - type) : strdup(""); tmp_field->value = strndup(value, value_end - value); @@ -1496,10 +1514,35 @@ enqueue_field(queue_field, &count_field, tmp_field); state = VCARD_STATE_NEWLINE; + + if (value_ml) + free(value_ml); } p++; break;/*}}}*/ + case VCARD_STATE_MULTILINE:/*{{{*/ + if (myisnewline(*p)) + { + value_end = p; + + strncat(value_ml, value, value_end - value); + + if (*(p+2) && myisblank(*(p+2))) + { + p = p + 3; + value = p; + } + else + { + value = value_ml; + state = VCARD_STATE_VALUE; + } + } + else + p++; + break;/*}}}*/ + default: synce_error("Unknown state: %i", state); goto exit;
--- ./lib/contact.c.Orig 2006-01-18 09:46:49.000000000 +0100 +++ ./lib/contact.c 2006-01-18 09:47:16.000000000 +0100 @@ -333,8 +333,8 @@ company = pFields[i].val.lpwstr; break; - case ID_JOB_TITLE: - strbuf_append(vcard, "TITLE:"); + case ID_JOB_ROLE: + strbuf_append(vcard, "ROLE:"); strbuf_append_escaped_wstr(vcard, pFields[i].val.lpwstr, flags); strbuf_append_crlf(vcard); break; @@ -733,7 +733,7 @@ INDEX_HOME_TEL, INDEX_LAST_NAME, INDEX_COMPANY, - INDEX_JOB_TITLE, + INDEX_JOB_ROLE, INDEX_DEPARTMENT, INDEX_OFFICE_LOC, INDEX_MOBILE_TEL, @@ -817,7 +817,7 @@ ID_HOME_TEL, ID_LAST_NAME, ID_COMPANY, - ID_JOB_TITLE, + ID_JOB_ROLE, ID_DEPARTMENT, ID_OFFICE_LOC, ID_MOBILE_TEL, @@ -1214,9 +1214,9 @@ add_string(parser, INDEX_COMPANY, type, value); } }/*}}}*/ - else if (STR_EQUAL(name, "TITLE"))/*{{{*/ + else if (STR_EQUAL(name, "ROLE"))/*{{{*/ { - add_string(parser, INDEX_JOB_TITLE, type, value); + add_string(parser, INDEX_JOB_ROLE, type, value); }/*}}}*/ else if (STR_EQUAL(name, "X-EVOLUTION-FILE-AS"))/*{{{*/ { --- ./lib/contact_ids.h.Orig 2006-01-18 09:46:50.000000000 +0100 +++ ./lib/contact_ids.h 2006-01-18 09:47:16.000000000 +0100 @@ -9,7 +9,7 @@ #define ID_HOME_TEL 0x3a09 #define ID_LAST_NAME 0x3a11 #define ID_COMPANY 0x3a16 -#define ID_JOB_TITLE 0x3a17 +#define ID_JOB_ROLE 0x3a17 #define ID_DEPARTMENT 0x3a18 #define ID_OFFICE_LOC 0x3a19 #define ID_MOBILE_TEL 0x3a1c
--- ./lib/contact.c.Orig 2006-01-18 09:49:44.000000000 +0100 +++ ./lib/contact.c 2006-01-18 09:50:00.000000000 +0100 @@ -221,6 +221,7 @@ /* organization parts */ WCHAR* company = NULL; WCHAR* department = NULL; + WCHAR* office = NULL; /* home address parts */ WCHAR* home_street = NULL; @@ -504,9 +505,7 @@ break; case ID_OFFICE_LOC: - strbuf_append(vcard, "X-EVOLUTION-OFFICE:"); - strbuf_append_escaped_wstr(vcard, pFields[i].val.lpwstr, flags); - strbuf_append_crlf(vcard); + office = pFields[i].val.lpwstr; break; case ID_RADIO_TEL: @@ -541,12 +540,14 @@ * followed by one or more levels of organizational unit names. */ - if (company || department) + if (company || department || office) { strbuf_append(vcard, "ORG:"); strbuf_append_escaped_wstr (vcard, company, flags); strbuf_append_c (vcard, ';'); strbuf_append_escaped_wstr (vcard, department, flags); + strbuf_append_c (vcard, ';'); + strbuf_append_escaped_wstr (vcard, office, flags); strbuf_append_crlf (vcard); } @@ -1204,6 +1205,12 @@ if (separator) { if (separator[1]) { + char* separator2 = strchr(separator + 1, ';'); + if (separator2) + { + add_string(parser, INDEX_OFFICE_LOC, type, separator2 + 1); + *separator2 = '\0'; + } add_string(parser, INDEX_DEPARTMENT, type, separator + 1); } *separator = '\0'; @@ -1252,10 +1259,6 @@ { add_string(parser, INDEX_ASSISTANT, type, value); } - else if (STR_EQUAL(name, "X-EVOLUTION-OFFICE")) - { - add_string(parser, INDEX_OFFICE_LOC, type, value); - } #if 0 else if (STR_EQUAL(name, ""))
--- ./lib/contact.c.Orig 2006-01-18 09:56:42.000000000 +0100 +++ ./lib/contact.c 2006-01-18 09:56:46.000000000 +0100 @@ -597,7 +597,7 @@ if (other_street || other_locality || other_postal_code || other_country) { - strbuf_append_type(vcard, "ADR", "POSTAL", flags); + strbuf_append_type(vcard, "ADR", "OTHER", flags); strbuf_append_escaped_wstr (vcard, NULL, flags); /* post office box */ strbuf_append_c (vcard, ';'); strbuf_append_escaped_wstr (vcard, NULL, flags); /* extended address */ @@ -1085,7 +1085,7 @@ char** address = strsplit(value, ';'); int where; - if (STR_IN_STR(type, "POSTAL")) + if (STR_IN_STR(type, "OTHER")) where = OTHER; else if (STR_IN_STR(type, "WORK")) where = WORK;
--- ./lib/contact.c.Orig 2006-01-18 10:05:05.000000000 +0100 +++ ./lib/contact.c 2006-01-18 10:05:31.000000000 +0100 @@ -559,12 +559,28 @@ if (home_street || home_locality || home_postal_code || home_country) { + char *street = NULL; + char *extended = NULL; + + if (home_street) + { + if (flags & RRA_CONTACT_UTF8) + street = wstr_to_utf8(home_street); + else + street = wstr_to_ascii(home_street); + + extended = strstr(street, "\n"); + + if (extended) + extended++[-1] = '\0'; + } + strbuf_append_type(vcard, "ADR", "HOME", flags); strbuf_append_escaped_wstr (vcard, NULL, flags); /* post office box */ strbuf_append_c (vcard, ';'); - strbuf_append_escaped_wstr (vcard, NULL, flags); /* extended address */ + strbuf_append_escaped (vcard, extended, flags); /* extended address */ strbuf_append_c (vcard, ';'); - strbuf_append_escaped_wstr (vcard, home_street, flags); + strbuf_append_escaped (vcard, street, flags); strbuf_append_c (vcard, ';'); strbuf_append_escaped_wstr (vcard, home_locality, flags); strbuf_append_c (vcard, ';'); @@ -574,16 +590,35 @@ strbuf_append_c (vcard, ';'); strbuf_append_escaped_wstr (vcard, home_country, flags); strbuf_append_crlf (vcard); + + if (street) + wstr_free_string(street); } if (work_street || work_locality || work_postal_code || work_country) { + char *street = NULL; + char *extended = NULL; + + if (work_street) + { + if (flags & RRA_CONTACT_UTF8) + street = wstr_to_utf8(work_street); + else + street = wstr_to_ascii(work_street); + + extended = strstr(street, "\n"); + + if (extended) + extended++[-1] = '\0'; + } + strbuf_append_type(vcard, "ADR", "WORK", flags); strbuf_append_escaped_wstr (vcard, NULL, flags); /* post office box */ strbuf_append_c (vcard, ';'); - strbuf_append_escaped_wstr (vcard, NULL, flags); /* extended address */ + strbuf_append_escaped (vcard, extended, flags); /* extended address */ strbuf_append_c (vcard, ';'); - strbuf_append_escaped_wstr (vcard, work_street, flags); + strbuf_append_escaped (vcard, street, flags); strbuf_append_c (vcard, ';'); strbuf_append_escaped_wstr (vcard, work_locality, flags); strbuf_append_c (vcard, ';'); @@ -593,16 +628,35 @@ strbuf_append_c (vcard, ';'); strbuf_append_escaped_wstr (vcard, work_country, flags); strbuf_append_crlf (vcard); + + if (street) + wstr_free_string(street); } if (other_street || other_locality || other_postal_code || other_country) { + char *street = NULL; + char *extended = NULL; + + if (other_street) + { + if (flags & RRA_CONTACT_UTF8) + street = wstr_to_utf8(other_street); + else + street = wstr_to_ascii(other_street); + + extended = strstr(street, "\n"); + + if (extended) + extended++[-1] = '\0'; + } + strbuf_append_type(vcard, "ADR", "OTHER", flags); strbuf_append_escaped_wstr (vcard, NULL, flags); /* post office box */ strbuf_append_c (vcard, ';'); - strbuf_append_escaped_wstr (vcard, NULL, flags); /* extended address */ + strbuf_append_escaped (vcard, extended, flags); /* extended address */ strbuf_append_c (vcard, ';'); - strbuf_append_escaped_wstr (vcard, other_street, flags); + strbuf_append_escaped (vcard, street, flags); strbuf_append_c (vcard, ';'); strbuf_append_escaped_wstr (vcard, other_locality, flags); strbuf_append_c (vcard, ';'); @@ -612,6 +666,9 @@ strbuf_append_c (vcard, ';'); strbuf_append_escaped_wstr (vcard, other_country, flags); strbuf_append_crlf (vcard); + + if (street) + wstr_free_string(street); } @@ -1103,7 +1160,15 @@ { if (address_index[i][where] && *address[i]) { - add_string(parser, address_index[i][where], type, address[i]); + if (i == 2 && *address[1]) + { + char buf[strlen(address[1]) + strlen(address[2]) + 3]; + + snprintf(buf, sizeof(buf), "%s\\n%s", address[2], address[1]); + + add_string(parser, address_index[i][where], type, buf); + } else + add_string(parser, address_index[i][where], type, address[i]); } }
--- ./lib/contact.c.Orig 2006-01-20 17:40:47.000000000 +0100 +++ ./lib/contact.c 2006-01-20 17:41:31.000000000 +0100 @@ -41,6 +41,8 @@ static void strbuf_append_escaped(StrBuf switch (*p) { case '\r': /* CR */ + case 19: /* XOFF */ + case 31: /* Unit separator */ /* ignore */ break; @@ -284,18 +286,16 @@ static bool rra_contact_to_vcard2(/*{{{* strbuf_append_date(vcard, "BDAY", &pFields[i].val.filetime); break; -#if 0 case ID_NOTE: { unsigned j; - for (j = 0; j < pFields[i].val.blob.dwCount && pFields[i].val.blob.lpb[i]; j++) + for (j = 0; j < pFields[i].val.blob.dwCount && pFields[i].val.blob.lpb[j]; j++) ; if (j == pFields[i].val.blob.dwCount) { strbuf_append(vcard, "NOTE:"); - /* XXX: need to handle newlines! */ - strbuf_append(vcard, (const char*)pFields[i].val.blob.lpb); + strbuf_append_escaped(vcard, pFields[i].val.blob.lpb, flags); strbuf_append_crlf(vcard); } else @@ -304,7 +304,6 @@ static bool rra_contact_to_vcard2(/*{{{* } } break; -#endif case ID_SUFFIX: suffix = pFields[i].val.lpwstr; @@ -782,9 +781,6 @@ typedef struct _Parser typedef enum _field_index { -/* - INDEX_NOTE, -*/ INDEX_SUFFIX, INDEX_FIRST_NAME, INDEX_WORK_TEL, @@ -833,6 +829,7 @@ typedef enum _field_index INDEX_EMAIL, INDEX_EMAIL2, INDEX_EMAIL3, + INDEX_NOTE, ID_COUNT } field_index; @@ -866,9 +863,6 @@ static uint32_t address_index[ADDRESS_FI static const uint32_t field_id[ID_COUNT] = { -/* - ID_NOTE, -*/ ID_SUFFIX, ID_FIRST_NAME, ID_WORK_TEL, @@ -916,7 +910,8 @@ static const uint32_t field_id[ID_COUNT] ID_OTHER_COUNTRY, ID_EMAIL, ID_EMAIL2, - ID_EMAIL3 + ID_EMAIL3, + ID_NOTE, }; static char* strdup_quoted_printable(const unsigned char* source)/*{{{*/ @@ -1055,6 +1050,36 @@ static void add_string(Parser* parser, u } }/*}}}*/ +static void add_blob(Parser* parser, uint32_t index, const char* type, char* data)/*{{{*/ +{ + char* converted = NULL; + CEPROPVAL* field = &parser->fields[index]; + + assert(data); + + if (field->propid & CEVT_FLAG_EMPTY) + { + field->propid = (field_id[index] << 16) | CEVT_BLOB; + + if (STR_IN_STR(type, "QUOTED-PRINTABLE")) + { + data = converted = strdup_quoted_printable(data); + assert(data); + } + + unescape_string(data); + assert(data); + + field->val.blob.dwCount = strlen(data); + field->val.blob.lpb = malloc(field->val.blob.dwCount); + assert(field->val.blob.lpb); + memcpy(field->val.blob.lpb, data, field->val.blob.dwCount); + + if (converted) + free(converted); + } +}/*}}}*/ + static bool parser_handle_field(/*{{{*/ Parser* parser, char* name, @@ -1324,6 +1349,10 @@ static bool parser_handle_field(/*{{{*/ { add_string(parser, INDEX_ASSISTANT, type, value); } + else if (STR_EQUAL(name, "NOTE")) + { + add_blob(parser, INDEX_NOTE, type, value); + } #if 0 else if (STR_EQUAL(name, "")) @@ -1492,6 +1521,10 @@ static bool rra_contact_from_vcard2(/*{{ field->propid = (field_id[count] << 16) | CEVT_FLAG_EMPTY | CEVT_FILETIME; break; + case INDEX_NOTE: + field->propid = (field_id[count] << 16) | + CEVT_FLAG_EMPTY | CEVT_BLOB; + break; default: field->propid = (field_id[count] << 16) | CEVT_FLAG_EMPTY | CEVT_LPWSTR;
--- ./lib/contact.c.Orig 2006-01-20 17:51:58.000000000 +0100 +++ ./lib/contact.c 2006-01-20 17:52:04.000000000 +0100 @@ -513,6 +513,12 @@ static bool rra_contact_to_vcard2(/*{{{* strbuf_append_crlf(vcard); break; + case ID_CHILDREN: + strbuf_append(vcard, "X-SYNCE-CHILDREN:"); + strbuf_append_escaped_wstr(vcard, pFields[i].val.lpwstr, flags); + strbuf_append_crlf(vcard); + break; + default: synce_warning("Did not handle field with ID %04x", pFields[i].propid >> 16); break; @@ -801,9 +807,7 @@ typedef enum _field_index INDEX_CATEGORY, INDEX_ASSISTANT, INDEX_ASSISTANT_TEL, -/* INDEX_CHILDREN, -*/ INDEX_WORK2_TEL, INDEX_WEB_PAGE, INDEX_PAGER, @@ -883,9 +887,7 @@ static const uint32_t field_id[ID_COUNT] ID_CATEGORY, ID_ASSISTANT, ID_ASSISTANT_TEL, -/* ID_CHILDREN, -*/ ID_WORK2_TEL, ID_WEB_PAGE, ID_PAGER, @@ -1353,6 +1355,10 @@ static bool parser_handle_field(/*{{{*/ { add_blob(parser, INDEX_NOTE, type, value); } + else if (STR_EQUAL(name, "X-SYNCE-CHILDREN")) + { + add_string(parser, INDEX_CHILDREN, type, value); + } #if 0 else if (STR_EQUAL(name, ""))