~ubuntu-branches/ubuntu/precise/evolution-data-server/precise-proposed

« back to all changes in this revision

Viewing changes to addressbook/backends/google/e-book-backend-google.c

  • Committer: Package Import Robot
  • Author(s): Mathieu Trudel-Lapierre
  • Date: 2011-09-19 12:15:29 UTC
  • mfrom: (1.1.93 upstream)
  • Revision ID: package-import@ubuntu.com-20110919121529-nsmfnges77ec7hux
Tags: 3.1.92-0ubuntu1
* New upstream release.
  - Cannot add more than one appointment per session (LP: #852277)
  - Contacts calendar backend doesn't show events (LP: #853905)
  - Set X-Evolution-Source header consistently (LP: #660626)

Show diffs side-by-side

added added

removed removed

Lines of Context:
46
46
#define URI_GET_CONTACTS "://www.google.com/m8/feeds/contacts/default/full"
47
47
#define GDATA_PHOTO_ETAG_ATTR "X-GDATA-PHOTO-ETAG"
48
48
 
 
49
/* Definitions for our custom X-URIS vCard attribute for storing URIs.
 
50
 * See: bgo#659079. It would be nice to move this into EVCard sometime. */
 
51
#define GDATA_URIS_ATTR "X-URIS"
 
52
#define GDATA_URIS_TYPE_HOME_PAGE "X-HOME-PAGE"
 
53
#define GDATA_URIS_TYPE_BLOG "X-BLOG"
 
54
#define GDATA_URIS_TYPE_PROFILE "X-PROFILE"
 
55
#define GDATA_URIS_TYPE_FTP "X-FTP"
 
56
 
49
57
#define EDB_ERROR(_code) e_data_book_create_error (E_DATA_BOOK_STATUS_ ## _code, NULL)
50
58
#define EDB_ERROR_EX(_code, _msg) e_data_book_create_error (E_DATA_BOOK_STATUS_ ## _code, _msg)
51
59
 
112
120
static const gchar *_e_contact_get_gdata_entry_xml (EContact *contact, const gchar **edit_uri);
113
121
 
114
122
static void
 
123
migrate_cache (EBookBackendCache *cache)
 
124
{
 
125
        const gchar *version;
 
126
        const gchar *version_key = "book-cache-version";
 
127
 
 
128
        g_return_if_fail (cache != NULL);
 
129
 
 
130
        version = e_file_cache_get_object (E_FILE_CACHE (cache), version_key);
 
131
        if (!version || atoi (version) < 1) {
 
132
                /* not versioned yet, dump the cache and reload it from a server */
 
133
                e_file_cache_clean (E_FILE_CACHE (cache));
 
134
                e_file_cache_add_object (E_FILE_CACHE (cache), version_key, "1");
 
135
        }
 
136
}
 
137
 
 
138
static void
115
139
cache_init (EBookBackend *backend,
116
140
            gboolean on_disk)
117
141
{
127
151
                priv->cache_type = ON_DISK_CACHE;
128
152
                priv->cache.on_disk = e_book_backend_cache_new (filename);
129
153
                g_free (filename);
 
154
 
 
155
                migrate_cache (priv->cache.on_disk);
130
156
        } else {
131
157
                priv->cache_type = IN_MEMORY_CACHE;
132
158
                priv->cache.in_memory.contacts = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
1665
1691
         * we can update the EContact with the photo data and ETag. */
1666
1692
        switch (data->photo_operation) {
1667
1693
                case LEAVE_PHOTO:
1668
 
                        /* Do nothing. */
 
1694
                        /* Do nothing apart from copy the photo stolen from the old GDataContactsContact to the updated one we've just received from
 
1695
                         * Google. */
 
1696
                        g_object_set_data_full (G_OBJECT (new_contact), "photo", data->photo, (GDestroyNotify) e_contact_photo_free);
 
1697
                        data->photo = NULL;
1669
1698
                        break;
1670
1699
                case ADD_PHOTO:
1671
1700
                case UPDATE_PHOTO:
2224
2253
#endif
2225
2254
        }
2226
2255
 
2227
 
        if (!priv->is_online || backend_is_authorized (backend))
 
2256
        if (!priv->is_online || backend_is_authorized (backend)) {
 
2257
                e_book_backend_notify_readonly (backend, FALSE);
2228
2258
                e_book_backend_notify_opened (backend, NULL /* Success */);
 
2259
        }
2229
2260
 
2230
2261
        e_data_book_respond_open (book, opid, NULL /* Success */);
2231
2262
}
2642
2673
static void add_attribute_from_gdata_gd_phone_number (EVCard *vcard, GDataGDPhoneNumber *number);
2643
2674
static void add_attribute_from_gdata_gd_postal_address (EVCard *vcard, GDataGDPostalAddress *address);
2644
2675
static void add_attribute_from_gdata_gd_organization (EVCard *vcard, GDataGDOrganization *org);
 
2676
static void add_attribute_from_gc_contact_website (EVCard *vcard, GDataGContactWebsite *website);
2645
2677
 
2646
2678
static GDataGDEmailAddress *gdata_gd_email_address_from_attribute (EVCardAttribute *attr, gboolean *primary);
2647
2679
static GDataGDIMAddress *gdata_gd_im_address_from_attribute (EVCardAttribute *attr, gboolean *primary);
2648
2680
static GDataGDPhoneNumber *gdata_gd_phone_number_from_attribute (EVCardAttribute *attr, gboolean *primary);
2649
2681
static GDataGDPostalAddress *gdata_gd_postal_address_from_attribute (EVCardAttribute *attr, gboolean *primary);
2650
2682
static GDataGDOrganization *gdata_gd_organization_from_attribute (EVCardAttribute *attr, gboolean *primary);
 
2683
static GDataGContactWebsite *gdata_gc_contact_website_from_attribute (EVCardAttribute *attr, gboolean *primary);
2651
2684
 
2652
2685
static gboolean is_known_google_im_protocol (const gchar *protocol);
2653
2686
 
2689
2722
        g_list_free (events);
2690
2723
}
2691
2724
 
2692
 
static void
2693
 
remove_websites (GDataContactsContact *contact)
2694
 
{
2695
 
        GList *websites, *itr;
2696
 
 
2697
 
        websites = gdata_contacts_contact_get_websites (contact);
2698
 
        if (!websites)
2699
 
                return;
2700
 
 
2701
 
        websites = g_list_copy (websites);
2702
 
        g_list_foreach (websites, (GFunc) g_object_ref, NULL);
2703
 
 
2704
 
        gdata_contacts_contact_remove_all_websites (contact);
2705
 
        for (itr = websites; itr; itr = itr->next) {
2706
 
                GDataGContactWebsite *website = itr->data;
2707
 
 
2708
 
                if (g_strcmp0 (gdata_gcontact_website_get_relation_type (website), GDATA_GCONTACT_WEBSITE_HOME_PAGE) != 0 &&
2709
 
                    g_strcmp0 (gdata_gcontact_website_get_relation_type (website), GDATA_GCONTACT_WEBSITE_BLOG) != 0)
2710
 
                        gdata_contacts_contact_add_website (contact, website);
2711
 
        }
2712
 
 
2713
 
        g_list_foreach (websites, (GFunc) g_object_unref, NULL);
2714
 
        g_list_free (websites);
2715
 
}
2716
 
 
2717
2725
static gboolean
2718
2726
_gdata_entry_update_from_e_contact (EBookBackend *backend,
2719
2727
                                    GDataEntry *entry,
2730
2738
        gboolean have_phone_primary = FALSE;
2731
2739
        gboolean have_postal_primary = FALSE;
2732
2740
        gboolean have_org_primary = FALSE;
 
2741
        gboolean have_uri_primary = FALSE;
2733
2742
        const gchar *title, *role, *note;
2734
2743
        EContactDate *bdate;
2735
2744
        const gchar *url;
2773
2782
        gdata_contacts_contact_remove_all_postal_addresses (GDATA_CONTACTS_CONTACT (entry));
2774
2783
        gdata_contacts_contact_remove_all_im_addresses (GDATA_CONTACTS_CONTACT (entry));
2775
2784
        gdata_contacts_contact_remove_all_organizations (GDATA_CONTACTS_CONTACT (entry));
 
2785
        gdata_contacts_contact_remove_all_websites (GDATA_CONTACTS_CONTACT (entry));
2776
2786
 
2777
2787
        category_names = gdata_contacts_contact_get_groups (GDATA_CONTACTS_CONTACT (entry));
2778
2788
        for (iter = category_names; iter != NULL; iter = g_list_delete_link (iter, iter))
2845
2855
                                gdata_contacts_contact_add_im_address (GDATA_CONTACTS_CONTACT (entry), im);
2846
2856
                                g_object_unref (im);
2847
2857
                        }
 
2858
                } else if (0 == g_ascii_strcasecmp (name, GDATA_URIS_ATTR)) {
 
2859
                        /* X-URIS */
 
2860
                        GDataGContactWebsite *website;
 
2861
 
 
2862
                        website =gdata_gc_contact_website_from_attribute (attr, &have_uri_primary);
 
2863
                        if (website) {
 
2864
                                gdata_contacts_contact_add_website (GDATA_CONTACTS_CONTACT (entry), website);
 
2865
                                g_object_unref (website);
 
2866
                        }
2848
2867
                } else if (e_vcard_attribute_is_single_valued (attr)) {
2849
2868
                        gchar *value;
2850
2869
 
2884
2903
                        gdata_gd_organization_set_job_description (org, role);
2885
2904
        }
