Printing converted data to trace logs (instead of terminal). This plugin
[gdataplugin.git] / src / gcalendar.c
blobffb1538d86248c37b65c1a17355758ab91717e36
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 * - 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 #include <opensync/opensync.h>
30 #include <opensync/opensync-plugin.h>
31 #include <opensync/opensync-helper.h>
32 #include <opensync/opensync-merger.h>
33 #include <opensync/opensync-format.h>
34 #include <opensync/opensync-data.h>
35 #include <opensync/opensync-version.h>
37 #include <glib.h>
39 #include <libxml/tree.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <sys/types.h>
45 #include <signal.h>
46 #include <sys/wait.h>
47 #include <gcal_status.h>
48 #include <gcalendar.h>
49 #include <gcontact.h>
50 #include "xslt_aux.h"
52 struct gc_plgdata
54 char *url;
55 char *username;
56 char *password;
57 char *gcal_anchor_path;
58 char *gcont_anchor_path;
59 char *timezone;
60 char *xslt_path;
61 /* libgcal resources */
62 char *cal_timestamp;
63 char *cont_timestamp;
64 gcal_t calendar;
65 gcal_t contacts;
66 struct gcal_event_array all_events;
67 struct gcal_contact_array all_contacts;
68 /* calendar sink/format */
69 OSyncObjTypeSink *gcal_sink;
70 OSyncObjFormat *gcal_format;
71 /* contact sink/format */
72 OSyncObjTypeSink *gcont_sink;
73 OSyncObjFormat *gcont_format;
74 /* XSLT context resource struct */
75 struct xslt_resources *xslt_ctx_gcal;
76 struct xslt_resources *xslt_ctx_gcont;
79 static void free_plg(struct gc_plgdata *plgdata)
81 if (plgdata->calendar) {
82 gcal_delete(plgdata->calendar);
83 gcal_cleanup_events(&(plgdata->all_events));
85 if (plgdata->contacts) {
86 gcal_delete(plgdata->contacts);
87 gcal_cleanup_contacts(&(plgdata->all_contacts));
90 if (plgdata->gcal_anchor_path)
91 free(plgdata->gcal_anchor_path);
92 if (plgdata->gcont_anchor_path)
93 free(plgdata->gcont_anchor_path);
94 if (plgdata->xslt_path)
95 free(plgdata->xslt_path);
96 if (plgdata->xslt_ctx_gcal)
97 xslt_delete(plgdata->xslt_ctx_gcal);
98 if (plgdata->xslt_ctx_gcont)
99 xslt_delete(plgdata->xslt_ctx_gcont);
100 if (plgdata->cal_timestamp)
101 free(plgdata->cal_timestamp);
102 if (plgdata->cont_timestamp)
103 free(plgdata->cont_timestamp);
104 if (plgdata->timezone)
105 free(plgdata->timezone);
106 if (plgdata->url)
107 xmlFree(plgdata->url);
108 if (plgdata->username)
109 xmlFree(plgdata->username);
110 if (plgdata->password)
111 xmlFree(plgdata->password);
112 if (plgdata->gcal_sink)
113 osync_objtype_sink_unref(plgdata->gcal_sink);
114 if (plgdata->gcal_format)
115 osync_objformat_unref(plgdata->gcal_format);
116 g_free(plgdata);
119 static void gc_connect(void *data, OSyncPluginInfo *info, OSyncContext *ctx)
121 osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, data, info, ctx);
122 static int counter = 0;
123 int result;
124 struct gc_plgdata *plgdata = data;
125 OSyncObjTypeSink *sink = osync_plugin_info_get_sink(info);
126 OSyncError *error = NULL;
127 char buffer[512];
129 if ((plgdata->calendar) && (counter == 0)) {
130 result = gcal_get_authentication(plgdata->calendar, plgdata->username,
131 plgdata->password);
132 ++counter;
133 if (result == -1)
134 goto error;
136 snprintf(buffer, sizeof(buffer) - 1, "%s/gcal2osync.xslt",
137 plgdata->xslt_path);
138 if ((result = xslt_initialize(plgdata->xslt_ctx_gcal, buffer)))
139 goto error;
140 osync_trace(TRACE_INTERNAL, "\ndone calendar: %s\n", buffer);
143 if (((plgdata->contacts) && (counter == 1)) ||
144 ((plgdata->gcont_sink) && (!plgdata->gcal_sink))) {
145 result = gcal_get_authentication(plgdata->contacts, plgdata->username,
146 plgdata->password);
147 counter++;
148 if (result == -1)
149 goto error;
151 snprintf(buffer, sizeof(buffer) - 1, "%s/gcont2osync.xslt",
152 plgdata->xslt_path);
153 if ((result = xslt_initialize(plgdata->xslt_ctx_gcont, buffer)))
154 goto error;
155 osync_trace(TRACE_INTERNAL, "\ndone contact: %s\n", buffer);
158 osync_context_report_success(ctx);
159 osync_trace(TRACE_EXIT, "%s", __func__);
160 return;
162 error:
163 osync_trace(TRACE_INTERNAL, "\nGood bye, cruel world...\n");
164 osync_context_report_osyncerror(ctx, &error);
167 static void gc_get_changes_calendar(void *data, OSyncPluginInfo *info, OSyncContext *ctx)
169 osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, data, info, ctx);
170 char buffer[512];
171 static int counter = 0;
172 struct gc_plgdata *plgdata = data;
173 char slow_sync_flag = 0;
174 OSyncObjTypeSink *sink = osync_plugin_info_get_sink(info);
175 OSyncError *error = NULL;
176 OSyncXMLFormat *xmlformat;
177 OSyncData *odata = NULL;
178 OSyncChange *chg = NULL;
179 int result = 0, i;
180 char *timestamp = NULL, *msg, *raw_xml = NULL;
181 gcal_event event;
183 if (!plgdata->gcal_sink)
184 return;
185 timestamp = osync_anchor_retrieve(plgdata->gcal_anchor_path, "gcalendar");
186 if (timestamp)
187 osync_trace(TRACE_INTERNAL, "timestamp is: %s\n", timestamp);
188 else
189 osync_trace(TRACE_INTERNAL, "first sync!\n");
191 if (osync_objtype_sink_get_slowsync(plgdata->gcal_sink) || !timestamp) {
192 osync_trace(TRACE_INTERNAL, "\n\t\tgcal: Client asked for slow syncing...\n");
193 slow_sync_flag = 1;
194 result = gcal_get_events(plgdata->calendar, &(plgdata->all_events));
196 } else {
197 osync_trace(TRACE_INTERNAL, "\n\t\tgcal: Client asked for fast syncing...\n");
198 result = gcal_get_updated_events(plgdata->calendar,
199 &(plgdata->all_events),
200 timestamp);
203 if (result) {
204 msg = "Failed getting events!";
205 goto error;
208 /* Calendar returns most recently updated event as first element */
209 event = gcal_event_element(&(plgdata->all_events), 0);
210 if (!event)
211 goto error;
212 plgdata->cont_timestamp = strdup(gcal_event_get_updated(event));
213 if (!plgdata->cont_timestamp) {
214 msg = "Failed copying event timestamp!\n";
215 goto error;
218 osync_trace(TRACE_INTERNAL, "gcalendar: got then all!\n");
219 for (i = 0; i < plgdata->all_events.length; ++i) {
220 event = gcal_event_element(&(plgdata->all_events), i);
221 if (!event)
222 goto error;
224 raw_xml = gcal_event_get_xml(event);
225 if ((result = xslt_transform(plgdata->xslt_ctx_gcal,
226 raw_xml)))
227 goto error;
229 raw_xml = plgdata->xslt_ctx_gcal->xml_str;
230 xmlformat = osync_xmlformat_parse(raw_xml,
231 strlen(raw_xml),
232 &error);
233 if (!xmlformat)
234 goto error;
236 osync_trace(TRACE_INTERNAL, "gevent: %s\nosync: %s\n",
237 gcal_event_get_xml(event), raw_xml);
239 osync_xmlformat_sort(xmlformat);
240 odata = osync_data_new(xmlformat,
241 osync_xmlformat_size(),
242 plgdata->gcal_format, &error);
243 if (!odata)
244 goto cleanup;
246 if (!(chg = osync_change_new(&error)))
247 goto cleanup;
248 osync_data_set_objtype(odata, osync_objtype_sink_get_name(plgdata->gcal_sink));
249 osync_change_set_data(chg, odata);
250 osync_data_unref(odata);
252 osync_change_set_uid(chg, gcal_event_get_url(event));
254 if (slow_sync_flag)
255 osync_change_set_changetype(chg, OSYNC_CHANGE_TYPE_ADDED);
256 else
257 if (gcal_event_is_deleted(event))
258 osync_change_set_changetype(chg, OSYNC_CHANGE_TYPE_DELETED);
259 else
260 osync_change_set_changetype(chg, OSYNC_CHANGE_TYPE_MODIFIED);
262 osync_context_report_change(ctx, chg);
263 osync_change_unref(chg);
266 /* Load XSLT style to convert osync xmlformat-event --> gdata */
267 snprintf(buffer, sizeof(buffer) - 1, "%s/osync2gcal.xslt",
268 plgdata->xslt_path);
269 if ((result = xslt_initialize(plgdata->xslt_ctx_gcal, buffer)))
270 goto error;
271 osync_trace(TRACE_INTERNAL, "\ndone calendar: %s\n", buffer);
274 exit:
275 osync_context_report_success(ctx);
276 return;
278 cleanup:
279 osync_error_unref(&error);
280 osync_xmlformat_unref(&xmlformat);
282 error:
283 osync_context_report_error(ctx, OSYNC_ERROR_GENERIC, msg);
288 static void gc_get_changes_contact(void *data, OSyncPluginInfo *info, OSyncContext *ctx)
290 osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, data, info, ctx);
291 char buffer[512];
292 static int counter = 0;
293 struct gc_plgdata *plgdata = data;
294 char slow_sync_flag = 0;
295 OSyncObjTypeSink *sink = osync_plugin_info_get_sink(info);
296 OSyncError *error = NULL;
297 OSyncXMLFormat *xmlformat;
298 OSyncData *odata = NULL;
299 OSyncChange *chg = NULL;
300 int result = 0, i;
301 char *timestamp = NULL, *msg, *raw_xml = NULL;
302 gcal_contact contact;
303 slow_sync_flag = 0;
305 if (!plgdata->gcont_sink)
306 return;
307 timestamp = osync_anchor_retrieve(plgdata->gcal_anchor_path, "gcontact");
308 if (osync_objtype_sink_get_slowsync(plgdata->gcont_sink) || !timestamp) {
309 osync_trace(TRACE_INTERNAL, "\n\t\tgcont: Client asked for slow syncing...\n");
310 slow_sync_flag = 1;
311 result = gcal_get_contacts(plgdata->contacts, &(plgdata->all_contacts));
313 } else {
314 osync_trace(TRACE_INTERNAL, "\n\t\tgcont: Client asked for fast syncing...\n");
315 result = gcal_get_updated_contacts(plgdata->contacts,
316 &(plgdata->all_contacts),
317 timestamp);
320 if (result) {
321 msg = "Failed getting contacts!";
322 goto error;
325 /* Contacts returns most recently updated entry as last element */
326 contact = gcal_contact_element(&(plgdata->all_contacts),
327 (plgdata->all_contacts.length - 1));
328 if (!contact)
329 goto error;
330 plgdata->cont_timestamp = strdup(gcal_contact_get_updated(contact));
331 if (!plgdata->cont_timestamp) {
332 msg = "Failed copying contact timestamp!\n";
333 goto error;
336 osync_trace(TRACE_INTERNAL, "gcontact: got then all!\n");
337 for (i = 0; i < plgdata->all_contacts.length; ++i) {
338 contact = gcal_contact_element(&(plgdata->all_contacts), i);
339 if (!contact)
340 goto error;
342 raw_xml = gcal_contact_get_xml(contact);
343 if ((result = xslt_transform(plgdata->xslt_ctx_gcont,
344 raw_xml)))
345 goto error;
346 raw_xml = plgdata->xslt_ctx_gcont->xml_str;
347 xmlformat = osync_xmlformat_parse(raw_xml,
348 strlen(raw_xml),
349 &error);
350 if (!xmlformat)
351 goto error;
353 osync_trace(TRACE_INTERNAL, "gcont: %s\nosync: %s\n",
354 gcal_contact_get_xml(contact), raw_xml);
356 osync_xmlformat_sort(xmlformat);
358 odata = osync_data_new(xmlformat,
359 osync_xmlformat_size(),
360 plgdata->gcont_format, &error);
362 if (!odata)
363 goto cleanup;
365 if (!(chg = osync_change_new(&error)))
366 goto cleanup;
367 osync_data_set_objtype(odata, osync_objtype_sink_get_name(plgdata->gcont_sink));
368 osync_change_set_data(chg, odata);
369 osync_data_unref(odata);
371 osync_change_set_uid(chg, gcal_contact_get_url(contact));
373 if (slow_sync_flag)
374 osync_change_set_changetype(chg, OSYNC_CHANGE_TYPE_ADDED);
375 else
376 if (gcal_contact_is_deleted(contact))
377 osync_change_set_changetype(chg, OSYNC_CHANGE_TYPE_DELETED);
378 else
379 osync_change_set_changetype(chg, OSYNC_CHANGE_TYPE_MODIFIED);
381 osync_context_report_change(ctx, chg);
382 osync_change_unref(chg);
385 /* Load XSLT style to convert osync xmlformat-contact --> gdata */
386 snprintf(buffer, sizeof(buffer) - 1, "%s/osync2gcont.xslt",
387 plgdata->xslt_path);
388 if ((result = xslt_initialize(plgdata->xslt_ctx_gcont, buffer)))
389 goto error;
390 osync_trace(TRACE_INTERNAL, "\ndone contact: %s\n", buffer);
393 exit:
394 osync_context_report_success(ctx);
395 return;
397 cleanup:
398 osync_error_unref(&error);
399 osync_xmlformat_unref(&xmlformat);
401 error:
402 osync_context_report_error(ctx, OSYNC_ERROR_GENERIC, msg);
405 static void gc_commit_change_calendar(void *data, OSyncPluginInfo *info,
406 OSyncContext *ctx, OSyncChange *change)
408 osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, data, info, ctx, change);
409 osync_trace(TRACE_INTERNAL, "hello, from calendar!\n");
410 OSyncObjTypeSink *sink = osync_plugin_info_get_sink(info);
411 struct gc_plgdata *plgdata = data;
412 gcal_event event = NULL;
414 int size, result;
415 char *osync_xml = NULL, *msg = NULL, *raw_xml = NULL, *updated_event = NULL;
416 OSyncData *odata = NULL;
418 if (!(odata = osync_change_get_data(change))) {
419 msg = "Cannot get raw data from change obj!\n";
420 goto error;
423 osync_data_get_data(odata, &osync_xml, &size);
424 if (!osync_xml) {
425 msg = "Failed getting xml from change obj!\n";
426 goto error;
429 /* Convert to gdata format */
430 if ((result = xslt_transform(plgdata->xslt_ctx_gcal, osync_xml))) {
431 msg = "Failed converting from osync xmlevent to gcalendar\n";
432 goto error;
434 raw_xml = plgdata->xslt_ctx_gcal->xml_str;
436 osync_trace(TRACE_EXIT, "osync: %s\ngcont: %s\n\n", osync_xml, raw_xml);
438 switch (osync_change_get_changetype(change)) {
439 case OSYNC_CHANGE_TYPE_ADDED:
440 result = gcal_add_xmlentry(plgdata->calendar, raw_xml, &updated_event);
441 if (result == -1) {
442 msg = "Failed adding new event!\n";
443 result = gcal_status_httpcode(plgdata->calendar);
444 goto error;
447 if (!(event = gcal_event_new(updated_event))) {
448 msg = "Failed recovering updated fields!\n";
449 goto error;
451 break;
453 case OSYNC_CHANGE_TYPE_MODIFIED:
454 result = gcal_update_xmlentry(plgdata->calendar, raw_xml, &updated_event,
455 NULL);
456 if (result == -1) {
457 msg = "Failed editing event!\n";
458 goto error;
461 if (!(event = gcal_event_new(updated_event))) {
462 msg = "Failed recovering updated fields!\n";
463 goto error;
465 break;
467 case OSYNC_CHANGE_TYPE_DELETED:
468 result = gcal_erase_xmlentry(plgdata->calendar, raw_xml);
469 if (result == -1) {
470 msg = "Failed deleting event!\n";
471 goto error;
473 break;
475 default:
476 osync_context_report_error(ctx, OSYNC_ERROR_NOT_SUPPORTED,
477 "Unknown change type");
478 goto error;
479 break;
482 if (updated_event)
483 free(updated_event);
485 if (event) {
486 /* update the timestamp */
487 if (plgdata->cal_timestamp)
488 free(plgdata->cal_timestamp);
489 plgdata->cal_timestamp = strdup(gcal_event_get_updated(event));
490 if (!plgdata->cal_timestamp) {
491 msg = "Failed copying contact timestamp!\n";
492 goto error;
495 /* FIXME: not sure if this works */
496 /* Inform the new ID */
497 osync_change_set_uid(change, gcal_event_get_url(event));
498 gcal_event_delete(event);
502 osync_context_report_success(ctx);
504 osync_trace(TRACE_EXIT, "%s", __func__);
506 return;
507 error:
508 osync_context_report_error(ctx, OSYNC_ERROR_GENERIC, msg);
509 osync_trace(TRACE_EXIT, "%s:%sHTTP code: %d", __func__, msg, result);
512 static void gc_commit_change_contact(void *data, OSyncPluginInfo *info,
513 OSyncContext *ctx, OSyncChange *change)
515 osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, data, info, ctx, change);
516 osync_trace(TRACE_INTERNAL, "hello, from contacts!\n");
518 OSyncObjTypeSink *sink = osync_plugin_info_get_sink(info);
519 struct gc_plgdata *plgdata = data;
520 gcal_contact contact = NULL;
521 int size, result;
522 char *osync_xml = NULL, *msg = NULL, *raw_xml = NULL, *updated_contact = NULL;
523 OSyncData *odata = NULL;
525 if (!(odata = osync_change_get_data(change))) {
526 msg = "Cannot get raw data from change obj!\n";
527 goto error;
530 osync_data_get_data(odata, &osync_xml, &size);
531 if (!osync_xml) {
532 msg = "Failed getting xml from change obj!\n";
533 goto error;
536 /* Convert to gdata format */
537 if ((result = xslt_transform(plgdata->xslt_ctx_gcont, osync_xml))) {
538 msg = "Failed converting from osync xmlcontact to gcontact\n";
539 goto error;
541 raw_xml = plgdata->xslt_ctx_gcont->xml_str;
543 osync_trace(TRACE_INTERNAL, "osync: %s\ngcont: %s\n\n", osync_xml, raw_xml);
545 switch (osync_change_get_changetype(change)) {
546 case OSYNC_CHANGE_TYPE_ADDED:
547 result = gcal_add_xmlentry(plgdata->contacts, raw_xml, &updated_contact);
548 if (result == -1) {
549 msg = "Failed adding new contact!\n";
550 result = gcal_status_httpcode(plgdata->contacts);
551 goto error;
554 if (!(contact = gcal_contact_new(updated_contact))) {
555 msg = "Failed recovering updated fields!\n";
556 goto error;
558 break;
560 case OSYNC_CHANGE_TYPE_MODIFIED:
561 result = gcal_update_xmlentry(plgdata->contacts, raw_xml, &updated_contact,
562 NULL);
563 if (result == -1) {
564 msg = "Failed editing event!\n";
565 goto error;
568 if (!(contact = gcal_contact_new(updated_contact))) {
569 msg = "Failed recovering updated fields!\n";
570 goto error;
572 break;
574 case OSYNC_CHANGE_TYPE_DELETED:
575 result = gcal_erase_xmlentry(plgdata->contacts, raw_xml);
576 if (result == -1) {
577 msg = "Failed deleting event!\n";
578 goto error;
580 break;
582 default:
583 osync_context_report_error(ctx, OSYNC_ERROR_NOT_SUPPORTED,
584 "Unknown change type");
585 goto error;
586 break;
589 if (updated_contact)
590 free(updated_contact);
592 if (contact) {
593 /* update the timestamp */
594 if (plgdata->cont_timestamp)
595 free(plgdata->cont_timestamp);
596 plgdata->cont_timestamp = strdup(gcal_contact_get_updated(contact));
597 if (!plgdata->cont_timestamp) {
598 msg = "Failed copying contact timestamp!\n";
599 goto error;
602 /* FIXME: not sure if this works */
603 /* Inform the new ID */
604 osync_change_set_uid(change, gcal_contact_get_url(contact));
605 gcal_contact_delete(contact);
608 osync_context_report_success(ctx);
609 osync_trace(TRACE_EXIT, "%s", __func__);
610 return;
612 error:
613 osync_context_report_error(ctx, OSYNC_ERROR_GENERIC, msg);
614 osync_trace(TRACE_EXIT, "%s:%sHTTP code: %d", __func__, msg, result);
617 static void gc_sync_done(void *data, OSyncPluginInfo *info, OSyncContext *ctx)
619 osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, data, info, ctx);
620 struct gc_plgdata *plgdata = NULL;
621 int result;
623 plgdata = data;
624 if (plgdata->calendar && plgdata->cal_timestamp)
625 osync_anchor_update(plgdata->gcal_anchor_path, "gcalendar",
626 plgdata->cal_timestamp);
627 if (plgdata->contacts && plgdata->cont_timestamp)
628 osync_anchor_update(plgdata->gcont_anchor_path, "gcontact",
629 plgdata->cont_timestamp);
632 static void gc_disconnect(void *data, OSyncPluginInfo *info, OSyncContext *ctx)
634 osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, data, info, ctx);
635 struct gc_plgdata *plgdata = data;
637 osync_context_report_success(ctx);
638 osync_trace(TRACE_EXIT, "%s", __func__);
641 static void gc_finalize(void *data)
643 osync_trace(TRACE_ENTRY, "%s(%p)", __func__, data);
644 struct gc_plgdata *plgdata = data;
646 free_plg(plgdata);
647 osync_trace(TRACE_EXIT, "%s", __func__);
650 static void *gc_initialize(OSyncPlugin *plugin,
651 OSyncPluginInfo *info,
652 OSyncError **error)
654 osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, plugin, info, error);
655 struct gc_plgdata *plgdata;
656 OSyncPluginConfig *config;
657 OSyncPluginAuthentication *auth;
658 OSyncPluginAdvancedOption *advanced;
659 OSyncList *resources;
660 OSyncList *r;
661 const char *objtype, *tmp;
662 int i, numobjs;
664 plgdata = osync_try_malloc0(sizeof(struct gc_plgdata), error);
665 config = osync_plugin_info_get_config(info);
666 if ((!plgdata) || (!config)) {
667 osync_error_set(error, OSYNC_ERROR_GENERIC,
668 "Unable to get config data.");
669 goto error_freeplg;
672 advanced = osync_plugin_config_get_advancedoption_value_by_name(config, "xslt");
673 if (!advanced) {
674 osync_trace(TRACE_INTERNAL, "Cannot locate xslt config!\n");
675 goto error_freeplg;
678 if (!(plgdata->xslt_path = strdup(osync_plugin_advancedoption_get_value(advanced))))
679 goto error_freeplg;
681 resources = osync_plugin_config_get_resources(config);
682 numobjs = osync_plugin_info_num_objtypes(info);
684 for (i = 1, r = resources; r; r = r->next, i++) {
685 osync_trace(TRACE_INTERNAL, "field: %s\n", osync_plugin_resource_get_objtype(r->data));
686 if (!(strcmp(osync_plugin_resource_get_objtype(r->data), "event")))
687 if (!(plgdata->calendar = gcal_new(GCALENDAR)))
688 goto error_freeplg;
689 else {
690 osync_trace(TRACE_INTERNAL, "\tcreated calendar obj!\n");
691 gcal_set_store_xml(plgdata->calendar, 1);
694 if (!(strcmp(osync_plugin_resource_get_objtype(r->data), "contact")))
695 if (!(plgdata->contacts = gcal_new(GCONTACT)))
696 goto error_freeplg;
697 else {
698 osync_trace(TRACE_INTERNAL, "\tcreated contact obj!\n");
699 gcal_set_store_xml(plgdata->contacts, 1);
705 /* TODO: how works resource policy? For while, copy everything... */
706 for (i = 0; i < numobjs; i++) {
708 if (!plgdata->username) {
709 auth = osync_plugin_config_get_authentication(config);
710 tmp = osync_plugin_authentication_get_username(auth);
711 if (!tmp)
712 goto error_freeplg;
713 else
714 if (!(plgdata->username = strdup(tmp)))
715 goto error_freeplg;
719 if (!plgdata->password) {
720 tmp = osync_plugin_authentication_get_password(auth);
721 if (!tmp)
722 goto error_freeplg;
723 else
724 if (!(plgdata->password = strdup(tmp)))
725 goto error_freeplg;
728 /* TODO: get proxy/calendar title/resources/etc */
732 OSyncObjTypeSinkFunctions functions_gcal;
733 memset(&functions_gcal, 0, sizeof(functions_gcal));
734 functions_gcal.connect = gc_connect;
735 functions_gcal.get_changes = gc_get_changes_calendar;
736 functions_gcal.commit = gc_commit_change_calendar;
737 functions_gcal.disconnect = gc_disconnect;
738 functions_gcal.sync_done = gc_sync_done;
741 if (plgdata->calendar) {
742 osync_trace(TRACE_INTERNAL, "\tcreating calendar sink...\n");
743 OSyncFormatEnv *formatenv1 = osync_plugin_info_get_format_env(info);
744 plgdata->gcal_format = osync_format_env_find_objformat(formatenv1, "xmlformat-event");
745 if (!plgdata->gcal_format)
746 goto error_freeplg;
747 osync_objformat_ref(plgdata->gcal_format);
749 plgdata->gcal_sink = osync_plugin_info_find_objtype(info, "event");
750 if (!plgdata->gcal_sink)
751 goto error_freeplg;
753 osync_objtype_sink_set_functions(plgdata->gcal_sink, functions_gcal, plgdata);
754 osync_plugin_info_add_objtype(info, plgdata->gcal_sink);
758 OSyncObjTypeSinkFunctions functions_gcont;
759 memset(&functions_gcont, 0, sizeof(functions_gcont));
760 functions_gcont.connect = gc_connect;
761 functions_gcont.get_changes = gc_get_changes_contact;
762 functions_gcont.commit = gc_commit_change_contact;
763 functions_gcont.disconnect = gc_disconnect;
764 functions_gcont.sync_done = gc_sync_done;
766 if (plgdata->contacts) {
767 osync_trace(TRACE_INTERNAL, "\tcreating contact sink...\n");
768 OSyncFormatEnv *formatenv2 = osync_plugin_info_get_format_env(info);
769 plgdata->gcont_format = osync_format_env_find_objformat(formatenv2, "xmlformat-contact");
770 if (!plgdata->gcont_format)
771 goto error_freeplg;
772 osync_objformat_ref(plgdata->gcont_format);
774 plgdata->gcont_sink = osync_plugin_info_find_objtype(info, "contact");
775 if (!plgdata->gcont_sink)
776 goto error_freeplg;
778 osync_objtype_sink_set_functions(plgdata->gcont_sink, functions_gcont, plgdata);
779 osync_plugin_info_add_objtype(info, plgdata->gcont_sink);
784 plgdata->gcal_anchor_path = g_strdup_printf("%s/calendar_anchor.db",
785 osync_plugin_info_get_configdir(info));
786 if (!(plgdata->gcal_anchor_path))
787 goto error_freeplg;
788 else
789 osync_trace(TRACE_INTERNAL, "\tanchor: %s\n", plgdata->gcal_anchor_path);
791 plgdata->gcont_anchor_path = g_strdup_printf("%s/contact_anchor.db",
792 osync_plugin_info_get_configdir(info));
793 if (!(plgdata->gcont_anchor_path))
794 goto error_freeplg;
795 else
796 osync_trace(TRACE_INTERNAL, "\tanchor: %s\n", plgdata->gcont_anchor_path);
798 if (plgdata->calendar)
799 if (!(plgdata->xslt_ctx_gcal = xslt_new()))
800 goto error_freeplg;
801 else
802 osync_trace(TRACE_INTERNAL, "\tsucceed creating xslt_gcal!\n");
804 if (plgdata->contacts)
805 if (!(plgdata->xslt_ctx_gcont = xslt_new()))
806 goto error_freeplg;
807 else
808 osync_trace(TRACE_INTERNAL, "\tsucceed creating xslt_gcont!\n");
810 osync_trace(TRACE_EXIT, "%s", __func__);
812 return plgdata;
814 error_freeplg:
815 if (plgdata)
816 free_plg(plgdata);
817 out:
818 osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error));
819 return NULL;
822 static osync_bool gc_discover(void *data, OSyncPluginInfo *info, OSyncError **error)
824 osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, data, info, error);
826 struct gc_plgdata *plgdata = data;
828 if (plgdata->calendar)
829 osync_objtype_sink_set_available(plgdata->gcal_sink, TRUE);
830 if (plgdata->contacts)
831 osync_objtype_sink_set_available(plgdata->gcont_sink, TRUE);
833 OSyncVersion *version = osync_version_new(error);
834 osync_version_set_plugin(version, "google-data");
835 osync_plugin_info_set_version(info, version);
836 osync_version_unref(version);
838 osync_trace(TRACE_EXIT, "%s", __func__);
839 return TRUE;
842 osync_bool get_sync_info(OSyncPluginEnv *env, OSyncError **error)
844 osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, env, error);
845 OSyncPlugin *plugin = osync_plugin_new(error);
846 if (!plugin)
847 goto error;
849 osync_plugin_set_name(plugin, "google-data");
850 osync_plugin_set_longname(plugin, "Google calendar/plugin");
851 osync_plugin_set_description(plugin, "Google calendar and contacts plugin");
853 osync_plugin_set_initialize(plugin, gc_initialize);
854 osync_plugin_set_finalize(plugin, gc_finalize);
855 osync_plugin_set_discover(plugin, gc_discover);
857 osync_plugin_env_register_plugin(env, plugin);
858 osync_plugin_unref(plugin);
860 osync_trace(TRACE_EXIT, "%s", __func__);
861 return TRUE;
863 error:
864 osync_trace(TRACE_EXIT_ERROR, "Unable to register: %s", osync_error_print(error));
865 osync_error_unref(error);
866 return FALSE;
869 int get_version(void)
871 return 1;