1 /** Google Calendar plugin
3 * Copyright (c) 2006 Eduardo Pereira Habkost <ehabkost@raisama.net>
4 * Copyright (c) 2008 Adenilson Cavalcanti da Silva <adenilson.silva@indt.org.br>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Lesser Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
24 * - find a way to report changes to opensync and make it work
25 * - review code for leaks (I'm not sure if I'm using opensync API correctly...)
29 #define _XOPEN_SOURCE /* man page say: glibc2 needs this */
33 #include <opensync/opensync.h>
34 #include <opensync/opensync-plugin.h>
35 #include <opensync/opensync-helper.h>
36 #include <opensync/opensync-merger.h>
37 #include <opensync/opensync-format.h>
38 #include <opensync/opensync-data.h>
39 #include <opensync/opensync-version.h>
43 #include <libxml/tree.h>
48 #include <sys/types.h>
51 #include <gcal_status.h>
52 #include <gcalendar.h>
57 static int timestamp_cmp(char *timestamp1
, char *timestamp2
)
59 /* timestamp (RFC3339) formating string */
60 char format
[] = "%FT%T";
61 struct tm first
, second
;
62 time_t t_first
, t_second
;
65 if (!timestamp1
|| !timestamp2
)
68 /* From timestamp string to time structure */
69 strptime(timestamp1
, format
, &first
);
70 strptime(timestamp2
, format
, &second
);
72 /* From time structure to calendar time (since
73 * Epoch (00:00:00 UTC, January 1, 1970)
75 t_first
= mktime(&first
);
76 t_second
= mktime(&second
);
78 if (t_first
== t_second
)
80 else if (t_first
> t_second
)
82 else if (t_first
< t_second
)
94 char *gcal_anchor_path
;
95 char *gcont_anchor_path
;
98 /* libgcal resources */
100 char *cont_timestamp
;
103 struct gcal_event_array all_events
;
104 struct gcal_contact_array all_contacts
;
105 /* calendar sink/format */
106 OSyncObjTypeSink
*gcal_sink
;
107 OSyncObjFormat
*gcal_format
;
108 /* contact sink/format */
109 OSyncObjTypeSink
*gcont_sink
;
110 OSyncObjFormat
*gcont_format
;
111 /* XSLT context resource struct */
112 struct xslt_resources
*xslt_ctx_gcal
;
113 struct xslt_resources
*xslt_ctx_gcont
;
116 static void free_plg(struct gc_plgdata
*plgdata
)
118 if (plgdata
->calendar
) {
119 gcal_delete(plgdata
->calendar
);
120 gcal_cleanup_events(&(plgdata
->all_events
));
122 if (plgdata
->contacts
) {
123 gcal_delete(plgdata
->contacts
);
124 gcal_cleanup_contacts(&(plgdata
->all_contacts
));
127 if (plgdata
->gcal_anchor_path
)
128 g_free(plgdata
->gcal_anchor_path
);
129 if (plgdata
->gcont_anchor_path
)
130 g_free(plgdata
->gcont_anchor_path
);
131 if (plgdata
->xslt_path
)
132 free(plgdata
->xslt_path
);
133 if (plgdata
->xslt_ctx_gcal
)
134 xslt_delete(plgdata
->xslt_ctx_gcal
);
135 if (plgdata
->xslt_ctx_gcont
)
136 xslt_delete(plgdata
->xslt_ctx_gcont
);
137 if (plgdata
->cal_timestamp
)
138 free(plgdata
->cal_timestamp
);
139 if (plgdata
->cont_timestamp
)
140 free(plgdata
->cont_timestamp
);
141 if (plgdata
->timezone
)
142 free(plgdata
->timezone
);
144 xmlFree(plgdata
->url
);
145 if (plgdata
->username
)
146 xmlFree(plgdata
->username
);
147 if (plgdata
->password
)
148 xmlFree(plgdata
->password
);
149 if (plgdata
->gcal_sink
)
150 osync_objtype_sink_unref(plgdata
->gcal_sink
);
151 if (plgdata
->gcal_format
)
152 osync_objformat_unref(plgdata
->gcal_format
);
156 static void gc_connect(void *data
, OSyncPluginInfo
*info
, OSyncContext
*ctx
)
158 osync_trace(TRACE_ENTRY
, "%s(%p, %p, %p)", __func__
, data
, info
, ctx
);
159 static int counter
= 0;
161 struct gc_plgdata
*plgdata
= data
;
162 OSyncObjTypeSink
*sink
= osync_plugin_info_get_sink(info
);
163 OSyncError
*error
= NULL
;
166 if ((plgdata
->calendar
) && (counter
== 0)) {
167 result
= gcal_get_authentication(plgdata
->calendar
, plgdata
->username
,
173 snprintf(buffer
, sizeof(buffer
) - 1, "%s/gcal2osync.xslt",
175 if ((result
= xslt_initialize(plgdata
->xslt_ctx_gcal
, buffer
)))
177 osync_trace(TRACE_INTERNAL
, "\ndone calendar: %s\n", buffer
);
180 if (((plgdata
->contacts
) && (counter
== 1)) ||
181 ((plgdata
->gcont_sink
) && (!plgdata
->gcal_sink
))) {
182 result
= gcal_get_authentication(plgdata
->contacts
, plgdata
->username
,
188 snprintf(buffer
, sizeof(buffer
) - 1, "%s/gcont2osync.xslt",
190 if ((result
= xslt_initialize(plgdata
->xslt_ctx_gcont
, buffer
)))
192 osync_trace(TRACE_INTERNAL
, "\ndone contact: %s\n", buffer
);
195 osync_context_report_success(ctx
);
196 osync_trace(TRACE_EXIT
, "%s", __func__
);
200 osync_trace(TRACE_INTERNAL
, "\nGood bye, cruel world...\n");
201 osync_context_report_osyncerror(ctx
, &error
);
204 static void gc_get_changes_calendar(void *data
, OSyncPluginInfo
*info
, OSyncContext
*ctx
)
206 osync_trace(TRACE_ENTRY
, "%s(%p, %p, %p)", __func__
, data
, info
, ctx
);
208 static int counter
= 0;
209 struct gc_plgdata
*plgdata
= data
;
210 char slow_sync_flag
= 0;
211 OSyncObjTypeSink
*sink
= osync_plugin_info_get_sink(info
);
212 OSyncError
*error
= NULL
;
213 OSyncXMLFormat
*xmlformat
;
214 OSyncData
*odata
= NULL
;
215 OSyncChange
*chg
= NULL
;
217 char *timestamp
= NULL
, *msg
, *raw_xml
= NULL
;
220 if (!plgdata
->gcal_sink
)
222 timestamp
= osync_anchor_retrieve(plgdata
->gcal_anchor_path
, "gcalendar");
224 osync_trace(TRACE_INTERNAL
, "timestamp is: %s\n", timestamp
);
226 osync_trace(TRACE_INTERNAL
, "first sync!\n");
228 if (osync_objtype_sink_get_slowsync(plgdata
->gcal_sink
)) {
229 osync_trace(TRACE_INTERNAL
, "\n\t\tgcal: Client asked for slow syncing...\n");
231 result
= gcal_get_events(plgdata
->calendar
, &(plgdata
->all_events
));
234 osync_trace(TRACE_INTERNAL
, "\n\t\tgcal: Client asked for fast syncing...\n");
235 result
= gcal_get_updated_events(plgdata
->calendar
,
236 &(plgdata
->all_events
),
241 msg
= "Failed getting events!";
245 osync_trace(TRACE_INTERNAL
, "gcalendar: got then all!\n");
246 if (plgdata
->all_events
.length
== 0) {
247 osync_trace(TRACE_INTERNAL
, "gcalendar: no changes...\n");
250 osync_trace(TRACE_INTERNAL
, "gcalendar: changes count: %d\n",
251 plgdata
->all_events
.length
);
254 /* Calendar returns most recently updated event as first element */
255 event
= gcal_event_element(&(plgdata
->all_events
), 0);
257 msg
= "Cannot access last updated event!\n";
260 plgdata
->cont_timestamp
= strdup(gcal_event_get_updated(event
));
261 if (!plgdata
->cont_timestamp
) {
262 msg
= "Failed copying event timestamp!\n";
266 for (i
= 0; i
< plgdata
->all_events
.length
; ++i
) {
267 event
= gcal_event_element(&(plgdata
->all_events
), i
);
271 osync_trace(TRACE_INTERNAL
, "gevent: timestamp:%s\tevent:%s\n",
272 timestamp
, gcal_event_get_updated(event
));
273 /* Workaround for inclusive returned results */
274 if ((timestamp_cmp(timestamp
, gcal_event_get_updated(event
)) == 0)
276 && !gcal_event_is_deleted(event
)) {
277 osync_trace(TRACE_INTERNAL
, "gevent: old event.");
280 osync_trace(TRACE_INTERNAL
, "gevent: new or deleted event!");
282 raw_xml
= gcal_event_get_xml(event
);
283 if ((result
= xslt_transform(plgdata
->xslt_ctx_gcal
,
287 raw_xml
= plgdata
->xslt_ctx_gcal
->xml_str
;
288 xmlformat
= osync_xmlformat_parse(raw_xml
,
294 osync_trace(TRACE_INTERNAL
, "gevent: %s\nosync: %s\n",
295 gcal_event_get_xml(event
), raw_xml
);
297 osync_xmlformat_sort(xmlformat
);
298 odata
= osync_data_new(xmlformat
,
299 osync_xmlformat_size(),
300 plgdata
->gcal_format
, &error
);
304 if (!(chg
= osync_change_new(&error
)))
306 osync_data_set_objtype(odata
, osync_objtype_sink_get_name(plgdata
->gcal_sink
));
307 osync_change_set_data(chg
, odata
);
308 osync_data_unref(odata
);
310 osync_change_set_uid(chg
, gcal_event_get_url(event
));
313 osync_change_set_changetype(chg
, OSYNC_CHANGE_TYPE_ADDED
);
315 if (gcal_event_is_deleted(event
)) {
316 osync_change_set_changetype(chg
, OSYNC_CHANGE_TYPE_DELETED
);
317 osync_trace(TRACE_INTERNAL
, "deleted entry!");
320 osync_change_set_changetype(chg
, OSYNC_CHANGE_TYPE_MODIFIED
);
322 osync_context_report_change(ctx
, chg
);
323 osync_change_unref(chg
);
328 /* Load XSLT style to convert osync xmlformat-event --> gdata */
329 snprintf(buffer
, sizeof(buffer
) - 1, "%s/osync2gcal.xslt",
331 if ((result
= xslt_initialize(plgdata
->xslt_ctx_gcal
, buffer
))) {
332 msg
= "Cannot initialize new XSLT!\n";
336 osync_trace(TRACE_INTERNAL
, "\ndone calendar: %s\n", buffer
);
339 osync_context_report_success(ctx
);
343 osync_error_unref(&error
);
344 osync_xmlformat_unref(&xmlformat
);
347 osync_context_report_error(ctx
, OSYNC_ERROR_GENERIC
, msg
);
352 static void gc_get_changes_contact(void *data
, OSyncPluginInfo
*info
, OSyncContext
*ctx
)
354 osync_trace(TRACE_ENTRY
, "%s(%p, %p, %p)", __func__
, data
, info
, ctx
);
356 static int counter
= 0;
357 struct gc_plgdata
*plgdata
= data
;
358 char slow_sync_flag
= 0;
359 OSyncObjTypeSink
*sink
= osync_plugin_info_get_sink(info
);
360 OSyncError
*error
= NULL
;
361 OSyncXMLFormat
*xmlformat
;
362 OSyncData
*odata
= NULL
;
363 OSyncChange
*chg
= NULL
;
365 char *timestamp
= NULL
, *msg
, *raw_xml
= NULL
;
366 gcal_contact contact
;
369 if (!plgdata
->gcont_sink
)
371 timestamp
= osync_anchor_retrieve(plgdata
->gcont_anchor_path
, "gcontact");
373 osync_trace(TRACE_INTERNAL
, "timestamp is: %s\n", timestamp
);
375 osync_trace(TRACE_INTERNAL
, "first sync!\n");
377 if (osync_objtype_sink_get_slowsync(plgdata
->gcont_sink
)) {
378 osync_trace(TRACE_INTERNAL
, "\n\t\tgcont: Client asked for slow syncing...\n");
380 result
= gcal_get_contacts(plgdata
->contacts
, &(plgdata
->all_contacts
));
383 osync_trace(TRACE_INTERNAL
, "\n\t\tgcont: Client asked for fast syncing...\n");
384 gcal_deleted(plgdata
->contacts
, SHOW
);
385 result
= gcal_get_updated_contacts(plgdata
->contacts
,
386 &(plgdata
->all_contacts
),
391 msg
= "Failed getting contacts!";
395 osync_trace(TRACE_INTERNAL
, "gcontact: got then all!\n");
396 if (plgdata
->all_contacts
.length
== 0) {
397 osync_trace(TRACE_INTERNAL
, "gcontact: no changes...\n");
400 osync_trace(TRACE_INTERNAL
, "gcontact: changes count: %d\n",
401 plgdata
->all_contacts
.length
);
403 /* Contacts returns most recently updated entry as last element */
404 contact
= gcal_contact_element(&(plgdata
->all_contacts
),
405 (plgdata
->all_contacts
.length
- 1));
407 msg
= "Cannot access last updated contact!\n";
410 plgdata
->cont_timestamp
= strdup(gcal_contact_get_updated(contact
));
411 if (!plgdata
->cont_timestamp
) {
412 msg
= "Failed copying contact timestamp!\n";
416 for (i
= 0; i
< plgdata
->all_contacts
.length
; ++i
) {
417 contact
= gcal_contact_element(&(plgdata
->all_contacts
), i
);
421 osync_trace(TRACE_INTERNAL
, "gcontact: timestamp:%s\tcontact:%s\n",
422 timestamp
, gcal_contact_get_updated(contact
));
423 /* Workaround for inclusive returned results */
424 if ((timestamp_cmp(timestamp
, gcal_contact_get_updated(contact
)) == 0)
426 && !gcal_contact_is_deleted(contact
)) {
427 osync_trace(TRACE_INTERNAL
, "gcontact: old contact.");
430 osync_trace(TRACE_INTERNAL
, "gcontact: new or deleted contact!");
432 raw_xml
= gcal_contact_get_xml(contact
);
433 if ((result
= xslt_transform(plgdata
->xslt_ctx_gcont
,
436 raw_xml
= plgdata
->xslt_ctx_gcont
->xml_str
;
437 xmlformat
= osync_xmlformat_parse(raw_xml
,
443 osync_trace(TRACE_INTERNAL
, "gcont: %s\nosync: %s\n",
444 gcal_contact_get_xml(contact
), raw_xml
);
446 osync_xmlformat_sort(xmlformat
);
448 odata
= osync_data_new(xmlformat
,
449 osync_xmlformat_size(),
450 plgdata
->gcont_format
, &error
);
455 if (!(chg
= osync_change_new(&error
)))
457 osync_data_set_objtype(odata
, osync_objtype_sink_get_name(plgdata
->gcont_sink
));
458 osync_change_set_data(chg
, odata
);
459 osync_data_unref(odata
);
461 osync_change_set_uid(chg
, gcal_contact_get_url(contact
));
464 osync_change_set_changetype(chg
, OSYNC_CHANGE_TYPE_ADDED
);
466 if (gcal_contact_is_deleted(contact
)) {
467 osync_change_set_changetype(chg
, OSYNC_CHANGE_TYPE_DELETED
);
468 osync_trace(TRACE_INTERNAL
, "deleted entry!");
471 osync_change_set_changetype(chg
, OSYNC_CHANGE_TYPE_MODIFIED
);
473 osync_context_report_change(ctx
, chg
);
474 osync_change_unref(chg
);
479 /* Load XSLT style to convert osync xmlformat-contact --> gdata */
480 snprintf(buffer
, sizeof(buffer
) - 1, "%s/osync2gcont.xslt",
482 if ((result
= xslt_initialize(plgdata
->xslt_ctx_gcont
, buffer
))) {
483 msg
= "Cannot initialize new XSLT!\n";
487 osync_trace(TRACE_INTERNAL
, "\ndone contact: %s\n", buffer
);
490 osync_context_report_success(ctx
);
494 osync_error_unref(&error
);
495 osync_xmlformat_unref(&xmlformat
);
498 osync_context_report_error(ctx
, OSYNC_ERROR_GENERIC
, msg
);
501 static void gc_commit_change_calendar(void *data
, OSyncPluginInfo
*info
,
502 OSyncContext
*ctx
, OSyncChange
*change
)
504 osync_trace(TRACE_ENTRY
, "%s(%p, %p, %p)", __func__
, data
, info
, ctx
, change
);
505 osync_trace(TRACE_INTERNAL
, "hello, from calendar!\n");
506 OSyncObjTypeSink
*sink
= osync_plugin_info_get_sink(info
);
507 struct gc_plgdata
*plgdata
= data
;
508 gcal_event event
= NULL
;
511 char *osync_xml
= NULL
, *msg
= NULL
, *raw_xml
= NULL
, *updated_event
= NULL
;
512 OSyncData
*odata
= NULL
;
514 if (!(odata
= osync_change_get_data(change
))) {
515 msg
= "Cannot get raw data from change obj!\n";
519 osync_data_get_data(odata
, &osync_xml
, &size
);
521 msg
= "Failed getting xml from change obj!\n";
525 /* Convert to gdata format */
526 if ((result
= xslt_transform(plgdata
->xslt_ctx_gcal
, osync_xml
))) {
527 msg
= "Failed converting from osync xmlevent to gcalendar\n";
530 raw_xml
= plgdata
->xslt_ctx_gcal
->xml_str
;
532 osync_trace(TRACE_EXIT
, "osync: %s\ngcont: %s\n\n", osync_xml
, raw_xml
);
534 switch (osync_change_get_changetype(change
)) {
535 case OSYNC_CHANGE_TYPE_ADDED
:
536 result
= gcal_add_xmlentry(plgdata
->calendar
, raw_xml
, &updated_event
);
538 msg
= "Failed adding new event!\n";
539 result
= gcal_status_httpcode(plgdata
->calendar
);
543 if (!(event
= gcal_event_new(updated_event
))) {
544 msg
= "Failed recovering updated fields!\n";
549 case OSYNC_CHANGE_TYPE_MODIFIED
:
550 result
= gcal_update_xmlentry(plgdata
->calendar
, raw_xml
, &updated_event
,
553 msg
= "Failed editing event!\n";
557 if (!(event
= gcal_event_new(updated_event
))) {
558 msg
= "Failed recovering updated fields!\n";
563 case OSYNC_CHANGE_TYPE_DELETED
:
564 result
= gcal_erase_xmlentry(plgdata
->calendar
, raw_xml
);
566 msg
= "Failed deleting event!\n";
572 osync_context_report_error(ctx
, OSYNC_ERROR_NOT_SUPPORTED
,
573 "Unknown change type");
582 /* update the timestamp */
583 if (plgdata
->cal_timestamp
)
584 free(plgdata
->cal_timestamp
);
585 plgdata
->cal_timestamp
= strdup(gcal_event_get_updated(event
));
586 if (!plgdata
->cal_timestamp
) {
587 msg
= "Failed copying contact timestamp!\n";
591 /* FIXME: not sure if this works */
592 /* Inform the new ID */
593 osync_change_set_uid(change
, gcal_event_get_url(event
));
594 gcal_event_delete(event
);
598 osync_context_report_success(ctx
);
600 osync_trace(TRACE_EXIT
, "%s", __func__
);
604 osync_context_report_error(ctx
, OSYNC_ERROR_GENERIC
, msg
);
605 osync_trace(TRACE_EXIT
, "%s:%sHTTP code: %d", __func__
, msg
, result
);
608 static void gc_commit_change_contact(void *data
, OSyncPluginInfo
*info
,
609 OSyncContext
*ctx
, OSyncChange
*change
)
611 osync_trace(TRACE_ENTRY
, "%s(%p, %p, %p)", __func__
, data
, info
, ctx
, change
);
612 osync_trace(TRACE_INTERNAL
, "hello, from contacts!\n");
614 OSyncObjTypeSink
*sink
= osync_plugin_info_get_sink(info
);
615 struct gc_plgdata
*plgdata
= data
;
616 gcal_contact contact
= NULL
;
618 char *osync_xml
= NULL
, *msg
= NULL
, *raw_xml
= NULL
, *updated_contact
= NULL
;
619 OSyncData
*odata
= NULL
;
621 if (!(odata
= osync_change_get_data(change
))) {
622 msg
= "Cannot get raw data from change obj!\n";
626 osync_data_get_data(odata
, &osync_xml
, &size
);
628 msg
= "Failed getting xml from change obj!\n";
632 /* Convert to gdata format */
633 if ((result
= xslt_transform(plgdata
->xslt_ctx_gcont
, osync_xml
))) {
634 msg
= "Failed converting from osync xmlcontact to gcontact\n";
637 raw_xml
= plgdata
->xslt_ctx_gcont
->xml_str
;
639 osync_trace(TRACE_INTERNAL
, "osync: %s\ngcont: %s\n\n", osync_xml
, raw_xml
);
641 switch (osync_change_get_changetype(change
)) {
642 case OSYNC_CHANGE_TYPE_ADDED
:
643 result
= gcal_add_xmlentry(plgdata
->contacts
, raw_xml
, &updated_contact
);
645 msg
= "Failed adding new contact!\n";
646 result
= gcal_status_httpcode(plgdata
->contacts
);
650 if (!(contact
= gcal_contact_new(updated_contact
))) {
651 msg
= "Failed recovering updated fields!\n";
656 case OSYNC_CHANGE_TYPE_MODIFIED
:
657 result
= gcal_update_xmlentry(plgdata
->contacts
, raw_xml
, &updated_contact
,
660 msg
= "Failed editing contact!\n";
664 if (!(contact
= gcal_contact_new(updated_contact
))) {
665 msg
= "Failed recovering updated fields!\n";
670 case OSYNC_CHANGE_TYPE_DELETED
:
671 result
= gcal_erase_xmlentry(plgdata
->contacts
, raw_xml
);
673 msg
= "Failed deleting contact!\n";
679 osync_context_report_error(ctx
, OSYNC_ERROR_NOT_SUPPORTED
,
680 "Unknown change type");
686 free(updated_contact
);
689 /* update the timestamp */
690 if (plgdata
->cont_timestamp
)
691 free(plgdata
->cont_timestamp
);
692 plgdata
->cont_timestamp
= strdup(gcal_contact_get_updated(contact
));
693 if (!plgdata
->cont_timestamp
) {
694 msg
= "Failed copying contact timestamp!\n";
698 /* FIXME: not sure if this works */
699 /* Inform the new ID */
700 osync_change_set_uid(change
, gcal_contact_get_url(contact
));
701 gcal_contact_delete(contact
);
704 osync_context_report_success(ctx
);
705 osync_trace(TRACE_EXIT
, "%s", __func__
);
709 osync_context_report_error(ctx
, OSYNC_ERROR_GENERIC
, msg
);
710 osync_trace(TRACE_EXIT
, "%s:%sHTTP code: %d", __func__
, msg
, result
);
713 static void gc_sync_done(void *data
, OSyncPluginInfo
*info
, OSyncContext
*ctx
)
715 osync_trace(TRACE_ENTRY
, "%s(%p, %p, %p)", __func__
, data
, info
, ctx
);
716 struct gc_plgdata
*plgdata
= data
;
717 OSyncObjTypeSink
*sink
= osync_plugin_info_get_sink(info
);
719 if (plgdata
->calendar
&& plgdata
->cal_timestamp
) {
720 osync_trace(TRACE_INTERNAL
, "query updated timestamp: %s\n",
721 plgdata
->cal_timestamp
);
722 osync_anchor_update(plgdata
->gcal_anchor_path
, "gcalendar",
723 plgdata
->cal_timestamp
);
726 if (plgdata
->contacts
&& plgdata
->cont_timestamp
) {
727 osync_trace(TRACE_INTERNAL
, "query updated timestamp: %s\n",
728 plgdata
->cont_timestamp
);
729 osync_anchor_update(plgdata
->gcont_anchor_path
, "gcontact",
730 plgdata
->cont_timestamp
);
733 osync_context_report_success(ctx
);
736 static void gc_disconnect(void *data
, OSyncPluginInfo
*info
, OSyncContext
*ctx
)
738 osync_trace(TRACE_ENTRY
, "%s(%p, %p, %p)", __func__
, data
, info
, ctx
);
739 osync_context_report_success(ctx
);
740 osync_trace(TRACE_EXIT
, "%s", __func__
);
743 static void gc_finalize(void *data
)
745 osync_trace(TRACE_ENTRY
, "%s(%p)", __func__
, data
);
746 struct gc_plgdata
*plgdata
= data
;
749 osync_trace(TRACE_EXIT
, "%s", __func__
);
752 static void *gc_initialize(OSyncPlugin
*plugin
,
753 OSyncPluginInfo
*info
,
756 osync_trace(TRACE_ENTRY
, "%s(%p, %p, %p)", __func__
, plugin
, info
, error
);
757 struct gc_plgdata
*plgdata
;
758 OSyncPluginConfig
*config
;
759 OSyncPluginAuthentication
*auth
;
760 OSyncPluginAdvancedOption
*advanced
;
761 OSyncList
*resources
;
763 const char *objtype
, *tmp
;
766 plgdata
= osync_try_malloc0(sizeof(struct gc_plgdata
), error
);
767 config
= osync_plugin_info_get_config(info
);
768 if ((!plgdata
) || (!config
)) {
769 osync_error_set(error
, OSYNC_ERROR_GENERIC
,
770 "Unable to get config data.");
774 advanced
= osync_plugin_config_get_advancedoption_value_by_name(config
, "xslt");
776 osync_trace(TRACE_INTERNAL
, "Cannot locate xslt config!\n");
780 if (!(plgdata
->xslt_path
= strdup(osync_plugin_advancedoption_get_value(advanced
))))
783 resources
= osync_plugin_config_get_resources(config
);
784 numobjs
= osync_plugin_info_num_objtypes(info
);
786 for (i
= 1, r
= resources
; r
; r
= r
->next
, i
++) {
787 osync_trace(TRACE_INTERNAL
, "field: %s\n", osync_plugin_resource_get_objtype(r
->data
));
788 if (!(strcmp(osync_plugin_resource_get_objtype(r
->data
), "event")))
789 if (!(plgdata
->calendar
= gcal_new(GCALENDAR
)))
792 osync_trace(TRACE_INTERNAL
, "\tcreated calendar obj!\n");
793 gcal_set_store_xml(plgdata
->calendar
, 1);
796 if (!(strcmp(osync_plugin_resource_get_objtype(r
->data
), "contact")))
797 if (!(plgdata
->contacts
= gcal_new(GCONTACT
)))
800 osync_trace(TRACE_INTERNAL
, "\tcreated contact obj!\n");
801 gcal_set_store_xml(plgdata
->contacts
, 1);
807 /* TODO: how works resource policy? For while, copy everything... */
808 for (i
= 0; i
< numobjs
; i
++) {
810 if (!plgdata
->username
) {
811 auth
= osync_plugin_config_get_authentication(config
);
812 tmp
= osync_plugin_authentication_get_username(auth
);
816 if (!(plgdata
->username
= strdup(tmp
)))
821 if (!plgdata
->password
) {
822 tmp
= osync_plugin_authentication_get_password(auth
);
826 if (!(plgdata
->password
= strdup(tmp
)))
830 /* TODO: get proxy/calendar title/resources/etc */
834 OSyncObjTypeSinkFunctions functions_gcal
;
835 memset(&functions_gcal
, 0, sizeof(functions_gcal
));
836 functions_gcal
.connect
= gc_connect
;
837 functions_gcal
.get_changes
= gc_get_changes_calendar
;
838 functions_gcal
.commit
= gc_commit_change_calendar
;
839 functions_gcal
.disconnect
= gc_disconnect
;
840 functions_gcal
.sync_done
= gc_sync_done
;
843 if (plgdata
->calendar
) {
844 osync_trace(TRACE_INTERNAL
, "\tcreating calendar sink...\n");
845 OSyncFormatEnv
*formatenv1
= osync_plugin_info_get_format_env(info
);
846 plgdata
->gcal_format
= osync_format_env_find_objformat(formatenv1
, "xmlformat-event");
847 if (!plgdata
->gcal_format
)
849 osync_objformat_ref(plgdata
->gcal_format
);
851 plgdata
->gcal_sink
= osync_plugin_info_find_objtype(info
, "event");
852 if (!plgdata
->gcal_sink
)
855 osync_objtype_sink_set_functions(plgdata
->gcal_sink
, functions_gcal
, plgdata
);
856 osync_plugin_info_add_objtype(info
, plgdata
->gcal_sink
);
860 OSyncObjTypeSinkFunctions functions_gcont
;
861 memset(&functions_gcont
, 0, sizeof(functions_gcont
));
862 functions_gcont
.connect
= gc_connect
;
863 functions_gcont
.get_changes
= gc_get_changes_contact
;
864 functions_gcont
.commit
= gc_commit_change_contact
;
865 functions_gcont
.disconnect
= gc_disconnect
;
866 functions_gcont
.sync_done
= gc_sync_done
;
868 if (plgdata
->contacts
) {
869 osync_trace(TRACE_INTERNAL
, "\tcreating contact sink...\n");
870 OSyncFormatEnv
*formatenv2
= osync_plugin_info_get_format_env(info
);
871 plgdata
->gcont_format
= osync_format_env_find_objformat(formatenv2
, "xmlformat-contact");
872 if (!plgdata
->gcont_format
)
874 osync_objformat_ref(plgdata
->gcont_format
);
876 plgdata
->gcont_sink
= osync_plugin_info_find_objtype(info
, "contact");
877 if (!plgdata
->gcont_sink
)
880 osync_objtype_sink_set_functions(plgdata
->gcont_sink
, functions_gcont
, plgdata
);
881 osync_plugin_info_add_objtype(info
, plgdata
->gcont_sink
);
886 plgdata
->gcal_anchor_path
= g_strdup_printf("%s/calendar_anchor.db",
887 osync_plugin_info_get_configdir(info
));
888 if (!(plgdata
->gcal_anchor_path
))
891 osync_trace(TRACE_INTERNAL
, "\tanchor: %s\n", plgdata
->gcal_anchor_path
);
893 plgdata
->gcont_anchor_path
= g_strdup_printf("%s/contact_anchor.db",
894 osync_plugin_info_get_configdir(info
));
895 if (!(plgdata
->gcont_anchor_path
))
898 osync_trace(TRACE_INTERNAL
, "\tanchor: %s\n", plgdata
->gcont_anchor_path
);
900 if (plgdata
->calendar
)
901 if (!(plgdata
->xslt_ctx_gcal
= xslt_new()))
904 osync_trace(TRACE_INTERNAL
, "\tsucceed creating xslt_gcal!\n");
906 if (plgdata
->contacts
)
907 if (!(plgdata
->xslt_ctx_gcont
= xslt_new()))
910 osync_trace(TRACE_INTERNAL
, "\tsucceed creating xslt_gcont!\n");
912 osync_trace(TRACE_EXIT
, "%s", __func__
);
920 osync_trace(TRACE_EXIT_ERROR
, "%s: %s", __func__
, osync_error_print(error
));
924 static osync_bool
gc_discover(void *data
, OSyncPluginInfo
*info
, OSyncError
**error
)
926 osync_trace(TRACE_ENTRY
, "%s(%p, %p, %p)", __func__
, data
, info
, error
);
928 struct gc_plgdata
*plgdata
= data
;
930 if (plgdata
->calendar
)
931 osync_objtype_sink_set_available(plgdata
->gcal_sink
, TRUE
);
932 if (plgdata
->contacts
)
933 osync_objtype_sink_set_available(plgdata
->gcont_sink
, TRUE
);
935 OSyncVersion
*version
= osync_version_new(error
);
936 osync_version_set_plugin(version
, "google-data");
937 osync_plugin_info_set_version(info
, version
);
938 osync_version_unref(version
);
940 osync_trace(TRACE_EXIT
, "%s", __func__
);
944 osync_bool
get_sync_info(OSyncPluginEnv
*env
, OSyncError
**error
)
946 osync_trace(TRACE_ENTRY
, "%s(%p, %p)", __func__
, env
, error
);
947 OSyncPlugin
*plugin
= osync_plugin_new(error
);
951 osync_plugin_set_name(plugin
, "google-data");
952 osync_plugin_set_longname(plugin
, "Google calendar/plugin");
953 osync_plugin_set_description(plugin
, "Google calendar and contacts plugin");
955 osync_plugin_set_initialize(plugin
, gc_initialize
);
956 osync_plugin_set_finalize(plugin
, gc_finalize
);
957 osync_plugin_set_discover(plugin
, gc_discover
);
959 osync_plugin_env_register_plugin(env
, plugin
);
960 osync_plugin_unref(plugin
);
962 osync_trace(TRACE_EXIT
, "%s", __func__
);
966 osync_trace(TRACE_EXIT_ERROR
, "Unable to register: %s", osync_error_print(error
));
967 osync_error_unref(error
);
971 int get_version(void)