Informing the ID (a.k.a. edit_url) to opensync after commiting changes.
[gdataplugin.git] / src / gcalendar.c
blobe0067a2361b86253ebabe5e2ed36876d70886098
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 * - commitchange/applychanges: report gdata entries directly and rely on
25 * gdata format plugin to do the conversion between formats.
26 * - commitchanges: report back updated fields, when ADDED (ID/updated/edit_url) or
27 * UPDATED (updated/edit_url)
28 * - review code for leaks (I'm not sure if I'm using opensync API correctly...)
32 #include <opensync/opensync.h>
33 #include <opensync/opensync-plugin.h>
34 #include <opensync/opensync-helper.h>
35 #include <opensync/opensync-merger.h>
36 #include <opensync/opensync-format.h>
37 #include <opensync/opensync-data.h>
38 #include <opensync/opensync-version.h>
40 #include <glib.h>
42 #include <libxml/tree.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <string.h>
47 #include <sys/types.h>
48 #include <signal.h>
49 #include <sys/wait.h>
50 #include <gcal_status.h>
51 #include <gcalendar.h>
52 #include <gcontact.h>
53 #include "xslt_aux.h"
55 struct gc_plgdata
57 char *url;
58 char *username;
59 char *password;
60 char *gcal_anchor_path;
61 char *gcont_anchor_path;
62 char *timezone;
63 char *xslt_path;
64 /* libgcal resources */
65 char *cal_timestamp;
66 char *cont_timestamp;
67 gcal_t calendar;
68 gcal_t contacts;
69 struct gcal_event_array all_events;
70 struct gcal_contact_array all_contacts;
71 /* calendar sink/format */
72 OSyncObjTypeSink *gcal_sink;
73 OSyncObjFormat *gcal_format;
74 /* contact sink/format */
75 OSyncObjTypeSink *gcont_sink;
76 OSyncObjFormat *gcont_format;
77 /* XSLT context resource struct */
78 struct xslt_resources *xslt_ctx_gcal;
79 struct xslt_resources *xslt_ctx_gcont;
82 static void free_plg(struct gc_plgdata *plgdata)
84 if (plgdata->calendar) {
85 gcal_delete(plgdata->calendar);
86 gcal_cleanup_events(&(plgdata->all_events));
88 if (plgdata->contacts) {
89 gcal_delete(plgdata->contacts);
90 gcal_cleanup_contacts(&(plgdata->all_contacts));
93 if (plgdata->gcal_anchor_path)
94 free(plgdata->gcal_anchor_path);
95 if (plgdata->gcont_anchor_path)
96 free(plgdata->gcont_anchor_path);
97 if (plgdata->xslt_path)
98 free(plgdata->xslt_path);
99 if (plgdata->xslt_ctx_gcal)
100 xslt_delete(plgdata->xslt_ctx_gcal);
101 if (plgdata->xslt_ctx_gcont)
102 xslt_delete(plgdata->xslt_ctx_gcont);
103 if (plgdata->cal_timestamp)
104 free(plgdata->cal_timestamp);
105 if (plgdata->cont_timestamp)
106 free(plgdata->cont_timestamp);
107 if (plgdata->timezone)
108 free(plgdata->timezone);
109 if (plgdata->url)
110 xmlFree(plgdata->url);
111 if (plgdata->username)
112 xmlFree(plgdata->username);
113 if (plgdata->password)
114 xmlFree(plgdata->password);
115 if (plgdata->gcal_sink)
116 osync_objtype_sink_unref(plgdata->gcal_sink);
117 if (plgdata->gcal_format)
118 osync_objformat_unref(plgdata->gcal_format);
119 g_free(plgdata);
122 static void gc_connect(void *data, OSyncPluginInfo *info, OSyncContext *ctx)
124 osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, data, info, ctx);
125 static int counter = 0;
126 int result;
127 struct gc_plgdata *plgdata = data;
128 OSyncObjTypeSink *sink = osync_plugin_info_get_sink(info);
129 OSyncError *error = NULL;
130 char buffer[512];
132 if ((plgdata->calendar) && (counter == 0)) {
133 result = gcal_get_authentication(plgdata->calendar, plgdata->username,
134 plgdata->password);
135 ++counter;
136 if (result == -1)
137 goto error;
139 snprintf(buffer, sizeof(buffer) - 1, "%s/gcal2osync.xslt",
140 plgdata->xslt_path);
141 if ((result = xslt_initialize(plgdata->xslt_ctx_gcal, buffer)))
142 goto error;
143 osync_trace(TRACE_INTERNAL, "\ndone calendar: %s\n", buffer);
146 if (((plgdata->contacts) && (counter == 1)) ||
147 ((plgdata->gcont_sink) && (!plgdata->gcal_sink))) {
148 result = gcal_get_authentication(plgdata->contacts, plgdata->username,
149 plgdata->password);
150 counter++;
151 if (result == -1)
152 goto error;
154 snprintf(buffer, sizeof(buffer) - 1, "%s/gcont2osync.xslt",
155 plgdata->xslt_path);
156 if ((result = xslt_initialize(plgdata->xslt_ctx_gcont, buffer)))
157 goto error;
158 osync_trace(TRACE_INTERNAL, "\ndone contact: %s\n", buffer);
161 osync_context_report_success(ctx);
162 osync_trace(TRACE_EXIT, "%s", __func__);
163 return;
165 error:
166 osync_trace(TRACE_INTERNAL, "\nGood bye, cruel world...\n");
167 osync_context_report_osyncerror(ctx, &error);
170 static void gc_get_changes_calendar(void *data, OSyncPluginInfo *info, OSyncContext *ctx)
172 osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, data, info, ctx);
173 char buffer[512];
174 static int counter = 0;
175 struct gc_plgdata *plgdata = data;
176 char slow_sync_flag = 0;
177 OSyncObjTypeSink *sink = osync_plugin_info_get_sink(info);
178 OSyncError *error = NULL;
179 OSyncXMLFormat *xmlformat;
180 OSyncData *odata = NULL;
181 OSyncChange *chg = NULL;
182 int result = 0, i;
183 char *timestamp = NULL, *msg, *raw_xml = NULL;
184 gcal_event event;
186 if (!plgdata->gcal_sink)
187 return;
188 timestamp = osync_anchor_retrieve(plgdata->gcal_anchor_path, "gcalendar");
189 if (timestamp)
190 osync_trace(TRACE_INTERNAL, "timestamp is: %s\n", timestamp);
191 else
192 osync_trace(TRACE_INTERNAL, "first sync!\n");
194 if (osync_objtype_sink_get_slowsync(plgdata->gcal_sink) || !timestamp) {
195 osync_trace(TRACE_INTERNAL, "\n\t\tgcal: Client asked for slow syncing...\n");
196 slow_sync_flag = 1;
197 result = gcal_get_events(plgdata->calendar, &(plgdata->all_events));
199 } else {
200 osync_trace(TRACE_INTERNAL, "\n\t\tgcal: Client asked for fast syncing...\n");
201 result = gcal_get_updated_events(plgdata->calendar,
202 &(plgdata->all_events),
203 timestamp);
206 if (result) {
207 msg = "Failed getting events!";
208 goto error;
211 /* Calendar returns most recently updated event as first element */
212 event = gcal_event_element(&(plgdata->all_events), 0);
213 if (!event)
214 goto error;
215 plgdata->cont_timestamp = strdup(gcal_event_get_updated(event));
216 if (!plgdata->cont_timestamp) {
217 msg = "Failed copying event timestamp!\n";
218 goto error;
221 osync_trace(TRACE_INTERNAL, "gcalendar: got then all!\n");
222 for (i = 0; i < plgdata->all_events.length; ++i) {
223 event = gcal_event_element(&(plgdata->all_events), i);
224 if (!event)
225 goto error;
227 raw_xml = gcal_event_get_xml(event);
228 if ((result = xslt_transform(plgdata->xslt_ctx_gcal,
229 raw_xml)))
230 goto error;
232 raw_xml = plgdata->xslt_ctx_gcal->xml_str;
233 xmlformat = osync_xmlformat_parse(raw_xml,
234 strlen(raw_xml),
235 &error);
236 if (!xmlformat)
237 goto error;
239 osync_xmlformat_sort(xmlformat);
240 odata = osync_data_new((char *)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 fprintf(stderr, "gcont: %s\nosync: %s\n", gcal_contact_get_xml(contact),
354 raw_xml);
356 osync_xmlformat_sort(xmlformat);
357 odata = osync_data_new((char *)xmlformat,
358 osync_xmlformat_size(),
359 plgdata->gcont_format, &error);
360 if (!odata)
361 goto cleanup;
363 if (!(chg = osync_change_new(&error)))
364 goto cleanup;
365 osync_data_set_objtype(odata, osync_objtype_sink_get_name(plgdata->gcont_sink));
366 osync_change_set_data(chg, odata);
367 osync_data_unref(odata);
369 osync_change_set_uid(chg, gcal_contact_get_url(contact));
371 if (slow_sync_flag)
372 osync_change_set_changetype(chg, OSYNC_CHANGE_TYPE_ADDED);
373 else
374 if (gcal_contact_is_deleted(contact))
375 osync_change_set_changetype(chg, OSYNC_CHANGE_TYPE_DELETED);
376 else
377 osync_change_set_changetype(chg, OSYNC_CHANGE_TYPE_MODIFIED);
379 osync_context_report_change(ctx, chg);
380 osync_change_unref(chg);
383 /* Load XSLT style to convert osync xmlformat-contact --> gdata */
384 snprintf(buffer, sizeof(buffer) - 1, "%s/osync2gcont.xslt",
385 plgdata->xslt_path);
386 if ((result = xslt_initialize(plgdata->xslt_ctx_gcont, buffer)))
387 goto error;
388 osync_trace(TRACE_INTERNAL, "\ndone contact: %s\n", buffer);
391 exit:
392 osync_context_report_success(ctx);
393 return;
395 cleanup:
396 osync_error_unref(&error);
397 osync_xmlformat_unref(&xmlformat);
399 error:
400 osync_context_report_error(ctx, OSYNC_ERROR_GENERIC, msg);
403 static void gc_commit_change_calendar(void *data, OSyncPluginInfo *info,
404 OSyncContext *ctx, OSyncChange *change)
406 osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, data, info, ctx, change);
407 osync_trace(TRACE_INTERNAL, "hello, from calendar!\n");
408 OSyncObjTypeSink *sink = osync_plugin_info_get_sink(info);
409 struct gc_plgdata *plgdata = data;
410 gcal_event event = NULL;
412 int size, result;
413 char *osync_xml = NULL, *msg = NULL, *raw_xml = NULL, *updated_event = NULL;
414 OSyncData *odata = NULL;
416 if (!(odata = osync_change_get_data(change))) {
417 msg = "Cannot get raw data from change obj!\n";
418 goto error;
421 osync_data_get_data(odata, &osync_xml, &size);
422 if (!osync_xml) {
423 msg = "Failed getting xml from change obj!\n";
424 goto error;
427 /* Convert to gdata format */
428 if ((result = xslt_transform(plgdata->xslt_ctx_gcal, osync_xml))) {
429 msg = "Failed converting from osync xmlevent to gcalendar\n";
430 goto error;
432 raw_xml = plgdata->xslt_ctx_gcal->xml_str;
434 switch (osync_change_get_changetype(change)) {
435 case OSYNC_CHANGE_TYPE_ADDED:
436 result = gcal_add_xmlentry(plgdata->calendar, raw_xml, &updated_event);
437 if (result == -1) {
438 msg = "Failed adding new event!\n";
439 goto error;
442 if (!(event = gcal_event_new(updated_event))) {
443 msg = "Failed recovering updated fields!\n";
444 goto error;
446 break;
448 case OSYNC_CHANGE_TYPE_MODIFIED:
449 result = gcal_update_xmlentry(plgdata->calendar, raw_xml, &updated_event,
450 NULL);
451 if (result == -1) {
452 msg = "Failed editing event!\n";
453 goto error;
456 if (!(event = gcal_event_new(updated_event))) {
457 msg = "Failed recovering updated fields!\n";
458 goto error;
460 break;
462 case OSYNC_CHANGE_TYPE_DELETED:
463 result = gcal_erase_xmlentry(plgdata->calendar, raw_xml);
464 if (result == -1) {
465 msg = "Failed deleting event!\n";
466 goto error;
468 break;
470 default:
471 osync_context_report_error(ctx, OSYNC_ERROR_NOT_SUPPORTED,
472 "Unknown change type");
473 goto error;
474 break;
477 if (osync_xml)
478 g_free(osync_xml);
480 if (updated_event)
481 free(updated_event);
483 if (event) {
484 /* Inform the new ID */
485 osync_change_set_uid(change, gcal_event_get_url(event));
486 gcal_event_delete(event);
490 osync_context_report_success(ctx);
492 osync_trace(TRACE_EXIT, "%s", __func__);
494 return;
495 error:
496 osync_context_report_error(ctx, OSYNC_ERROR_GENERIC, msg);
499 static void gc_commit_change_contact(void *data, OSyncPluginInfo *info,
500 OSyncContext *ctx, OSyncChange *change)
502 osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, data, info, ctx, change);
503 osync_trace(TRACE_INTERNAL, "hello, from contacts!\n");
505 OSyncObjTypeSink *sink = osync_plugin_info_get_sink(info);
506 struct gc_plgdata *plgdata = data;
507 gcal_contact contact = NULL;
508 int size, result;
509 char *osync_xml = NULL, *msg = NULL, *raw_xml = NULL, *updated_contact = NULL;
510 OSyncData *odata = NULL;
512 if (!(odata = osync_change_get_data(change))) {
513 msg = "Cannot get raw data from change obj!\n";
514 goto error;
517 osync_data_get_data(odata, &osync_xml, &size);
518 if (!osync_xml) {
519 msg = "Failed getting xml from change obj!\n";
520 goto error;
523 /* Convert to gdata format */
524 if ((result = xslt_transform(plgdata->xslt_ctx_gcont, osync_xml))) {
525 msg = "Failed converting from osync xmlcontact to gcontact\n";
526 goto error;
528 raw_xml = plgdata->xslt_ctx_gcont->xml_str;
530 fprintf(stderr, "osync: %s\ngcont: %s\n\n", osync_xml, raw_xml);
532 switch (osync_change_get_changetype(change)) {
533 case OSYNC_CHANGE_TYPE_ADDED:
534 result = gcal_add_xmlentry(plgdata->contacts, raw_xml, &updated_contact);
535 if (result == -1) {
536 msg = "Failed adding new contact!\n";
537 goto error;
540 if (!(contact = gcal_contact_new(updated_contact))) {
541 msg = "Failed recovering updated fields!\n";
542 goto error;
544 break;
546 case OSYNC_CHANGE_TYPE_MODIFIED:
547 result = gcal_update_xmlentry(plgdata->contacts, raw_xml, &updated_contact,
548 NULL);
549 if (result == -1) {
550 msg = "Failed editing event!\n";
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_DELETED:
561 result = gcal_erase_xmlentry(plgdata->contacts, raw_xml);
562 if (result == -1) {
563 msg = "Failed deleting event!\n";
564 goto error;
566 break;
568 default:
569 osync_context_report_error(ctx, OSYNC_ERROR_NOT_SUPPORTED,
570 "Unknown change type");
571 goto error;
572 break;
575 if (osync_xml)
576 g_free(osync_xml);
578 if (updated_contact)
579 free(updated_contact);
581 if (contact) {
582 osync_change_set_uid(change, gcal_contact_get_url(contact));
583 gcal_contact_delete(contact);
586 osync_context_report_success(ctx);
587 osync_trace(TRACE_EXIT, "%s", __func__);
588 return;
590 error:
591 osync_context_report_error(ctx, OSYNC_ERROR_GENERIC, msg);
595 static void gc_sync_done(void *data, OSyncPluginInfo *info, OSyncContext *ctx)
597 osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, data, info, ctx);
598 struct gc_plgdata *plgdata = NULL;
599 int result;
601 plgdata = data;
602 osync_anchor_update(plgdata->gcal_anchor_path, "gcalendar", plgdata->cal_timestamp);
603 osync_anchor_update(plgdata->gcont_anchor_path, "gcontact", plgdata->cont_timestamp);
606 static void gc_disconnect(void *data, OSyncPluginInfo *info, OSyncContext *ctx)
608 osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, data, info, ctx);
609 struct gc_plgdata *plgdata = data;
611 osync_context_report_success(ctx);
612 osync_trace(TRACE_EXIT, "%s", __func__);
615 static void gc_finalize(void *data)
617 osync_trace(TRACE_ENTRY, "%s(%p)", __func__, data);
618 struct gc_plgdata *plgdata = data;
620 free_plg(plgdata);
621 osync_trace(TRACE_EXIT, "%s", __func__);
624 static void *gc_initialize(OSyncPlugin *plugin,
625 OSyncPluginInfo *info,
626 OSyncError **error)
628 osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, plugin, info, error);
629 struct gc_plgdata *plgdata;
630 OSyncPluginConfig *config;
631 OSyncPluginAuthentication *auth;
632 OSyncPluginAdvancedOption *advanced;
633 OSyncList *resources;
634 OSyncList *r;
635 const char *objtype, *tmp;
636 int i, numobjs;
638 plgdata = osync_try_malloc0(sizeof(struct gc_plgdata), error);
639 config = osync_plugin_info_get_config(info);
640 if ((!plgdata) || (!config)) {
641 osync_error_set(error, OSYNC_ERROR_GENERIC,
642 "Unable to get config data.");
643 goto error_freeplg;
646 advanced = osync_plugin_config_get_advancedoption_value_by_name(config, "xslt");
647 if (!advanced) {
648 osync_trace(TRACE_INTERNAL, "Cannot locate xslt config!\n");
649 goto error_freeplg;
652 if (!(plgdata->xslt_path = strdup(osync_plugin_advancedoption_get_value(advanced))))
653 goto error_freeplg;
655 resources = osync_plugin_config_get_resources(config);
656 numobjs = osync_plugin_info_num_objtypes(info);
658 for (i = 1, r = resources; r; r = r->next, i++) {
659 osync_trace(TRACE_INTERNAL, "field: %s\n", osync_plugin_resource_get_objtype(r->data));
660 if (!(strcmp(osync_plugin_resource_get_objtype(r->data), "event")))
661 if (!(plgdata->calendar = gcal_new(GCALENDAR)))
662 goto error_freeplg;
663 else {
664 osync_trace(TRACE_INTERNAL, "\tcreated calendar obj!\n");
665 gcal_set_store_xml(plgdata->calendar, 1);
668 if (!(strcmp(osync_plugin_resource_get_objtype(r->data), "contact")))
669 if (!(plgdata->contacts = gcal_new(GCONTACT)))
670 goto error_freeplg;
671 else {
672 osync_trace(TRACE_INTERNAL, "\tcreated contact obj!\n");
673 gcal_set_store_xml(plgdata->contacts, 1);
679 /* TODO: how works resource policy? For while, copy everything... */
680 for (i = 0; i < numobjs; i++) {
682 if (!plgdata->username) {
683 auth = osync_plugin_config_get_authentication(config);
684 tmp = osync_plugin_authentication_get_username(auth);
685 if (!tmp)
686 goto error_freeplg;
687 else
688 if (!(plgdata->username = strdup(tmp)))
689 goto error_freeplg;
693 if (!plgdata->password) {
694 tmp = osync_plugin_authentication_get_password(auth);
695 if (!tmp)
696 goto error_freeplg;
697 else
698 if (!(plgdata->password = strdup(tmp)))
699 goto error_freeplg;
702 /* TODO: get proxy/calendar title/resources/etc */
706 OSyncObjTypeSinkFunctions functions_gcal;
707 memset(&functions_gcal, 0, sizeof(functions_gcal));
708 functions_gcal.connect = gc_connect;
709 functions_gcal.get_changes = gc_get_changes_calendar;
710 functions_gcal.commit = gc_commit_change_calendar;
711 functions_gcal.disconnect = gc_disconnect;
712 functions_gcal.sync_done = gc_sync_done;
715 if (plgdata->calendar) {
716 osync_trace(TRACE_INTERNAL, "\tcreating calendar sink...\n");
717 OSyncFormatEnv *formatenv1 = osync_plugin_info_get_format_env(info);
718 plgdata->gcal_format = osync_format_env_find_objformat(formatenv1, "xmlformat-event-doc");
719 if (!plgdata->gcal_format)
720 goto error_freeplg;
721 osync_objformat_ref(plgdata->gcal_format);
723 plgdata->gcal_sink = osync_plugin_info_find_objtype(info, "event");
724 if (!plgdata->gcal_sink)
725 goto error_freeplg;
727 osync_objtype_sink_set_functions(plgdata->gcal_sink, functions_gcal, plgdata);
728 osync_plugin_info_add_objtype(info, plgdata->gcal_sink);
732 OSyncObjTypeSinkFunctions functions_gcont;
733 memset(&functions_gcont, 0, sizeof(functions_gcont));
734 functions_gcont.connect = gc_connect;
735 functions_gcont.get_changes = gc_get_changes_contact;
736 functions_gcont.commit = gc_commit_change_contact;
737 functions_gcont.disconnect = gc_disconnect;
738 functions_gcont.sync_done = gc_sync_done;
740 if (plgdata->contacts) {
741 osync_trace(TRACE_INTERNAL, "\tcreating contact sink...\n");
742 OSyncFormatEnv *formatenv2 = osync_plugin_info_get_format_env(info);
743 plgdata->gcont_format = osync_format_env_find_objformat(formatenv2, "xmlformat-contact-doc");
744 if (!plgdata->gcont_format)
745 goto error_freeplg;
746 osync_objformat_ref(plgdata->gcont_format);
748 plgdata->gcont_sink = osync_plugin_info_find_objtype(info, "contact");
749 if (!plgdata->gcont_sink)
750 goto error_freeplg;
752 osync_objtype_sink_set_functions(plgdata->gcont_sink, functions_gcont, plgdata);
753 osync_plugin_info_add_objtype(info, plgdata->gcont_sink);
758 plgdata->gcal_anchor_path = g_strdup_printf("%s/calendar_anchor.db",
759 osync_plugin_info_get_configdir(info));
760 if (!(plgdata->gcal_anchor_path))
761 goto error_freeplg;
762 else
763 osync_trace(TRACE_INTERNAL, "\tanchor: %s\n", plgdata->gcal_anchor_path);
765 plgdata->gcont_anchor_path = g_strdup_printf("%s/contact_anchor.db",
766 osync_plugin_info_get_configdir(info));
767 if (!(plgdata->gcont_anchor_path))
768 goto error_freeplg;
769 else
770 osync_trace(TRACE_INTERNAL, "\tanchor: %s\n", plgdata->gcont_anchor_path);
772 if (plgdata->calendar)
773 if (!(plgdata->xslt_ctx_gcal = xslt_new()))
774 goto error_freeplg;
775 else
776 osync_trace(TRACE_INTERNAL, "\tsucceed creating xslt_gcal!\n");
778 if (plgdata->contacts)
779 if (!(plgdata->xslt_ctx_gcont = xslt_new()))
780 goto error_freeplg;
781 else
782 osync_trace(TRACE_INTERNAL, "\tsucceed creating xslt_gcont!\n");
784 osync_trace(TRACE_EXIT, "%s", __func__);
786 return plgdata;
788 error_freeplg:
789 if (plgdata)
790 free_plg(plgdata);
791 out:
792 osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error));
793 return NULL;
796 static osync_bool gc_discover(void *data, OSyncPluginInfo *info, OSyncError **error)
798 osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, data, info, error);
800 struct gc_plgdata *plgdata = data;
802 if (plgdata->calendar)
803 osync_objtype_sink_set_available(plgdata->gcal_sink, TRUE);
804 if (plgdata->contacts)
805 osync_objtype_sink_set_available(plgdata->gcont_sink, TRUE);
807 OSyncVersion *version = osync_version_new(error);
808 osync_version_set_plugin(version, "google-data");
809 osync_plugin_info_set_version(info, version);
810 osync_version_unref(version);
812 osync_trace(TRACE_EXIT, "%s", __func__);
813 return TRUE;
816 osync_bool get_sync_info(OSyncPluginEnv *env, OSyncError **error)
818 osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, env, error);
819 OSyncPlugin *plugin = osync_plugin_new(error);
820 if (!plugin)
821 goto error;
823 osync_plugin_set_name(plugin, "google-data");
824 osync_plugin_set_longname(plugin, "Google calendar/plugin");
825 osync_plugin_set_description(plugin, "Google calendar and contacts plugin");
827 osync_plugin_set_initialize(plugin, gc_initialize);
828 osync_plugin_set_finalize(plugin, gc_finalize);
829 osync_plugin_set_discover(plugin, gc_discover);
831 osync_plugin_env_register_plugin(env, plugin);
832 osync_plugin_unref(plugin);
834 osync_trace(TRACE_EXIT, "%s", __func__);
835 return TRUE;
837 error:
838 osync_trace(TRACE_EXIT_ERROR, "Unable to register: %s", osync_error_print(error));
839 osync_error_unref(error);
840 return FALSE;
843 int get_version(void)
845 return 1;