2886
2905
 
2887
 
        remove_websites (GDATA_CONTACTS_CONTACT (entry));
2888
 
 
2889
2906
        url = e_contact_get_const (contact, E_CONTACT_HOMEPAGE_URL);
2890
2907
        if (url && *url) {
2891
2908
                GDataGContactWebsite *website = gdata_gcontact_website_new (url, GDATA_GCONTACT_WEBSITE_HOME_PAGE, NULL, FALSE);
3011
3028
        GList *websites, *events;
3012
3029
        GDate bdate;
3013
3030
        gboolean bdate_has_year;
 
3031
        gboolean have_uri_home = FALSE, have_uri_blog = FALSE;
3014
3032
 
3015
3033
        uid = gdata_entry_get_id (entry);
3016
3034
        if (NULL == uid)
3153
3171
                if (!uri || !*uri || !reltype)
3154
3172
                        continue;
3155
3173
 
3156
 
                if (g_str_equal (reltype, GDATA_GCONTACT_WEBSITE_HOME_PAGE))
 
3174
                if (!have_uri_home && g_str_equal (reltype, GDATA_GCONTACT_WEBSITE_HOME_PAGE)) {
3157
3175
                        e_contact_set (E_CONTACT (vcard), E_CONTACT_HOMEPAGE_URL, uri);
3158
 
                else if (g_str_equal (reltype, GDATA_GCONTACT_WEBSITE_BLOG))
 
3176
                        have_uri_home = TRUE;
 
3177
                } else if (!have_uri_blog && g_str_equal (reltype, GDATA_GCONTACT_WEBSITE_BLOG)) {
3159
3178
                        e_contact_set (E_CONTACT (vcard), E_CONTACT_BLOG_URL, uri);
 
3179
                        have_uri_blog = TRUE;
 
3180
                } else {
 
3181
                        add_attribute_from_gc_contact_website (vcard, website);
 
3182
                }
3160
3183
        }
