/* we try to be as forgiving as we possibly can here - this isn't a * validator. Almost nothing is considered a fatal error. We always * try to return *something*. */ static void parse (EVCard *evc, const char *str) { char *buf ; char *p; EVCardAttribute *attr; buf = make_valid_utf8 (str); //buf = fold_lines (buf); d(printf ("BEFORE FOLDING:\n")); d(printf (str)); d(printf ("\n\nAFTER FOLDING:\n")); d(printf (buf)); p = buf; attr = read_attribute (&p); if (!attr || attr->group || g_ascii_strcasecmp (attr->name, "begin")) { g_warning ("vcard began without a BEGIN:VCARD\n"); } if (attr && !g_ascii_strcasecmp (attr->name, "begin")) { e_vcard_attribute_free (attr); attr = NULL; } else if (attr) e_vcard_add_attribute (evc, attr); while (*p) { EVCardAttribute *next_attr = read_attribute (&p); if (next_attr) { attr = next_attr; if (g_ascii_strcasecmp (next_attr->name, "end")) e_vcard_add_attribute (evc, next_attr); else break; } } if (!attr || attr->group || g_ascii_strcasecmp (attr->name, "end")) { g_warning ("vcard ended without END:VCARD\n"); } if (attr && !g_ascii_strcasecmp (attr->name, "end")) e_vcard_attribute_free (attr); g_free (buf); evc->priv->attributes = g_list_reverse (evc->priv->attributes); }
/** * e_vcard_remove_attributes: * @evc: vcard object * @attr_group: group name of attributes to be removed * @attr_name: name of the arributes to be removed * * Removes all the attributes with group name and attribute name equal to * passed in values. If @attr_group is %NULL or an empty string, * it removes all the attributes with passed in name irrespective of * their group names. **/ void e_vcard_remove_attributes (EVCard *evc, const char *attr_group, const char *attr_name) { GList *attr; g_return_if_fail (E_IS_VCARD (evc)); g_return_if_fail (attr_name != NULL); attr = evc->priv->attributes; while (attr) { GList *next_attr; EVCardAttribute *a = attr->data; next_attr = attr->next; if (((!attr_group || *attr_group == '\0') || (attr_group && !g_ascii_strcasecmp (attr_group, a->group))) && ((!attr_name && !a->name) || !g_ascii_strcasecmp (attr_name, a->name))) { /* matches, remove/delete the attribute */ evc->priv->attributes = g_list_delete_link (evc->priv->attributes, attr); e_vcard_attribute_free (a); } attr = next_attr; } }
/** * e_vcard_remove_attribute: * @evc: an #EVCard * @attr: an #EVCardAttribute to remove * * Removes @attr from @evc and frees it. **/ void e_vcard_remove_attribute (EVCard *evc, EVCardAttribute *attr) { g_return_if_fail (E_IS_VCARD (evc)); g_return_if_fail (attr != NULL); evc->priv->attributes = g_list_remove (evc->priv->attributes, attr); e_vcard_attribute_free (attr); }
/* utility functions shared between all contact importers */ static void preview_contact (EWebViewPreview *preview, EContact *contact) { gint idx; gboolean had_value = FALSE; const gint fields[] = { E_CONTACT_FILE_AS, E_CONTACT_CATEGORIES, E_CONTACT_IS_LIST, E_CONTACT_LIST_SHOW_ADDRESSES, E_CONTACT_WANTS_HTML, E_CONTACT_FULL_NAME, E_CONTACT_GIVEN_NAME, E_CONTACT_FAMILY_NAME, E_CONTACT_NICKNAME, E_CONTACT_SPOUSE, E_CONTACT_BIRTH_DATE, E_CONTACT_ANNIVERSARY, E_CONTACT_MAILER, E_CONTACT_EMAIL, -1, E_CONTACT_ORG, E_CONTACT_ORG_UNIT, E_CONTACT_OFFICE, E_CONTACT_TITLE, E_CONTACT_ROLE, E_CONTACT_MANAGER, E_CONTACT_ASSISTANT, -1, E_CONTACT_PHONE_ASSISTANT, E_CONTACT_PHONE_BUSINESS, E_CONTACT_PHONE_BUSINESS_2, E_CONTACT_PHONE_BUSINESS_FAX, E_CONTACT_PHONE_CALLBACK, E_CONTACT_PHONE_CAR, E_CONTACT_PHONE_COMPANY, E_CONTACT_PHONE_HOME, E_CONTACT_PHONE_HOME_2, E_CONTACT_PHONE_HOME_FAX, E_CONTACT_PHONE_ISDN, E_CONTACT_PHONE_MOBILE, E_CONTACT_PHONE_OTHER, E_CONTACT_PHONE_OTHER_FAX, E_CONTACT_PHONE_PAGER, E_CONTACT_PHONE_PRIMARY, E_CONTACT_PHONE_RADIO, E_CONTACT_PHONE_TELEX, E_CONTACT_PHONE_TTYTDD, -1, E_CONTACT_ADDRESS_HOME, E_CONTACT_ADDRESS_WORK, E_CONTACT_ADDRESS_OTHER, -1, E_CONTACT_HOMEPAGE_URL, E_CONTACT_BLOG_URL, E_CONTACT_CALENDAR_URI, E_CONTACT_FREEBUSY_URL, E_CONTACT_ICS_CALENDAR, E_CONTACT_VIDEO_URL, -1, E_CONTACT_IM_AIM, E_CONTACT_IM_GROUPWISE, E_CONTACT_IM_JABBER, E_CONTACT_IM_YAHOO, E_CONTACT_IM_MSN, E_CONTACT_IM_ICQ, E_CONTACT_IM_GADUGADU, E_CONTACT_IM_SKYPE, -1, E_CONTACT_NOTE }; g_return_if_fail (preview != NULL); g_return_if_fail (contact != NULL); for (idx = 0; idx < G_N_ELEMENTS (fields); idx++) { EContactField field; if (fields[idx] == -1) { if (had_value) e_web_view_preview_add_empty_line (preview); had_value = FALSE; continue; } field = fields[idx]; if (field == E_CONTACT_BIRTH_DATE || field == E_CONTACT_ANNIVERSARY) { EContactDate *dt = e_contact_get (contact, field); if (dt) { GDate gd = { 0 }; struct tm tm; gchar *value; g_date_set_dmy (&gd, dt->day, dt->month, dt->year); g_date_to_struct_tm (&gd, &tm); value = e_datetime_format_format_tm ( "addressbook", "table", DTFormatKindDate, &tm); if (value) { e_web_view_preview_add_section ( preview, e_contact_pretty_name (field), value); had_value = TRUE; } g_free (value); e_contact_date_free (dt); } } else if (field == E_CONTACT_IS_LIST || field == E_CONTACT_WANTS_HTML || field == E_CONTACT_LIST_SHOW_ADDRESSES) { if (e_contact_get (contact, field)) { e_web_view_preview_add_text ( preview, e_contact_pretty_name (field)); had_value = TRUE; } } else if (field == E_CONTACT_ADDRESS_HOME || field == E_CONTACT_ADDRESS_WORK || field == E_CONTACT_ADDRESS_OTHER) { EContactAddress *addr = e_contact_get (contact, field); if (addr) { gboolean have = FALSE; #define add_it(_what) \ if (addr->_what && *addr->_what) { \ e_web_view_preview_add_section ( \ preview, have ? NULL : \ e_contact_pretty_name (field), addr->_what); \ have = TRUE; \ had_value = TRUE; \ } add_it (po); add_it (ext); add_it (street); add_it (locality); add_it (region); add_it (code); add_it (country); #undef add_it e_contact_address_free (addr); } } else if (field == E_CONTACT_IM_AIM || field == E_CONTACT_IM_GROUPWISE || field == E_CONTACT_IM_JABBER || field == E_CONTACT_IM_YAHOO || field == E_CONTACT_IM_MSN || field == E_CONTACT_IM_ICQ || field == E_CONTACT_IM_GADUGADU || field == E_CONTACT_IM_SKYPE || field == E_CONTACT_EMAIL) { GList *attrs, *a; gboolean have = FALSE; const gchar *pretty_name; pretty_name = e_contact_pretty_name (field); attrs = e_contact_get_attributes (contact, field); for (a = attrs; a; a = a->next) { EVCardAttribute *attr = a->data; GList *value; if (!attr) continue; value = e_vcard_attribute_get_values (attr); while (value != NULL) { const gchar *str = value->data; if (str && *str) { e_web_view_preview_add_section ( preview, have ? NULL : pretty_name, str); have = TRUE; had_value = TRUE; } value = value->next; } e_vcard_attribute_free (attr); } g_list_free (attrs); } else if (field == E_CONTACT_CATEGORIES) { const gchar *pretty_name; const gchar *value; pretty_name = e_contact_pretty_name (field); value = e_contact_get_const (contact, field); if (value != NULL && *value != '\0') { e_web_view_preview_add_section ( preview, pretty_name, value); had_value = TRUE; } } else { const gchar *pretty_name; const gchar *value; pretty_name = e_contact_pretty_name (field); value = e_contact_get_const (contact, field); if (value != NULL && *value != '\0') { e_web_view_preview_add_section ( preview, pretty_name, value); had_value = TRUE; } } } }
/* reads an entire attribute from the input buffer, leaving p pointing at the start of the next line (past the \r\n) */ static EVCardAttribute* read_attribute (char **p) { char *attr_group = NULL; char *attr_name = NULL; EVCardAttribute *attr = NULL; GString *str; char *lp; gboolean is_qp = FALSE; /* first read in the group/name */ str = g_string_new (""); for( lp = skip_newline( *p, is_qp ); *lp != '\n' && *lp != '\r' && *lp != '\0'; lp = skip_newline( lp, is_qp ) ) { if (*lp == ':' || *lp == ';') { if (str->len != 0) { /* we've got a name, break out to the value/attribute parsing */ attr_name = g_string_free (str, FALSE); break; } else { /* a line of the form: * (group.)?[:;] * * since we don't have an attribute * name, skip to the end of the line * and try again. */ g_string_free (str, TRUE); *p = lp; skip_to_next_line(p); goto lose; } } else if (*lp == '.') { if (attr_group) { g_warning ("extra `.' in attribute specification. ignoring extra group `%s'", str->str); g_string_free (str, TRUE); str = g_string_new (""); } if (str->len != 0) { attr_group = g_string_free (str, FALSE); str = g_string_new (""); } } else if (g_unichar_isalnum (g_utf8_get_char (lp)) || *lp == '-' || *lp == '_') { g_string_append_unichar (str, g_utf8_get_char (lp)); } else { g_warning ("invalid character found in attribute group/name"); g_string_free (str, TRUE); *p = lp; skip_to_next_line(p); goto lose; } lp = g_utf8_next_char(lp); } if (!attr_name) { skip_to_next_line (p); goto lose; } attr = e_vcard_attribute_new (attr_group, attr_name); g_free (attr_group); g_free (attr_name); if (*lp == ';') { /* skip past the ';' */ lp = g_utf8_next_char(lp); read_attribute_params (attr, &lp, &is_qp); if (is_qp) attr->encoding = EVC_ENCODING_RAW; } if (*lp == ':') { /* skip past the ':' */ lp = g_utf8_next_char(lp); read_attribute_value (attr, &lp, is_qp); } *p = lp; if (!attr->values) goto lose; return attr; lose: if (attr) e_vcard_attribute_free (attr); return NULL; }