From: Yang Gu Date: Mon, 22 Jun 2009 02:59:25 +0000 (+0800) Subject: Merge phonebook entries belong to one person X-Git-Tag: 0.1~64 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=95ec7c126f65417e2041cd8f3080f801879d5035;p=platform%2Fupstream%2Fofono.git Merge phonebook entries belong to one person --- diff --git a/drivers/atmodem/phonebook.c b/drivers/atmodem/phonebook.c index 82adf10..05ef090 100644 --- a/drivers/atmodem/phonebook.c +++ b/drivers/atmodem/phonebook.c @@ -55,7 +55,7 @@ static void at_cpbr_notify(GAtResult *result, gpointer user_data) const char *number; int type; const char *text; - int hidden = 0; + int hidden = -1; const char *group = NULL; const char *adnumber = NULL; int adtype = -1; diff --git a/src/phonebook.c b/src/phonebook.c index fa05d43..4cfb04e 100644 --- a/src/phonebook.c +++ b/src/phonebook.c @@ -46,12 +46,39 @@ #define PHONEBOOK_FLAG_CACHED 0x1 +enum { + TEL_TYPE_VOICE, + TEL_TYPE_HOME, + TEL_TYPE_MOBILE, + TEL_TYPE_FAX, + TEL_TYPE_WORK +}; + struct phonebook_data { struct ofono_phonebook_ops *ops; DBusMessage *pending; int storage_index; /* go through all supported storage */ int flags; GString *vcards; /* entries with vcard 3.0 format */ + GSList *merge_list; /* cache the entries that may need a merge */ +}; + +struct phonebook_number { + char *number; + int type; /* international or not */ + int category; /* represent for "WORK", "HOME", etc */ + int prefer; +}; + +struct phonebook_person { + GSList *number_list; /* one person may have more than one numbers */ + char *text; + int hidden; + char *group; + char *secondtext; + char *email; + char *sip_uri; + char *tel_uri; }; static const char *storage_support[] = { "\"SM\"", "\"ME\"", NULL }; @@ -135,20 +162,93 @@ static void add_slash(char *dest, const char *src, int len_max, int len) return; } -static void vcard_printf_number(GString *entries_vcard_pointer, int type, - const char *number, int prefer) +static void vcard_printf_begin(GString *vcards) +{ + vcard_printf(vcards, "BEGIN:VCARD"); + vcard_printf(vcards, "VERSION:3.0"); +} + +static void vcard_printf_text(GString *vcards, const char *text) { - char *pref = "", *intl = ""; + char field[LEN_MAX]; + add_slash(field, text, LEN_MAX, strlen(text)); + vcard_printf(vcards, "FN:%s", field); +} + +static void vcard_printf_number(GString *vcards, const char *number, int type, + int category, int prefer) +{ + char *pref = "", *intl = "", *category_string = ""; char buf[128]; + if (!number || !strlen(number) || !type) + return; + if (prefer) pref = "PREF,"; + switch (category) { + case TEL_TYPE_HOME: + category_string = "HOME"; + break; + case TEL_TYPE_MOBILE: + category_string = "CELL"; + break; + case TEL_TYPE_FAX: + category_string = "FAX"; + break; + case TEL_TYPE_WORK: + category_string = "WORK"; + break; + case TEL_TYPE_VOICE: + default: + category_string = "VOICE"; + break; + } + if ((type == TYPE_INTERNATIONAL) && (number[0] != '+')) intl = "+"; - sprintf(buf, "TEL;TYPE=\%sVOICE:\%s\%s", pref, intl, number); - vcard_printf(entries_vcard_pointer, buf, number); + sprintf(buf, "TEL;TYPE=\%s%s:\%s\%s", pref, + category_string, intl, number); + vcard_printf(vcards, buf, number); +} + +static void vcard_printf_group(GString *vcards, const char *group) +{ + int len = strlen(group); + if (group && len) { + char field[LEN_MAX]; + add_slash(field, group, LEN_MAX, len); + vcard_printf(vcards, "CATEGORIES:%s", field); + } +} + +static void vcard_printf_email(GString *vcards, const char *email) +{ + int len = strlen(email); + if (email && len) { + char field[LEN_MAX]; + add_slash(field, email, LEN_MAX, len); + vcard_printf(vcards, + "EMAIL;TYPE=INTERNET:%s", field); + } +} + +static void vcard_printf_sip_uri(GString *vcards, const char *sip_uri) +{ + int len = strlen(sip_uri); + if (sip_uri && len) { + char field[LEN_MAX]; + add_slash(field, sip_uri, LEN_MAX, len); + vcard_printf(vcards, "IMPP;TYPE=SIP:%s", field); + } +} + +static void vcard_printf_end(GString *vcards) +{ + vcard_printf(vcards, "END:VCARD"); + vcard_printf(vcards, ""); } static DBusMessage *generate_export_entries_reply(struct ofono_modem *modem, @@ -169,6 +269,50 @@ static DBusMessage *generate_export_entries_reply(struct ofono_modem *modem, return reply; } +static gboolean need_merge(const char *text) +{ + int len = strlen(text); + char c = text[len-1]; + if ((text[len-2] == '/') && + ((c == 'w') || (c == 'h') || (c == 'm') || (c == 'o'))) + return TRUE; + return FALSE; +} + +static void merge_field_generic(char **str1, const char *str2) +{ + if ((*str1 == NULL) && (str2 != NULL)) + *str1 = g_strdup(str2); +} + +static void merge_field_number(GSList **l, const char *number, int type, + char c, int prefer) +{ + struct phonebook_number *pn = g_new0(struct phonebook_number, 1); + int category; + + pn->number = g_strdup(number); + pn->type = type; + switch (c) { + case 'w': + case 'o': + category = TEL_TYPE_WORK; + break; + case 'h': + category = TEL_TYPE_HOME; + break; + case 'm': + category = TEL_TYPE_MOBILE; + break; + default: + category = TEL_TYPE_VOICE; + break; + } + pn->category = category; + pn->prefer = prefer; + *l = g_slist_append(*l, pn); +} + void ofono_phonebook_entry(struct ofono_modem *modem, int index, const char *number, int type, const char *text, int hidden, @@ -179,37 +323,54 @@ void ofono_phonebook_entry(struct ofono_modem *modem, int index, { struct phonebook_data *phonebook = modem->phonebook; char field[LEN_MAX]; - int len; - - vcard_printf(phonebook->vcards, "BEGIN:VCARD"); - vcard_printf(phonebook->vcards, "VERSION:3.0"); - - add_slash(field, text, LEN_MAX, strlen(text)); - - vcard_printf(phonebook->vcards, "FN:%s", field); - vcard_printf_number(phonebook->vcards, type, number, 1); - - if (group && (len = strlen(group))) { - add_slash(field, group, LEN_MAX, len); - vcard_printf(phonebook->vcards, "CATEGORIES:%s", field); - } - - if (adnumber && strlen(adnumber) && adtype != -1) - vcard_printf_number(phonebook->vcards, adtype, adnumber, 0); - - if (email && (len = strlen(email))) { - add_slash(field, email, LEN_MAX, len); - vcard_printf(phonebook->vcards, - "EMAIL;TYPE=INTERNET:%s", field); - } - - if (sip_uri && (len = strlen(sip_uri))) { - add_slash(field, sip_uri, LEN_MAX, len); - vcard_printf(phonebook->vcards, "IMPP;TYPE=SIP:%s", field); + /* + * We need to collect all the entries that belong to one person, + * so that only one vCard will be generated at last. + * Entries only differ with '/w', '/h', '/m', etc. in field text + * are deemed as entries of one person. + */ + if (need_merge(text)) { + GSList *l; + int has_merge = 0; + int len_text = strlen(text); + char *text_temp = g_strndup(text, len_text - 2); + struct phonebook_person *person; + for (l = phonebook->merge_list; l; l = l->next) { + person = l->data; + if (!strcmp(text_temp, person->text)) { + has_merge = 1; + break; + } + } + if (has_merge == 0) { + person = g_new0(struct phonebook_person, 1); + phonebook->merge_list = g_slist_append( + phonebook->merge_list, person); + } + merge_field_generic(&(person->text), text_temp); + merge_field_number(&(person->number_list), number, type, + text[len_text - 1], 1); + merge_field_number(&(person->number_list), adnumber, adtype, + text[len_text - 1], 0); + merge_field_generic(&(person->group), group); + merge_field_generic(&(person->secondtext), secondtext); + merge_field_generic(&(person->email), email); + merge_field_generic(&(person->sip_uri), sip_uri); + merge_field_generic(&(person->tel_uri), tel_uri); + g_free(text_temp); + return; } - vcard_printf(phonebook->vcards, "END:VCARD"); - vcard_printf(phonebook->vcards, ""); + vcard_printf_begin(phonebook->vcards); + vcard_printf_text(phonebook->vcards, text); + vcard_printf_number(phonebook->vcards, number, type, + TEL_TYPE_VOICE, 1); + vcard_printf_number(phonebook->vcards, adnumber, adtype, + TEL_TYPE_VOICE, 0); + vcard_printf_group(phonebook->vcards, group); + vcard_printf_email(phonebook->vcards, email); + vcard_printf_sip_uri(phonebook->vcards, sip_uri); + vcard_printf_end(phonebook->vcards); } static void export_phonebook_cb(const struct ofono_error *error, void *data) @@ -232,6 +393,7 @@ static void export_phonebook(struct ofono_modem *modem) struct phonebook_data *phonebook = modem->phonebook; DBusMessage *reply; const char *pb = storage_support[phonebook->storage_index]; + GSList *l, *m; if (pb) { phonebook->ops->export_entries(modem, pb, @@ -239,6 +401,22 @@ static void export_phonebook(struct ofono_modem *modem) return; } + /* convert the collected entries that are already merged to vcard */ + for (l = phonebook->merge_list; l; l = l->next) { + struct phonebook_person *person = l->data; + vcard_printf_begin(phonebook->vcards); + vcard_printf_text(phonebook->vcards, person->text); + for (m = person->number_list; m; m = m->next) { + struct phonebook_number *pn = m->data; + vcard_printf_number(phonebook->vcards, pn->number, + pn->type, pn->category, pn->prefer); + } + vcard_printf_group(phonebook->vcards, person->group); + vcard_printf_email(phonebook->vcards, person->email); + vcard_printf_sip_uri(phonebook->vcards, person->sip_uri); + vcard_printf_end(phonebook->vcards); + } + reply = generate_export_entries_reply(modem, phonebook->pending); if (!reply) {