3161
3184
 
3162
3185
        g_date_clear (&bdate, 1);
3326
3349
        { "work", { "WORK", NULL }},
3327
3350
};
3328
3351
 
 
3352
static const struct RelTypeMap rel_type_map_uris[] = {
 
3353
        { GDATA_GCONTACT_WEBSITE_HOME_PAGE, { GDATA_URIS_TYPE_HOME_PAGE, NULL }},
 
3354
        { GDATA_GCONTACT_WEBSITE_BLOG, { GDATA_URIS_TYPE_BLOG, NULL }},
 
3355
        { GDATA_GCONTACT_WEBSITE_PROFILE, { GDATA_URIS_TYPE_PROFILE, NULL }},
 
3356
        { GDATA_GCONTACT_WEBSITE_FTP, { GDATA_URIS_TYPE_FTP, NULL }},
 
3357
        { GDATA_GCONTACT_WEBSITE_HOME, { "HOME", NULL }},
 
3358
        { GDATA_GCONTACT_WEBSITE_OTHER, { "OTHER", NULL }},
 
3359
        { GDATA_GCONTACT_WEBSITE_WORK, { "WORK", NULL }},
 
3360
};
 
3361
 
3329
3362
static const struct RelTypeMap rel_type_map_others[] = {
3330
3363
        { "home", { "HOME", NULL }},
3331
3364
        { "other", { "OTHER", NULL }},
3377
3410
}
3378
3411
 
3379
3412
static gboolean
 
3413
add_type_param_from_google_rel_uris (EVCardAttribute *attr,
 
3414
                                     const gchar *rel)
 
3415
{
 
3416
        return _add_type_param_from_google_rel (attr, rel_type_map_uris, G_N_ELEMENTS (rel_type_map_uris), rel);
 
3417
}
 
3418
 
 
3419
static gboolean
3380
3420
add_type_param_from_google_rel (EVCardAttribute *attr,
3381
3421
                                const gchar *rel)
3382
3422
{
3397
3437
static gchar *
3398
3438
_google_rel_from_types (GList *types,
3399
3439
                        const struct RelTypeMap rel_type_map[],
3400
 
                        guint map_len)
 
3440
                        guint map_len,
 
3441
                        gboolean use_prefix)
