Creating an gcal_contact object out of returned XML from google server
[gdataplugin.git] / src / gcalendar.c
blobbad8e90e5f5e012e7fa8228aece2feca525e219c
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 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
19 * 02110-1301 USA
23 /* TODO:
24 * - commitchanges: report back updated fields, when ADDED (ID/updated/edit_url) or
25 * UPDATED (updated/edit_url)
26 * - review code for leaks (I'm not sure if I'm using opensync API correctly...)
30 #include <opensync/opensync.h>
31 #include <opensync/opensync-plugin.h>
32 #include <opensync/opensync-helper.h>
33 #include <opensync/opensync-merger.h>
34 #include <opensync/opensync-format.h>
35 #include <opensync/opensync-data.h>
36 #include <opensync/opensync-version.h>
38 #include <glib.h>
40 #include <libxml/tree.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <sys/types.h>
46 #include <signal.h>
47 #include <sys/wait.h>
48 #include <gcal_status.h>
49 #include <gcalendar.h>
50 #include <gcontact.h>
51 #include "xslt_aux.h"
53 struct gc_plgdata
55 char *url;
56 char *username;
57 char *password;
58 char *gcal_anchor_path;
59 char *gcont_anchor_path;
60 char *timezone;
61 char *xslt_path;
62 /* libgcal resources */
63 char *cal_timestamp;
64 char *cont_timestamp;
65 gcal_t calendar;
66 gcal_t contacts;
67 struct gcal_event_array all_events;
68 struct gcal_contact_array all_contacts;
69 /* calendar sink/format */
70 OSyncObjTypeSink *gcal_sink;
71 OSyncObjFormat *gcal_format;
72 /* contact sink/format */
73 OSyncObjTypeSink *gcont_sink;
74 OSyncObjFormat *gcont_format;
75 /* XSLT context resource struct */
76 struct xslt_resources *xslt_ctx_gcal;
77 struct xslt_resources *xslt_ctx_gcont;
80 static void free_plg(struct gc_plgdata *plgdata)
82 if (plgdata->calendar) {
83 gcal_delete(plgdata->calendar);
84 gcal_cleanup_events(&(plgdata->all_events));
86 if (plgdata->contacts) {
87 gcal_delete(plgdata->contacts);
88 gcal_cleanup_contacts(&(plgdata->all_contacts));
91 if (plgdata->gcal_anchor_path)
92 free(plgdata->gcal_anchor_path);
93 if (plgdata->gcont_anchor_path)
94 free(plgdata->gcont_anchor_path);
95 if (plgdata->xslt_path)
96 free(plgdata->xslt_path);
97 if (plgdata->xslt_ctx_gcal)
98 xslt_delete(plgdata->xslt_ctx_gcal);
99 if (plgdata->xslt_ctx_gcont)
100 xslt_delete(plgdata->xslt_ctx_gcont);
101 if (plgdata->cal_timestamp)
102 free(plgdata->cal_timestamp);
103 if (plgdata->cont_timestamp)
104 free(plgdata->cont_timestamp);
105 if (plgdata->timezone)
106 free(plgdata->timezone);
107 if (plgdata->url)
108 xmlFree(plgdata->url);
109 if (plgdata->username)
110 xmlFree(plgdata->username);
111 if (plgdata->password)
112 xmlFree(plgdata->password);
113 if (plgdata->gcal_sink)
114 osync_objtype_sink_unref(plgdata->gcal_sink);
115 if (plgdata->gcal_format)
116 osync_objformat_unref(plgdata->gcal_format);
117 g_free(plgdata);
120 /** Run gchelper and return the file descriptors for its stdin/stdout
123 osync_bool run_helper(struct gc_plgdata *plgdata, const char *operation,
124 const char *arg, int *in, int *out, pid_t *ppid,
125 OSyncError **error)
128 osync_bool result = FALSE;
129 /* TODO: add calls to libgcal */
130 exit:
131 return result;
134 static void gc_connect(void *data, OSyncPluginInfo *info, OSyncContext *ctx)
136 osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, data, info, ctx);
137 static int counter = 0;
138 int result;
139 struct gc_plgdata *plgdata = data;
140 OSyncObjTypeSink *sink = osync_plugin_info_get_sink(info);
141 OSyncError *error = NULL;
142 char buffer[512];
144 if ((plgdata->calendar) && (counter == 0)) {
145 result = gcal_get_authentication(plgdata->calendar, plgdata->username,
146 plgdata->password);
147 ++counter;
148 if (result == -1)
149 goto error;
151 snprintf(buffer, sizeof(buffer) - 1, "%s/gcal2osync.xslt",
152 plgdata->xslt_path);
153 if ((result = xslt_initialize(plgdata->xslt_ctx_gcal, buffer)))
154 goto error;
155 osync_trace(TRACE_INTERNAL, "\ndone calendar: %s\n", buffer);
158 if (((plgdata->contacts) && (counter == 1)) ||
159 ((plgdata->gcont_sink) && (!plgdata->gcal_sink))) {
160 result = gcal_get_authentication(plgdata->contacts, plgdata->username,
161 plgdata->password);
162 counter++;
163 if (result == -1)
164 goto error;
166 snprintf(buffer, sizeof(buffer) - 1, "%s/gcont2osync.xslt",
167 plgdata->xslt_path);
168 if ((result = xslt_initialize(plgdata->xslt_ctx_gcont, buffer)))
169 goto error;
170 osync_trace(TRACE_INTERNAL, "\ndone contact: %s\n", buffer);
173 osync_context_report_success(ctx);
174 osync_trace(TRACE_EXIT, "%s", __func__);
175 return;
177 error:
178 osync_trace(TRACE_INTERNAL, "\nGood bye, cruel world...\n");
179 osync_context_report_osyncerror(ctx, &error);
182 static void gc_get_changes(void *data, OSyncPluginInfo *info, OSyncContext *ctx)
184 osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, data, info, ctx);
185 char buffer[512];
186 static int counter = 0;
187 struct gc_plgdata *plgdata = data;
188 char slow_sync_flag = 0;
189 OSyncObjTypeSink *sink = osync_plugin_info_get_sink(info);
190 OSyncError *error = NULL;
191 OSyncXMLFormat *xmlformat;
192 OSyncData *odata = NULL;
193 OSyncChange *chg = NULL;
194 int result = 0, i;
195 char *timestamp = NULL, *msg, *raw_xml = NULL;
196 gcal_event event;
197 gcal_contact contact;
199 timestamp = osync_anchor_retrieve(plgdata->gcal_anchor_path, "gcalendar");
200 if (timestamp)
201 osync_trace(TRACE_INTERNAL, "timestamp is: %s\n", timestamp);
202 else
203 osync_trace(TRACE_INTERNAL, "first sync!\n");
205 if ((plgdata->gcal_sink) && (counter == 0)) {
206 if (osync_objtype_sink_get_slowsync(plgdata->gcal_sink) || !timestamp) {
207 osync_trace(TRACE_INTERNAL, "\n\t\tgcal: Client asked for slow syncing...\n");
208 slow_sync_flag = 1;
209 result = gcal_get_events(plgdata->calendar, &(plgdata->all_events));
211 } else {
212 osync_trace(TRACE_INTERNAL, "\n\t\tgcal: Client asked for fast syncing...\n");
213 result = gcal_get_updated_events(plgdata->calendar,
214 &(plgdata->all_events),
215 timestamp);
218 if (result) {
219 msg = "Failed getting events!";
220 goto error;
223 /* Calendar returns most recently updated event as first element */
224 event = gcal_event_element(&(plgdata->all_events), 0);
225 if (!event)
226 goto error;
227 plgdata->cont_timestamp = strdup(gcal_event_get_updated(event));
228 if (!plgdata->cont_timestamp) {
229 msg = "Failed copying event timestamp!\n";
230 goto error;
233 osync_trace(TRACE_INTERNAL, "\tgot then all!\n");
234 for (i = 0; i < plgdata->all_events.length; ++i) {
235 event = gcal_event_element(&(plgdata->all_events), i);
236 if (!event)
237 goto error;
239 raw_xml = gcal_event_get_xml(event);
240 if ((result = xslt_transform(plgdata->xslt_ctx_gcal,
241 raw_xml)))
242 goto error;
244 raw_xml = plgdata->xslt_ctx_gcal->xml_str;
245 xmlformat = osync_xmlformat_parse(raw_xml,
246 strlen(raw_xml),
247 &error);
248 if (!xmlformat)
249 goto error;
251 osync_xmlformat_sort(xmlformat);
252 odata = osync_data_new((char *)xmlformat,
253 osync_xmlformat_size(),
254 plgdata->gcal_format, &error);
255 if (!odata)
256 goto cleanup;
258 if (!(chg = osync_change_new(&error)))
259 goto cleanup;
260 osync_data_set_objtype(odata, osync_objtype_sink_get_name(plgdata->gcal_sink));
261 osync_change_set_data(chg, odata);
262 osync_data_unref(odata);
264 osync_change_set_uid(chg, gcal_event_get_id(event));
266 if (slow_sync_flag)
267 osync_change_set_changetype(chg, OSYNC_CHANGE_TYPE_ADDED);
268 else
269 if (gcal_event_is_deleted(event))
270 osync_change_set_changetype(chg, OSYNC_CHANGE_TYPE_DELETED);
271 else
272 osync_change_set_changetype(chg, OSYNC_CHANGE_TYPE_MODIFIED);
274 osync_context_report_change(ctx, chg);
275 osync_change_unref(chg);
278 /* Load XSLT style to convert osync xmlformat-event --> gdata */
279 snprintf(buffer, sizeof(buffer) - 1, "%s/osync2gcal.xslt",
280 plgdata->xslt_path);
281 if ((result = xslt_initialize(plgdata->xslt_ctx_gcal, buffer)))
282 goto error;
283 osync_trace(TRACE_INTERNAL, "\ndone calendar: %s\n", buffer);
287 slow_sync_flag = 0;
289 timestamp = osync_anchor_retrieve(plgdata->gcal_anchor_path, "gcontact");
290 if (((plgdata->gcont_sink) && (counter == 1)) ||
291 ((plgdata->gcont_sink) && (!plgdata->gcal_sink))) {
292 if (osync_objtype_sink_get_slowsync(plgdata->gcont_sink) || !timestamp) {
293 osync_trace(TRACE_INTERNAL, "\n\t\tgcont: Client asked for slow syncing...\n");
294 slow_sync_flag = 1;
295 result = gcal_get_contacts(plgdata->contacts, &(plgdata->all_contacts));
297 } else {
298 osync_trace(TRACE_INTERNAL, "\n\t\tgcont: Client asked for fast syncing...\n");
299 result = gcal_get_updated_contacts(plgdata->contacts,
300 &(plgdata->all_contacts),
301 timestamp);
305 if (result) {
306 msg = "Failed getting contacts!";
307 goto error;
310 /* Contacts returns most recently updated event as last element */
311 contact = gcal_contact_element(&(plgdata->all_contacts),
312 (plgdata->all_contacts.length - 1));
313 if (!contact)
314 goto error;
315 plgdata->cont_timestamp = strdup(gcal_contact_get_updated(contact));
316 if (!plgdata->cont_timestamp) {
317 msg = "Failed copying contact timestamp!\n";
318 goto error;
321 osync_trace(TRACE_INTERNAL, "\tgot then all!\n");
322 for (i = 0; i < plgdata->all_contacts.length; ++i) {
323 contact = gcal_contact_element(&(plgdata->all_contacts), i);
324 if (!contact)
325 goto error;
327 raw_xml = gcal_contact_get_xml(contact);
328 if ((result = xslt_transform(plgdata->xslt_ctx_gcont,
329 raw_xml)))
330 goto error;
331 raw_xml = plgdata->xslt_ctx_gcal->xml_str;
332 xmlformat = osync_xmlformat_parse(raw_xml,
333 strlen(raw_xml),
334 &error);
335 if (!xmlformat)
336 goto error;
338 osync_xmlformat_sort(xmlformat);
339 odata = osync_data_new((char *)xmlformat,
340 osync_xmlformat_size(),
341 plgdata->gcont_format, &error);
342 if (!odata)
343 goto cleanup;
345 if (!(chg = osync_change_new(&error)))
346 goto cleanup;
347 osync_data_set_objtype(odata, osync_objtype_sink_get_name(plgdata->gcont_sink));
348 osync_change_set_data(chg, odata);
349 osync_data_unref(odata);
351 osync_change_set_uid(chg, gcal_contact_get_id(contact));
353 if (slow_sync_flag)
354 osync_change_set_changetype(chg, OSYNC_CHANGE_TYPE_ADDED);
355 else
356 if (gcal_contact_is_deleted(contact))
357 osync_change_set_changetype(chg, OSYNC_CHANGE_TYPE_DELETED);
358 else
359 osync_change_set_changetype(chg, OSYNC_CHANGE_TYPE_MODIFIED);
361 osync_context_report_change(ctx, chg);
362 osync_change_unref(chg);
365 /* Load XSLT style to convert osync xmlformat-contact --> gdata */
366 snprintf(buffer, sizeof(buffer) - 1, "%s/osync2gcont.xslt",
367 plgdata->xslt_path);
368 if ((result = xslt_initialize(plgdata->xslt_ctx_gcont, buffer)))
369 goto error;
370 osync_trace(TRACE_INTERNAL, "\ndone contact: %s\n", buffer);
374 exit:
375 ++counter;
376 osync_context_report_success(ctx);
377 return;
379 cleanup:
380 osync_error_unref(&error);
381 osync_xmlformat_unref(&xmlformat);
383 error:
384 ++counter;
385 osync_context_report_error(ctx, OSYNC_ERROR_GENERIC, msg);
388 static void gc_commit_change_calendar(void *data, OSyncPluginInfo *info,
389 OSyncContext *ctx, OSyncChange *change)
391 osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, data, info, ctx, change);
392 osync_trace(TRACE_INTERNAL, "hello, from calendar!\n");
393 OSyncObjTypeSink *sink = osync_plugin_info_get_sink(info);
394 struct gc_plgdata *plgdata = data;
395 gcal_event event = NULL;
397 int size, result;
398 char *osync_xml = NULL, *msg = NULL, *raw_xml = NULL, *updated_event = NULL;
399 OSyncData *odata = NULL;
401 if (!(odata = osync_change_get_data(change))) {
402 msg = "Cannot get raw data from change obj!\n";
403 goto error;
406 osync_data_get_data(odata, &osync_xml, &size);
407 if (!osync_xml) {
408 msg = "Failed getting xml from change obj!\n";
409 goto error;
412 /* Convert to gdata format */
413 if ((result = xslt_transform(plgdata->xslt_ctx_gcal, osync_xml))) {
414 msg = "Failed converting from osync xmlevent to gcalendar\n";
415 goto error;
417 raw_xml = plgdata->xslt_ctx_gcal->xml_str;
419 switch (osync_change_get_changetype(change)) {
420 case OSYNC_CHANGE_TYPE_ADDED:
421 result = gcal_add_xmlentry(plgdata->calendar, raw_xml, &updated_event);
422 if (result == -1) {
423 msg = "Failed adding new event!\n";
424 goto error;
427 if (!(event = gcal_event_new(updated_event))) {
428 msg = "Failed recovering updated fields!\n";
429 goto error;
431 /* TODO: inform back the id/edit_url/last_updated */
432 break;
434 case OSYNC_CHANGE_TYPE_MODIFIED:
435 result = gcal_update_xmlentry(plgdata->calendar, raw_xml, &updated_event,
436 NULL);
437 if (result == -1) {
438 msg = "Failed editing event!\n";
439 goto error;
442 if (!(event = gcal_event_new(updated_event))) {
443 msg = "Failed recovering updated fields!\n";
444 goto error;
446 /* TODO: inform back the edit_url/last_updated */
447 break;
449 case OSYNC_CHANGE_TYPE_DELETED:
450 result = gcal_erase_xmlentry(plgdata->calendar, raw_xml);
451 if (result == -1) {
452 msg = "Failed deleting event!\n";
453 goto error;
455 break;
457 default:
458 osync_context_report_error(ctx, OSYNC_ERROR_NOT_SUPPORTED,
459 "Unknown change type");
460 goto error;
461 break;
464 if (osync_xml)
465 g_free(osync_xml);
467 if (updated_event)
468 free(updated_event);
470 if (event)
471 gcal_event_delete(event);
473 osync_context_report_success(ctx);
475 osync_trace(TRACE_EXIT, "%s", __func__);
477 return;
478 error:
479 osync_context_report_error(ctx, OSYNC_ERROR_GENERIC, msg);
482 static void gc_commit_change_contact(void *data, OSyncPluginInfo *info,
483 OSyncContext *ctx, OSyncChange *change)
485 osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, data, info, ctx, change);
486 osync_trace(TRACE_INTERNAL, "hello, from contacts!\n");
488 OSyncObjTypeSink *sink = osync_plugin_info_get_sink(info);
489 struct gc_plgdata *plgdata = data;
490 gcal_contact contact = NULL;
491 int size, result;
492 char *osync_xml = NULL, *msg = NULL, *raw_xml = NULL, *updated_contact = NULL;
493 OSyncData *odata = NULL;
495 if (!(odata = osync_change_get_data(change))) {
496 msg = "Cannot get raw data from change obj!\n";
497 goto error;
500 osync_data_get_data(odata, &osync_xml, &size);
501 if (!osync_xml) {
502 msg = "Failed getting xml from change obj!\n";
503 goto error;
506 /* Convert to gdata format */
507 if ((result = xslt_transform(plgdata->xslt_ctx_gcont, osync_xml))) {
508 msg = "Failed converting from osync xmlcontact to gcontact\n";
509 goto error;
511 raw_xml = plgdata->xslt_ctx_gcal->xml_str;
513 switch (osync_change_get_changetype(change)) {
514 case OSYNC_CHANGE_TYPE_ADDED:
515 result = gcal_add_xmlentry(plgdata->contacts, raw_xml, &updated_contact);
516 if (result == -1) {
517 msg = "Failed adding new contact!\n";
518 goto error;
521 if (!(contact = gcal_contact_new(updated_contact))) {
522 msg = "Failed recovering updated fields!\n";
523 goto error;
525 /* TODO: inform back the id/edit_url/last_updated */
526 break;
528 case OSYNC_CHANGE_TYPE_MODIFIED:
529 result = gcal_update_xmlentry(plgdata->contacts, raw_xml, &updated_contact,
530 NULL);
531 if (result == -1) {
532 msg = "Failed editing event!\n";
533 goto error;
536 if (!(contact = gcal_contact_new(updated_contact))) {
537 msg = "Failed recovering updated fields!\n";
538 goto error;
540 /* TODO: inform back the id/edit_url/last_updated */
541 break;
543 case OSYNC_CHANGE_TYPE_DELETED:
544 result = gcal_erase_xmlentry(plgdata->contacts, raw_xml);
545 if (result == -1) {
546 msg = "Failed deleting event!\n";
547 goto error;
549 break;
551 default:
552 osync_context_report_error(ctx, OSYNC_ERROR_NOT_SUPPORTED,
553 "Unknown change type");
554 goto error;
555 break;
558 if (osync_xml)
559 g_free(osync_xml);
561 if (updated_contact)
562 free(updated_contact);
564 if (contact)
565 free(contact);
567 osync_context_report_success(ctx);
568 osync_trace(TRACE_EXIT, "%s", __func__);
569 return;
571 error:
572 osync_context_report_error(ctx, OSYNC_ERROR_GENERIC, msg);
576 static void gc_sync_done(void *data, OSyncPluginInfo *info, OSyncContext *ctx)
578 osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, data, info, ctx);
579 struct gc_plgdata *plgdata = NULL;
580 int result;
582 plgdata = data;
583 osync_anchor_update(plgdata->gcal_anchor_path, "gcalendar", plgdata->cal_timestamp);
584 osync_anchor_update(plgdata->gcont_anchor_path, "gcontact", plgdata->cont_timestamp);
587 static void gc_disconnect(void *data, OSyncPluginInfo *info, OSyncContext *ctx)
589 osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, data, info, ctx);
590 struct gc_plgdata *plgdata = data;
592 osync_context_report_success(ctx);
593 osync_trace(TRACE_EXIT, "%s", __func__);
596 static void gc_finalize(void *data)
598 osync_trace(TRACE_ENTRY, "%s(%p)", __func__, data);
599 struct gc_plgdata *plgdata = data;
601 free_plg(plgdata);
602 osync_trace(TRACE_EXIT, "%s", __func__);
605 static void *gc_initialize(OSyncPlugin *plugin,
606 OSyncPluginInfo *info,
607 OSyncError **error)
609 osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, plugin, info, error);
610 struct gc_plgdata *plgdata;
611 OSyncPluginConfig *config;
612 OSyncPluginAuthentication *auth;
613 OSyncPluginAdvancedOption *advanced;
614 OSyncList *resources;
615 OSyncList *r;
616 const char *objtype, *tmp;
617 int i, numobjs;
619 plgdata = osync_try_malloc0(sizeof(struct gc_plgdata), error);
620 config = osync_plugin_info_get_config(info);
621 if ((!plgdata) || (!config)) {
622 osync_error_set(error, OSYNC_ERROR_GENERIC,
623 "Unable to get config data.");
624 goto error_freeplg;
627 advanced = osync_plugin_config_get_advancedoption_value_by_name(config, "xslt");
628 if (!advanced) {
629 osync_trace(TRACE_INTERNAL, "Cannot locate xslt config!\n");
630 goto error_freeplg;
633 if (!(plgdata->xslt_path = strdup(osync_plugin_advancedoption_get_value(advanced))))
634 goto error_freeplg;
636 resources = osync_plugin_config_get_resources(config);
637 numobjs = osync_plugin_info_num_objtypes(info);
639 for (i = 1, r = resources; r; r = r->next, i++) {
640 osync_trace(TRACE_INTERNAL, "field: %s\n", osync_plugin_resource_get_objtype(r->data));
641 if (!(strcmp(osync_plugin_resource_get_objtype(r->data), "event")))
642 if (!(plgdata->calendar = gcal_new(GCALENDAR)))
643 goto error_freeplg;
644 else {
645 osync_trace(TRACE_INTERNAL, "\tcreated calendar obj!\n");
646 gcal_set_store_xml(plgdata->calendar, 1);
649 if (!(strcmp(osync_plugin_resource_get_objtype(r->data), "contact")))
650 if (!(plgdata->contacts = gcal_new(GCONTACT)))
651 goto error_freeplg;
652 else {
653 osync_trace(TRACE_INTERNAL, "\tcreated contact obj!\n");
654 gcal_set_store_xml(plgdata->contacts, 1);
660 /* TODO: how works resource policy? For while, copy everything... */
661 for (i = 0; i < numobjs; i++) {
663 if (!plgdata->username) {
664 auth = osync_plugin_config_get_authentication(config);
665 tmp = osync_plugin_authentication_get_username(auth);
666 if (!tmp)
667 goto error_freeplg;
668 else
669 if (!(plgdata->username = strdup(tmp)))
670 goto error_freeplg;
674 if (!plgdata->password) {
675 tmp = osync_plugin_authentication_get_password(auth);
676 if (!tmp)
677 goto error_freeplg;
678 else
679 if (!(plgdata->password = strdup(tmp)))
680 goto error_freeplg;
683 /* TODO: get proxy/calendar title/resources/etc */
687 OSyncObjTypeSinkFunctions functions_gcal;
688 memset(&functions_gcal, 0, sizeof(functions_gcal));
689 functions_gcal.connect = gc_connect;
690 functions_gcal.get_changes = gc_get_changes;
691 functions_gcal.commit = gc_commit_change_calendar;
692 functions_gcal.disconnect = gc_disconnect;
693 functions_gcal.sync_done = gc_sync_done;
696 if (plgdata->calendar) {
697 osync_trace(TRACE_INTERNAL, "\tcreating calendar sink...\n");
698 OSyncFormatEnv *formatenv1 = osync_plugin_info_get_format_env(info);
699 plgdata->gcal_format = osync_format_env_find_objformat(formatenv1, "xmlformat-event");
700 if (!plgdata->gcal_format)
701 goto error_freeplg;
702 osync_objformat_ref(plgdata->gcal_format);
704 plgdata->gcal_sink = osync_plugin_info_find_objtype(info, "event");
705 if (!plgdata->gcal_sink)
706 goto error_freeplg;
708 osync_objtype_sink_set_functions(plgdata->gcal_sink, functions_gcal, plgdata);
709 osync_plugin_info_add_objtype(info, plgdata->gcal_sink);
713 OSyncObjTypeSinkFunctions functions_gcont;
714 memset(&functions_gcont, 0, sizeof(functions_gcont));
715 functions_gcont.connect = gc_connect;
716 functions_gcont.get_changes = gc_get_changes;
717 functions_gcont.commit = gc_commit_change_contact;
718 functions_gcont.disconnect = gc_disconnect;
719 functions_gcont.sync_done = gc_sync_done;
721 if (plgdata->contacts) {
722 osync_trace(TRACE_INTERNAL, "\tcreating contact sink...\n");
723 OSyncFormatEnv *formatenv2 = osync_plugin_info_get_format_env(info);
724 plgdata->gcont_format = osync_format_env_find_objformat(formatenv2, "xmlformat-contact");
725 if (!plgdata->gcont_format)
726 goto error_freeplg;
727 osync_objformat_ref(plgdata->gcont_format);
729 plgdata->gcont_sink = osync_plugin_info_find_objtype(info, "contact");
730 if (!plgdata->gcont_sink)
731 goto error_freeplg;
733 osync_objtype_sink_set_functions(plgdata->gcont_sink, functions_gcont, plgdata);
734 osync_plugin_info_add_objtype(info, plgdata->gcont_sink);
739 plgdata->gcal_anchor_path = g_strdup_printf("%s/calendar_anchor.db",
740 osync_plugin_info_get_configdir(info));
741 if (!(plgdata->gcal_anchor_path))
742 goto error_freeplg;
743 else
744 osync_trace(TRACE_INTERNAL, "\tanchor: %s\n", plgdata->gcal_anchor_path);
746 plgdata->gcont_anchor_path = g_strdup_printf("%s/contact_anchor.db",
747 osync_plugin_info_get_configdir(info));
748 if (!(plgdata->gcont_anchor_path))
749 goto error_freeplg;
750 else
751 osync_trace(TRACE_INTERNAL, "\tanchor: %s\n", plgdata->gcont_anchor_path);
753 if (plgdata->calendar)
754 if (!(plgdata->xslt_ctx_gcal = xslt_new()))
755 goto error_freeplg;
756 else
757 osync_trace(TRACE_INTERNAL, "\tsucceed creating xslt_gcal!\n");
759 if (plgdata->contacts)
760 if (!(plgdata->xslt_ctx_gcont = xslt_new()))
761 goto error_freeplg;
762 else
763 osync_trace(TRACE_INTERNAL, "\tsucceed creating xslt_gcont!\n");
765 osync_trace(TRACE_EXIT, "%s", __func__);
767 return plgdata;
769 error_freeplg:
770 if (plgdata)
771 free_plg(plgdata);
772 out:
773 osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error));
774 return NULL;
777 static osync_bool gc_discover(void *data, OSyncPluginInfo *info, OSyncError **error)
779 osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, data, info, error);
781 struct gc_plgdata *plgdata = data;
783 if (plgdata->calendar)
784 osync_objtype_sink_set_available(plgdata->gcal_sink, TRUE);
785 if (plgdata->contacts)
786 osync_objtype_sink_set_available(plgdata->gcont_sink, TRUE);
788 OSyncVersion *version = osync_version_new(error);
789 osync_version_set_plugin(version, "google-data");
790 osync_plugin_info_set_version(info, version);
791 osync_version_unref(version);
793 osync_trace(TRACE_EXIT, "%s", __func__);
794 return TRUE;
797 osync_bool get_sync_info(OSyncPluginEnv *env, OSyncError **error)
799 osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, env, error);
800 OSyncPlugin *plugin = osync_plugin_new(error);
801 if (!plugin)
802 goto error;
804 osync_plugin_set_name(plugin, "google-data");
805 osync_plugin_set_longname(plugin, "Google calendar/plugin");
806 osync_plugin_set_description(plugin, "Google calendar and contacts plugin");
808 osync_plugin_set_initialize(plugin, gc_initialize);
809 osync_plugin_set_finalize(plugin, gc_finalize);
810 osync_plugin_set_discover(plugin, gc_discover);
812 osync_plugin_env_register_plugin(env, plugin);
813 osync_plugin_unref(plugin);
815 osync_trace(TRACE_EXIT, "%s", __func__);
816 return TRUE;
818 error:
819 osync_trace(TRACE_EXIT_ERROR, "Unable to register: %s", osync_error_print(error));
820 osync_error_unref(error);
821 return FALSE;
824 int get_version(void)
826 return 1;