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 /* From timestamp string to time structure */
66 strptime(timestamp1
, format
, &first
);
67 strptime(timestamp2
, format
, &second
);
69 /* From time structure to calendar time (since
70 * Epoch (00:00:00 UTC, January 1, 1970)
72 t_first
= mktime(&first
);
73 t_second
= mktime(&second
);
75 if (t_first
== t_second
)
77 else if (t_first
> t_second
)
79 else if (t_first
< t_second
)
91 char *gcal_anchor_path
;
92 char *gcont_anchor_path
;
95 /* libgcal resources */
100 struct gcal_event_array all_events
;
101 struct gcal_contact_array all_contacts
;
102 /* calendar sink/format */
103 OSyncObjTypeSink
*gcal_sink
;
104 OSyncObjFormat
*gcal_format
;
105 /* contact sink/format */
106 OSyncObjTypeSink
*gcont_sink
;
107 OSyncObjFormat
*gcont_format
;
108 /* XSLT context resource struct */
109 struct xslt_resources
*xslt_ctx_gcal
;
110 struct xslt_resources
*xslt_ctx_gcont
;
113 static void free_plg(struct gc_plgdata
*plgdata
)
115 if (plgdata
->calendar
) {
116 gcal_delete(plgdata
->calendar
);
117 gcal_cleanup_events(&(plgdata
->all_events
));
119 if (plgdata
->contacts
) {
120 gcal_delete(plgdata
->contacts
);
121 gcal_cleanup_contacts(&(plgdata
->all_contacts
));
124 if (plgdata
->gcal_anchor_path
)
125 g_free(plgdata
->gcal_anchor_path
);
126 if (plgdata
->gcont_anchor_path
)
127 g_free(plgdata
->gcont_anchor_path
);
128 if (plgdata
->xslt_path
)
129 free(plgdata
->xslt_path
);
130 if (plgdata
->xslt_ctx_gcal
)
131 xslt_delete(plgdata
->xslt_ctx_gcal
);
132 if (plgdata
->xslt_ctx_gcont
)
133 xslt_delete(plgdata
->xslt_ctx_gcont
);
134 if (plgdata
->cal_timestamp
)
135 free(plgdata
->cal_timestamp
);
136 if (plgdata
->cont_timestamp
)
137 free(plgdata
->cont_timestamp
);
138 if (plgdata
->timezone
)
139 free(plgdata
->timezone
);
141 xmlFree(plgdata
->url
);
142 if (plgdata
->username
)
143 xmlFree(plgdata
->username
);
144 if (plgdata
->password
)
145 xmlFree(plgdata
->password
);
146 if (plgdata
->gcal_sink
)
147 osync_objtype_sink_unref(plgdata
->gcal_sink
);
148 if (plgdata
->gcal_format
)
149 osync_objformat_unref(plgdata
->gcal_format
);
153 static void gc_connect(void *data
, OSyncPluginInfo
*info
, OSyncContext
*ctx
)
155 osync_trace(TRACE_ENTRY
, "%s(%p, %p, %p)", __func__
, data
, info
, ctx
);
156 static int counter
= 0;
158 struct gc_plgdata
*plgdata
= data
;
159 OSyncObjTypeSink
*sink
= osync_plugin_info_get_sink(info
);
160 OSyncError
*error
= NULL
;
163 if ((plgdata
->calendar
) && (counter
== 0)) {
164 result
= gcal_get_authentication(plgdata
->calendar
, plgdata
->username
,
170 snprintf(buffer
, sizeof(buffer
) - 1, "%s/gcal2osync.xslt",
172 if ((result
= xslt_initialize(plgdata
->xslt_ctx_gcal
, buffer
)))
174 osync_trace(TRACE_INTERNAL
, "\ndone calendar: %s\n", buffer
);
177 if (((plgdata
->contacts
) && (counter
== 1)) ||
178 ((plgdata
->gcont_sink
) && (!plgdata
->gcal_sink
))) {
179 result
= gcal_get_authentication(plgdata
->contacts
, plgdata
->username
,
185 snprintf(buffer
, sizeof(buffer
) - 1, "%s/gcont2osync.xslt",
187 if ((result
= xslt_initialize(plgdata
->xslt_ctx_gcont
, buffer
)))
189 osync_trace(TRACE_INTERNAL
, "\ndone contact: %s\n", buffer
);
192 osync_context_report_success(ctx
);
193 osync_trace(TRACE_EXIT
, "%s", __func__
);
197 osync_trace(TRACE_INTERNAL
, "\nGood bye, cruel world...\n");
198 osync_context_report_osyncerror(ctx
, &error
);
201 static void gc_get_changes_calendar(void *data
, OSyncPluginInfo
*info
, OSyncContext
*ctx
)
203 osync_trace(TRACE_ENTRY
, "%s(%p, %p, %p)", __func__
, data
, info
, ctx
);
205 static int counter
= 0;
206 struct gc_plgdata
*plgdata
= data
;
207 char slow_sync_flag
= 0;
208 OSyncObjTypeSink
*sink
= osync_plugin_info_get_sink(info
);
209 OSyncError
*error
= NULL
;
210 OSyncXMLFormat
*xmlformat
;
211 OSyncData
*odata
= NULL
;
212 OSyncChange
*chg
= NULL
;
214 char *timestamp
= NULL
, *msg
, *raw_xml
= NULL
;
217 if (!plgdata
->gcal_sink
)
219 timestamp
= osync_anchor_retrieve(plgdata
->gcal_anchor_path
, "gcalendar");
221 osync_trace(TRACE_INTERNAL
, "timestamp is: %s\n", timestamp
);
223 osync_trace(TRACE_INTERNAL
, "first sync!\n");
225 if (osync_objtype_sink_get_slowsync(plgdata
->gcal_sink
)) {
226 osync_trace(TRACE_INTERNAL
, "\n\t\tgcal: Client asked for slow syncing...\n");
228 result
= gcal_get_events(plgdata
->calendar
, &(plgdata
->all_events
));
231 osync_trace(TRACE_INTERNAL
, "\n\t\tgcal: Client asked for fast syncing...\n");
232 result
= gcal_get_updated_events(plgdata
->calendar
,
233 &(plgdata
->all_events
),
238 msg
= "Failed getting events!";
242 osync_trace(TRACE_INTERNAL
, "gcalendar: got then all!\n");
243 if (plgdata
->all_events
.length
== 0) {
244 osync_trace(TRACE_INTERNAL
, "gcalendar: no changes...\n");
247 osync_trace(TRACE_INTERNAL
, "gcalendar: changes count: %d\n",
248 plgdata
->all_events
.length
);
251 /* Calendar returns most recently updated event as first element */
252 event
= gcal_event_element(&(plgdata
->all_events
), 0);
254 msg
= "Cannot access last updated event!\n";
257 plgdata
->cont_timestamp
= strdup(gcal_event_get_updated(event
));
258 if (!plgdata
->cont_timestamp
) {
259 msg
= "Failed copying event timestamp!\n";
263 for (i
= 0; i
< plgdata
->all_events
.length
; ++i
) {
264 event
= gcal_event_element(&(plgdata
->all_events
), i
);
268 raw_xml
= gcal_event_get_xml(event
);
269 if ((result
= xslt_transform(plgdata
->xslt_ctx_gcal
,
273 raw_xml
= plgdata
->xslt_ctx_gcal
->xml_str
;
274 xmlformat
= osync_xmlformat_parse(raw_xml
,
280 osync_trace(TRACE_INTERNAL
, "gevent: %s\nosync: %s\n",
281 gcal_event_get_xml(event
), raw_xml
);
283 osync_xmlformat_sort(xmlformat
);
284 odata
= osync_data_new(xmlformat
,
285 osync_xmlformat_size(),
286 plgdata
->gcal_format
, &error
);
290 if (!(chg
= osync_change_new(&error
)))
292 osync_data_set_objtype(odata
, osync_objtype_sink_get_name(plgdata
->gcal_sink
));
293 osync_change_set_data(chg
, odata
);
294 osync_data_unref(odata
);
296 osync_change_set_uid(chg
, gcal_event_get_url(event
));
299 osync_change_set_changetype(chg
, OSYNC_CHANGE_TYPE_ADDED
);
301 if (gcal_event_is_deleted(event
))
302 osync_change_set_changetype(chg
, OSYNC_CHANGE_TYPE_DELETED
);
304 osync_change_set_changetype(chg
, OSYNC_CHANGE_TYPE_MODIFIED
);
306 osync_context_report_change(ctx
, chg
);
307 osync_change_unref(chg
);
312 /* Load XSLT style to convert osync xmlformat-event --> gdata */
313 snprintf(buffer
, sizeof(buffer
) - 1, "%s/osync2gcal.xslt",
315 if ((result
= xslt_initialize(plgdata
->xslt_ctx_gcal
, buffer
))) {
316 msg
= "Cannot initialize new XSLT!\n";
320 osync_trace(TRACE_INTERNAL
, "\ndone calendar: %s\n", buffer
);
323 osync_context_report_success(ctx
);
327 osync_error_unref(&error
);
328 osync_xmlformat_unref(&xmlformat
);
331 osync_context_report_error(ctx
, OSYNC_ERROR_GENERIC
, msg
);
336 static void gc_get_changes_contact(void *data
, OSyncPluginInfo
*info
, OSyncContext
*ctx
)
338 osync_trace(TRACE_ENTRY
, "%s(%p, %p, %p)", __func__
, data
, info
, ctx
);
340 static int counter
= 0;
341 struct gc_plgdata
*plgdata
= data
;
342 char slow_sync_flag
= 0;
343 OSyncObjTypeSink
*sink
= osync_plugin_info_get_sink(info
);
344 OSyncError
*error
= NULL
;
345 OSyncXMLFormat
*xmlformat
;
346 OSyncData
*odata
= NULL
;
347 OSyncChange
*chg
= NULL
;
349 char *timestamp
= NULL
, *msg
, *raw_xml
= NULL
;
350 gcal_contact contact
;
353 if (!plgdata
->gcont_sink
)
355 timestamp
= osync_anchor_retrieve(plgdata
->gcont_anchor_path
, "gcontact");
357 osync_trace(TRACE_INTERNAL
, "timestamp is: %s\n", timestamp
);
359 osync_trace(TRACE_INTERNAL
, "first sync!\n");
361 if (osync_objtype_sink_get_slowsync(plgdata
->gcont_sink
)) {
362 osync_trace(TRACE_INTERNAL
, "\n\t\tgcont: Client asked for slow syncing...\n");
364 result
= gcal_get_contacts(plgdata
->contacts
, &(plgdata
->all_contacts
));
367 osync_trace(TRACE_INTERNAL
, "\n\t\tgcont: Client asked for fast syncing...\n");
368 result
= gcal_get_updated_contacts(plgdata
->contacts
,
369 &(plgdata
->all_contacts
),
374 msg
= "Failed getting contacts!";
378 osync_trace(TRACE_INTERNAL
, "gcontact: got then all!\n");
379 if (plgdata
->all_contacts
.length
== 0) {
380 osync_trace(TRACE_INTERNAL
, "gcontact: no changes...\n");
383 osync_trace(TRACE_INTERNAL
, "gcontact: changes count: %d\n",
384 plgdata
->all_contacts
.length
);
386 /* Contacts returns most recently updated entry as last element */
387 contact
= gcal_contact_element(&(plgdata
->all_contacts
),
388 (plgdata
->all_contacts
.length
- 1));
390 msg
= "Cannot access last updated contact!\n";
393 plgdata
->cont_timestamp
= strdup(gcal_contact_get_updated(contact
));
394 if (!plgdata
->cont_timestamp
) {
395 msg
= "Failed copying contact timestamp!\n";
399 for (i
= 0; i
< plgdata
->all_contacts
.length
; ++i
) {
400 contact
= gcal_contact_element(&(plgdata
->all_contacts
), i
);
404 raw_xml
= gcal_contact_get_xml(contact
);
405 if ((result
= xslt_transform(plgdata
->xslt_ctx_gcont
,
408 raw_xml
= plgdata
->xslt_ctx_gcont
->xml_str
;
409 xmlformat
= osync_xmlformat_parse(raw_xml
,
415 osync_trace(TRACE_INTERNAL
, "gcont: %s\nosync: %s\n",
416 gcal_contact_get_xml(contact
), raw_xml
);
418 osync_xmlformat_sort(xmlformat
);
420 odata
= osync_data_new(xmlformat
,
421 osync_xmlformat_size(),
422 plgdata
->gcont_format
, &error
);
427 if (!(chg
= osync_change_new(&error
)))
429 osync_data_set_objtype(odata
, osync_objtype_sink_get_name(plgdata
->gcont_sink
));
430 osync_change_set_data(chg
, odata
);
431 osync_data_unref(odata
);
433 osync_change_set_uid(chg
, gcal_contact_get_url(contact
));
436 osync_change_set_changetype(chg
, OSYNC_CHANGE_TYPE_ADDED
);
438 if (gcal_contact_is_deleted(contact
))
439 osync_change_set_changetype(chg
, OSYNC_CHANGE_TYPE_DELETED
);
441 osync_change_set_changetype(chg
, OSYNC_CHANGE_TYPE_MODIFIED
);
443 osync_context_report_change(ctx
, chg
);
444 osync_change_unref(chg
);
449 /* Load XSLT style to convert osync xmlformat-contact --> gdata */
450 snprintf(buffer
, sizeof(buffer
) - 1, "%s/osync2gcont.xslt",
452 if ((result
= xslt_initialize(plgdata
->xslt_ctx_gcont
, buffer
))) {
453 msg
= "Cannot initialize new XSLT!\n";
457 osync_trace(TRACE_INTERNAL
, "\ndone contact: %s\n", buffer
);
460 osync_context_report_success(ctx
);
464 osync_error_unref(&error
);
465 osync_xmlformat_unref(&xmlformat
);
468 osync_context_report_error(ctx
, OSYNC_ERROR_GENERIC
, msg
);
471 static void gc_commit_change_calendar(void *data
, OSyncPluginInfo
*info
,
472 OSyncContext
*ctx
, OSyncChange
*change
)
474 osync_trace(TRACE_ENTRY
, "%s(%p, %p, %p)", __func__
, data
, info
, ctx
, change
);
475 osync_trace(TRACE_INTERNAL
, "hello, from calendar!\n");
476 OSyncObjTypeSink
*sink
= osync_plugin_info_get_sink(info
);
477 struct gc_plgdata
*plgdata
= data
;
478 gcal_event event
= NULL
;
481 char *osync_xml
= NULL
, *msg
= NULL
, *raw_xml
= NULL
, *updated_event
= NULL
;
482 OSyncData
*odata
= NULL
;
484 if (!(odata
= osync_change_get_data(change
))) {
485 msg
= "Cannot get raw data from change obj!\n";
489 osync_data_get_data(odata
, &osync_xml
, &size
);
491 msg
= "Failed getting xml from change obj!\n";
495 /* Convert to gdata format */
496 if ((result
= xslt_transform(plgdata
->xslt_ctx_gcal
, osync_xml
))) {
497 msg
= "Failed converting from osync xmlevent to gcalendar\n";
500 raw_xml
= plgdata
->xslt_ctx_gcal
->xml_str
;
502 osync_trace(TRACE_EXIT
, "osync: %s\ngcont: %s\n\n", osync_xml
, raw_xml
);
504 switch (osync_change_get_changetype(change
)) {
505 case OSYNC_CHANGE_TYPE_ADDED
:
506 result
= gcal_add_xmlentry(plgdata
->calendar
, raw_xml
, &updated_event
);
508 msg
= "Failed adding new event!\n";
509 result
= gcal_status_httpcode(plgdata
->calendar
);
513 if (!(event
= gcal_event_new(updated_event
))) {
514 msg
= "Failed recovering updated fields!\n";
519 case OSYNC_CHANGE_TYPE_MODIFIED
:
520 result
= gcal_update_xmlentry(plgdata
->calendar
, raw_xml
, &updated_event
,
523 msg
= "Failed editing event!\n";
527 if (!(event
= gcal_event_new(updated_event
))) {
528 msg
= "Failed recovering updated fields!\n";
533 case OSYNC_CHANGE_TYPE_DELETED
:
534 result
= gcal_erase_xmlentry(plgdata
->calendar
, raw_xml
);
536 msg
= "Failed deleting event!\n";
542 osync_context_report_error(ctx
, OSYNC_ERROR_NOT_SUPPORTED
,
543 "Unknown change type");
552 /* update the timestamp */
553 if (plgdata
->cal_timestamp
)
554 free(plgdata
->cal_timestamp
);
555 plgdata
->cal_timestamp
= strdup(gcal_event_get_updated(event
));
556 if (!plgdata
->cal_timestamp
) {
557 msg
= "Failed copying contact timestamp!\n";
561 /* FIXME: not sure if this works */
562 /* Inform the new ID */
563 osync_change_set_uid(change
, gcal_event_get_url(event
));
564 gcal_event_delete(event
);
568 osync_context_report_success(ctx
);
570 osync_trace(TRACE_EXIT
, "%s", __func__
);
574 osync_context_report_error(ctx
, OSYNC_ERROR_GENERIC
, msg
);
575 osync_trace(TRACE_EXIT
, "%s:%sHTTP code: %d", __func__
, msg
, result
);
578 static void gc_commit_change_contact(void *data
, OSyncPluginInfo
*info
,
579 OSyncContext
*ctx
, OSyncChange
*change
)
581 osync_trace(TRACE_ENTRY
, "%s(%p, %p, %p)", __func__
, data
, info
, ctx
, change
);
582 osync_trace(TRACE_INTERNAL
, "hello, from contacts!\n");
584 OSyncObjTypeSink
*sink
= osync_plugin_info_get_sink(info
);
585 struct gc_plgdata
*plgdata
= data
;
586 gcal_contact contact
= NULL
;
588 char *osync_xml
= NULL
, *msg
= NULL
, *raw_xml
= NULL
, *updated_contact
= NULL
;
589 OSyncData
*odata
= NULL
;
591 if (!(odata
= osync_change_get_data(change
))) {
592 msg
= "Cannot get raw data from change obj!\n";
596 osync_data_get_data(odata
, &osync_xml
, &size
);
598 msg
= "Failed getting xml from change obj!\n";
602 /* Convert to gdata format */
603 if ((result
= xslt_transform(plgdata
->xslt_ctx_gcont
, osync_xml
))) {
604 msg
= "Failed converting from osync xmlcontact to gcontact\n";
607 raw_xml
= plgdata
->xslt_ctx_gcont
->xml_str
;
609 osync_trace(TRACE_INTERNAL
, "osync: %s\ngcont: %s\n\n", osync_xml
, raw_xml
);
611 switch (osync_change_get_changetype(change
)) {
612 case OSYNC_CHANGE_TYPE_ADDED
:
613 result
= gcal_add_xmlentry(plgdata
->contacts
, raw_xml
, &updated_contact
);
615 msg
= "Failed adding new contact!\n";
616 result
= gcal_status_httpcode(plgdata
->contacts
);
620 if (!(contact
= gcal_contact_new(updated_contact
))) {
621 msg
= "Failed recovering updated fields!\n";
626 case OSYNC_CHANGE_TYPE_MODIFIED
:
627 result
= gcal_update_xmlentry(plgdata
->contacts
, raw_xml
, &updated_contact
,
630 msg
= "Failed editing contact!\n";
634 if (!(contact
= gcal_contact_new(updated_contact
))) {
635 msg
= "Failed recovering updated fields!\n";
640 case OSYNC_CHANGE_TYPE_DELETED
:
641 result
= gcal_erase_xmlentry(plgdata
->contacts
, raw_xml
);
643 msg
= "Failed deleting contact!\n";
649 osync_context_report_error(ctx
, OSYNC_ERROR_NOT_SUPPORTED
,
650 "Unknown change type");
656 free(updated_contact
);
659 /* update the timestamp */
660 if (plgdata
->cont_timestamp
)
661 free(plgdata
->cont_timestamp
);
662 plgdata
->cont_timestamp
= strdup(gcal_contact_get_updated(contact
));
663 if (!plgdata
->cont_timestamp
) {
664 msg
= "Failed copying contact timestamp!\n";
668 /* FIXME: not sure if this works */
669 /* Inform the new ID */
670 osync_change_set_uid(change
, gcal_contact_get_url(contact
));
671 gcal_contact_delete(contact
);
674 osync_context_report_success(ctx
);
675 osync_trace(TRACE_EXIT
, "%s", __func__
);
679 osync_context_report_error(ctx
, OSYNC_ERROR_GENERIC
, msg
);
680 osync_trace(TRACE_EXIT
, "%s:%sHTTP code: %d", __func__
, msg
, result
);
683 static void gc_sync_done(void *data
, OSyncPluginInfo
*info
, OSyncContext
*ctx
)
685 osync_trace(TRACE_ENTRY
, "%s(%p, %p, %p)", __func__
, data
, info
, ctx
);
686 struct gc_plgdata
*plgdata
= data
;
687 OSyncObjTypeSink
*sink
= osync_plugin_info_get_sink(info
);
689 if (plgdata
->calendar
&& plgdata
->cal_timestamp
) {
690 /* FIXME: hack to workaround the limitation of google protocol
691 * doing inclusive query: advance 1 second in timestamp.
693 plgdata
->cal_timestamp
[18] += 1;
694 osync_trace(TRACE_INTERNAL
, "query updated timestamp: %s\n",
695 plgdata
->cal_timestamp
);
696 osync_anchor_update(plgdata
->gcal_anchor_path
, "gcalendar",
697 plgdata
->cal_timestamp
);
700 if (plgdata
->contacts
&& plgdata
->cont_timestamp
) {
701 /* FIXME: hack to workaround the limitation of google protocol
702 * doing inclusive query: advance 1 second in timestamp.
704 plgdata
->cont_timestamp
[18] += 1;
705 osync_trace(TRACE_INTERNAL
, "query updated timestamp: %s\n",
706 plgdata
->cont_timestamp
);
707 osync_anchor_update(plgdata
->gcont_anchor_path
, "gcontact",
708 plgdata
->cont_timestamp
);
711 osync_context_report_success(ctx
);
714 static void gc_disconnect(void *data
, OSyncPluginInfo
*info
, OSyncContext
*ctx
)
716 osync_trace(TRACE_ENTRY
, "%s(%p, %p, %p)", __func__
, data
, info
, ctx
);
717 osync_context_report_success(ctx
);
718 osync_trace(TRACE_EXIT
, "%s", __func__
);
721 static void gc_finalize(void *data
)
723 osync_trace(TRACE_ENTRY
, "%s(%p)", __func__
, data
);
724 struct gc_plgdata
*plgdata
= data
;
727 osync_trace(TRACE_EXIT
, "%s", __func__
);
730 static void *gc_initialize(OSyncPlugin
*plugin
,
731 OSyncPluginInfo
*info
,
734 osync_trace(TRACE_ENTRY
, "%s(%p, %p, %p)", __func__
, plugin
, info
, error
);
735 struct gc_plgdata
*plgdata
;
736 OSyncPluginConfig
*config
;
737 OSyncPluginAuthentication
*auth
;
738 OSyncPluginAdvancedOption
*advanced
;
739 OSyncList
*resources
;
741 const char *objtype
, *tmp
;
744 plgdata
= osync_try_malloc0(sizeof(struct gc_plgdata
), error
);
745 config
= osync_plugin_info_get_config(info
);
746 if ((!plgdata
) || (!config
)) {
747 osync_error_set(error
, OSYNC_ERROR_GENERIC
,
748 "Unable to get config data.");
752 advanced
= osync_plugin_config_get_advancedoption_value_by_name(config
, "xslt");
754 osync_trace(TRACE_INTERNAL
, "Cannot locate xslt config!\n");
758 if (!(plgdata
->xslt_path
= strdup(osync_plugin_advancedoption_get_value(advanced
))))
761 resources
= osync_plugin_config_get_resources(config
);
762 numobjs
= osync_plugin_info_num_objtypes(info
);
764 for (i
= 1, r
= resources
; r
; r
= r
->next
, i
++) {
765 osync_trace(TRACE_INTERNAL
, "field: %s\n", osync_plugin_resource_get_objtype(r
->data
));
766 if (!(strcmp(osync_plugin_resource_get_objtype(r
->data
), "event")))
767 if (!(plgdata
->calendar
= gcal_new(GCALENDAR
)))
770 osync_trace(TRACE_INTERNAL
, "\tcreated calendar obj!\n");
771 gcal_set_store_xml(plgdata
->calendar
, 1);
774 if (!(strcmp(osync_plugin_resource_get_objtype(r
->data
), "contact")))
775 if (!(plgdata
->contacts
= gcal_new(GCONTACT
)))
778 osync_trace(TRACE_INTERNAL
, "\tcreated contact obj!\n");
779 gcal_set_store_xml(plgdata
->contacts
, 1);
785 /* TODO: how works resource policy? For while, copy everything... */
786 for (i
= 0; i
< numobjs
; i
++) {
788 if (!plgdata
->username
) {
789 auth
= osync_plugin_config_get_authentication(config
);
790 tmp
= osync_plugin_authentication_get_username(auth
);
794 if (!(plgdata
->username
= strdup(tmp
)))
799 if (!plgdata
->password
) {
800 tmp
= osync_plugin_authentication_get_password(auth
);
804 if (!(plgdata
->password
= strdup(tmp
)))
808 /* TODO: get proxy/calendar title/resources/etc */
812 OSyncObjTypeSinkFunctions functions_gcal
;
813 memset(&functions_gcal
, 0, sizeof(functions_gcal
));
814 functions_gcal
.connect
= gc_connect
;
815 functions_gcal
.get_changes
= gc_get_changes_calendar
;
816 functions_gcal
.commit
= gc_commit_change_calendar
;
817 functions_gcal
.disconnect
= gc_disconnect
;
818 functions_gcal
.sync_done
= gc_sync_done
;
821 if (plgdata
->calendar
) {
822 osync_trace(TRACE_INTERNAL
, "\tcreating calendar sink...\n");
823 OSyncFormatEnv
*formatenv1
= osync_plugin_info_get_format_env(info
);
824 plgdata
->gcal_format
= osync_format_env_find_objformat(formatenv1
, "xmlformat-event");
825 if (!plgdata
->gcal_format
)
827 osync_objformat_ref(plgdata
->gcal_format
);
829 plgdata
->gcal_sink
= osync_plugin_info_find_objtype(info
, "event");
830 if (!plgdata
->gcal_sink
)
833 osync_objtype_sink_set_functions(plgdata
->gcal_sink
, functions_gcal
, plgdata
);
834 osync_plugin_info_add_objtype(info
, plgdata
->gcal_sink
);
838 OSyncObjTypeSinkFunctions functions_gcont
;
839 memset(&functions_gcont
, 0, sizeof(functions_gcont
));
840 functions_gcont
.connect
= gc_connect
;
841 functions_gcont
.get_changes
= gc_get_changes_contact
;
842 functions_gcont
.commit
= gc_commit_change_contact
;
843 functions_gcont
.disconnect
= gc_disconnect
;
844 functions_gcont
.sync_done
= gc_sync_done
;
846 if (plgdata
->contacts
) {
847 osync_trace(TRACE_INTERNAL
, "\tcreating contact sink...\n");
848 OSyncFormatEnv
*formatenv2
= osync_plugin_info_get_format_env(info
);
849 plgdata
->gcont_format
= osync_format_env_find_objformat(formatenv2
, "xmlformat-contact");
850 if (!plgdata
->gcont_format
)
852 osync_objformat_ref(plgdata
->gcont_format
);
854 plgdata
->gcont_sink
= osync_plugin_info_find_objtype(info
, "contact");
855 if (!plgdata
->gcont_sink
)
858 osync_objtype_sink_set_functions(plgdata
->gcont_sink
, functions_gcont
, plgdata
);
859 osync_plugin_info_add_objtype(info
, plgdata
->gcont_sink
);
864 plgdata
->gcal_anchor_path
= g_strdup_printf("%s/calendar_anchor.db",
865 osync_plugin_info_get_configdir(info
));
866 if (!(plgdata
->gcal_anchor_path
))
869 osync_trace(TRACE_INTERNAL
, "\tanchor: %s\n", plgdata
->gcal_anchor_path
);
871 plgdata
->gcont_anchor_path
= g_strdup_printf("%s/contact_anchor.db",
872 osync_plugin_info_get_configdir(info
));
873 if (!(plgdata
->gcont_anchor_path
))
876 osync_trace(TRACE_INTERNAL
, "\tanchor: %s\n", plgdata
->gcont_anchor_path
);
878 if (plgdata
->calendar
)
879 if (!(plgdata
->xslt_ctx_gcal
= xslt_new()))
882 osync_trace(TRACE_INTERNAL
, "\tsucceed creating xslt_gcal!\n");
884 if (plgdata
->contacts
)
885 if (!(plgdata
->xslt_ctx_gcont
= xslt_new()))
888 osync_trace(TRACE_INTERNAL
, "\tsucceed creating xslt_gcont!\n");
890 osync_trace(TRACE_EXIT
, "%s", __func__
);
898 osync_trace(TRACE_EXIT_ERROR
, "%s: %s", __func__
, osync_error_print(error
));
902 static osync_bool
gc_discover(void *data
, OSyncPluginInfo
*info
, OSyncError
**error
)
904 osync_trace(TRACE_ENTRY
, "%s(%p, %p, %p)", __func__
, data
, info
, error
);
906 struct gc_plgdata
*plgdata
= data
;
908 if (plgdata
->calendar
)
909 osync_objtype_sink_set_available(plgdata
->gcal_sink
, TRUE
);
910 if (plgdata
->contacts
)
911 osync_objtype_sink_set_available(plgdata
->gcont_sink
, TRUE
);
913 OSyncVersion
*version
= osync_version_new(error
);
914 osync_version_set_plugin(version
, "google-data");
915 osync_plugin_info_set_version(info
, version
);
916 osync_version_unref(version
);
918 osync_trace(TRACE_EXIT
, "%s", __func__
);
922 osync_bool
get_sync_info(OSyncPluginEnv
*env
, OSyncError
**error
)
924 osync_trace(TRACE_ENTRY
, "%s(%p, %p)", __func__
, env
, error
);
925 OSyncPlugin
*plugin
= osync_plugin_new(error
);
929 osync_plugin_set_name(plugin
, "google-data");
930 osync_plugin_set_longname(plugin
, "Google calendar/plugin");
931 osync_plugin_set_description(plugin
, "Google calendar and contacts plugin");
933 osync_plugin_set_initialize(plugin
, gc_initialize
);
934 osync_plugin_set_finalize(plugin
, gc_finalize
);
935 osync_plugin_set_discover(plugin
, gc_discover
);
937 osync_plugin_env_register_plugin(env
, plugin
);
938 osync_plugin_unref(plugin
);
940 osync_trace(TRACE_EXIT
, "%s", __func__
);
944 osync_trace(TRACE_EXIT_ERROR
, "Unable to register: %s", osync_error_print(error
));
945 osync_error_unref(error
);
949 int get_version(void)