3401
3442
{
3402
 
        const gchar format[] = "http://schemas.google.com/g/2005#%s";
 
3443
        const gchar *format = "http://schemas.google.com/g/2005#%s";
3403
3444
        guint i;
 
3445
        if (!use_prefix)
 
3446
                format = "%s";
3404
3447
 
3405
3448
        /* For each of the entries in the map... */
3406
3449
        for (i = 0; i < map_len; i++) {
3427
3470
static gchar *
3428
3471
google_rel_from_types (GList *types)
3429
3472
{
3430
 
        return _google_rel_from_types (types, rel_type_map_others, G_N_ELEMENTS (rel_type_map_others));
 
3473
        return _google_rel_from_types (types, rel_type_map_others, G_N_ELEMENTS (rel_type_map_others), TRUE);
3431
3474
}
3432
3475
 
3433
3476
static gchar *
3434
3477
google_rel_from_types_phone (GList *types)
3435
3478
{
3436
 
        return _google_rel_from_types (types, rel_type_map_phone, G_N_ELEMENTS (rel_type_map_phone));
 
3479
        return _google_rel_from_types (types, rel_type_map_phone, G_N_ELEMENTS (rel_type_map_phone), TRUE);
 
3480
}
 
3481
 
 
3482
static gchar *
 
3483
google_rel_from_types_uris (GList *types)
 
3484
{
 
3485
        return _google_rel_from_types (types, rel_type_map_uris, G_N_ELEMENTS (rel_type_map_uris), FALSE);
3437
3486
}
3438
3487
 
3439
3488
static gboolean
3686
3735
                e_vcard_add_attribute (vcard, attr);
3687
3736
}
3688
3737
 
 
3738
static void
 
3739
add_attribute_from_gc_contact_website (EVCard *vcard,
 
3740
                                       GDataGContactWebsite *website)
 
3741
{
 
3742
        EVCardAttribute *attr;
 
3743
        gboolean has_type;
 
3744
 
 
3745
        if (!website || !gdata_gcontact_website_get_uri (website))
 
3746
                return;
 
3747
 
 
3748
        attr = e_vcard_attribute_new (NULL, GDATA_URIS_ATTR);
 
3749
        has_type = add_type_param_from_google_rel_uris (attr, gdata_gcontact_website_get_relation_type (website));
 
3750
        if (gdata_gcontact_website_is_primary (website))
 
3751
                add_primary_param (attr, has_type);
 
3752
        add_label_param (attr, gdata_gcontact_website_get_label (website));
 
3753
 
 
3754
        e_vcard_attribute_add_value (attr, gdata_gcontact_website_get_uri (website));
 
3755
 
 
3756
        e_vcard_add_attribute (vcard, attr);
 
3757
}
3689
3758
static GDataGDEmailAddress *
3690
3759
gdata_gd_email_address_from_attribute (EVCardAttribute *attr,
3691
3760
                                       gboolean *have_primary)
3902
3971
 
3903
3972
        return org;
3904
3973
}
 
3974
 
 
3975
static GDataGContactWebsite *
 
3976
gdata_gc_contact_website_from_attribute (EVCardAttribute *attr,
 
3977
                                         gboolean *have_primary)
 
3978
{
 
3979
        GDataGContactWebsite *website = NULL;
 
3980
        GList *values;
 
3981
 
 
3982
        values = e_vcard_attribute_get_values (attr);
 
3983
        if (values) {
 
3984
                GList *types;
 
3985
                gchar *rel;
 
3986
                const gchar *label;
 
3987
                gboolean primary;
 
3988
 
 
3989
                types = get_google_primary_type_label (attr, &primary, &label);
 
3990
                if (!*have_primary)
 
3991
                        *have_primary = primary;
 
3992
                else
 
3993
                        primary = FALSE;
 
3994
 
 
3995
                rel = google_rel_from_types_uris (types);
 
3996
                website = gdata_gcontact_website_new (values->data, rel, label, primary);
 
3997
                g_free (rel);
 
3998
 
 
3999
                __debug__ ("New %suri entry %s (%s/%s)",
 
4000
                           gdata_gcontact_website_is_primary (website) ? "primary " : "",
 
4001
                           gdata_gcontact_website_get_uri (website),
 
4002
                           gdata_gcontact_website_get_relation_type (website),
 
4003
                           gdata_gcontact_website_get_label (website));
 
4004
        }
 
4005
 
 
4006
        return website;
 
4007
}