Changeset 2345
- Timestamp:
- 07/21/07 11:21:17 (1 year ago)
- Files:
-
- plugins/google-calendar/src/Makefile.am (modified) (1 diff)
- plugins/google-calendar/src/gcalendar.c (modified) (20 diffs)
- plugins/google-calendar/src/google-cal-helper.py (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
plugins/google-calendar/src/Makefile.am
r1724 r2345 20 20 gcalendar_la_CFLAGS = -DGCAL_HELPER=\"$(libexecdir)/google-cal-helper\" 21 21 gcalendar_la_LDFLAGS = -avoid-version -export-dynamic -module 22 gcalendar_la_LIBADD = @PACKAGE_LIBS@ @LIBS@ -lopensync-xml22 gcalendar_la_LIBADD = @PACKAGE_LIBS@ @LIBS@ 23 23 24 24 google-cal-helper: $(srcdir)/google-cal-helper.py plugins/google-calendar/src/gcalendar.c
r1435 r2345 21 21 22 22 #include <opensync/opensync.h> 23 #include <opensync/opensync_xml.h> 23 #include <opensync/opensync-plugin.h> 24 #include <opensync/opensync-helper.h> 25 #include <opensync/opensync-merger.h> 26 #include <opensync/opensync-format.h> 27 #include <opensync/opensync-data.h> 28 #include <opensync/opensync-version.h> 24 29 25 30 #include <glib.h> … … 39 44 char *username; 40 45 char *password; 41 OSyncMember *member;42 46 OSyncHashTable *hashtable; 47 OSyncObjTypeSink *sink; 48 OSyncObjFormat *objformat; 43 49 }; 50 51 static void free_plg(struct gc_plgdata *plgdata) 52 { 53 if (plgdata->url) 54 xmlFree(plgdata->url); 55 if (plgdata->username) 56 xmlFree(plgdata->username); 57 if (plgdata->password) 58 xmlFree(plgdata->password); 59 if (plgdata->hashtable) 60 osync_hashtable_free(plgdata->hashtable); 61 if (plgdata->sink) 62 osync_objtype_sink_unref(plgdata->sink); 63 if (plgdata->objformat) 64 osync_objformat_unref(plgdata->objformat); 65 g_free(plgdata); 66 } 44 67 45 68 /** Run gchelper and return the file descriptors for its stdin/stdout … … 162 185 } 163 186 164 osync_bool gc_parse_config(struct gc_plgdata *plgdata, c har *cfg, int cfgsize, OSyncError **error)187 osync_bool gc_parse_config(struct gc_plgdata *plgdata, const char *cfg, OSyncError **error) 165 188 { 166 189 xmlNode *node; … … 168 191 osync_bool ret = FALSE; 169 192 170 doc = xmlParseMemory(cfg, cfgsize);193 doc = xmlParseMemory(cfg, strlen(cfg) + 1); 171 194 if (!doc) { 172 195 osync_error_set(error, OSYNC_ERROR_GENERIC, "Couldn't parse configuration"); … … 209 232 } 210 233 211 static void *gc_initialize(OSyncMember *member, OSyncError **error) 212 { 213 struct gc_plgdata *plgdata = NULL; 214 char *cfg; 215 int cfgsize; 216 217 if (!osync_member_get_config(member, &cfg, &cfgsize, error)) { 218 osync_error_update(error, "Unable to get config data: %s", osync_error_print(error)); 219 goto out; 220 } 221 222 plgdata = osync_try_malloc0(sizeof(struct gc_plgdata), error); 223 if (!plgdata) 224 goto out_freecfg; 225 226 if (!gc_parse_config(plgdata, cfg, cfgsize, error)) 227 goto error_freedata; 228 229 plgdata->member = member; 230 plgdata->hashtable = osync_hashtable_new(); 231 232 out_freecfg: 233 g_free(cfg); 234 out: 235 return plgdata; 236 237 238 error_freedata: 239 g_free(plgdata); 240 plgdata = NULL; 241 goto out_freecfg; 242 } 243 244 static void gc_connect(OSyncContext *ctx) 245 { 246 struct gc_plgdata *plgdata = (struct gc_plgdata*)osync_context_get_plugin_data(ctx); 247 234 static void gc_connect(void *data, OSyncPluginInfo *info, OSyncContext *ctx) 235 { 236 osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, data, info, ctx); 237 238 struct gc_plgdata *plgdata = data; 239 OSyncObjTypeSink *sink = osync_plugin_info_get_sink(info); 248 240 OSyncError *error = NULL; 249 if (!osync_hashtable_load(plgdata->hashtable, plgdata->member, &error)) { 241 242 char *tablepath = g_strdup_printf("%s/hashtable.db", osync_plugin_info_get_configdir(info)); 243 244 plgdata->hashtable = osync_hashtable_new(tablepath, osync_objtype_sink_get_name(sink), &error); 245 g_free(tablepath); 246 247 if (!plgdata->hashtable) { 250 248 osync_context_report_osyncerror(ctx, &error); 251 249 return; … … 253 251 254 252 osync_context_report_success(ctx); 255 } 256 257 static void gc_get_changeinfo(OSyncContext *ctx) 258 { 259 struct gc_plgdata *plgdata = (struct gc_plgdata*)osync_context_get_plugin_data(ctx); 253 254 osync_trace(TRACE_EXIT, "%s", __func__); 255 } 256 257 static void gc_get_changes(void *data, OSyncPluginInfo *info, OSyncContext *ctx) 258 { 259 osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, data, info, ctx); 260 261 struct gc_plgdata *plgdata = data; 262 OSyncObjTypeSink *sink = osync_plugin_info_get_sink(info); 260 263 OSyncError *error = NULL; 261 264 … … 266 269 int status; 267 270 268 if (osync_ member_get_slow_sync(plgdata->member, "event")) {269 osync_hashtable_ set_slow_sync(plgdata->hashtable, "event");271 if (osync_objtype_sink_get_slowsync(sink)) { 272 osync_hashtable_reset(plgdata->hashtable); 270 273 } 271 274 … … 278 281 out = fdopen(output, "r"); 279 282 if (!out) { 280 osync_context_report_error(ctx, OSYNC_ERROR_GENERIC, "Couldn't open helper output");283 osync_context_report_error(ctx, OSYNC_ERROR_GENERIC, "Couldn't open helper output"); 281 284 close(output); 282 285 goto error_fdopen; … … 312 315 if (fread(xmldata, size, 1, out) < 1) { 313 316 osync_context_report_error(ctx, OSYNC_ERROR_GENERIC, "Error reading xml data from helper"); 314 goto error_readxml; 315 317 goto error_xml; 316 318 } 317 319 318 320 if (fread(uid, uidsize, 1, out) < 1) { 319 321 osync_context_report_error(ctx, OSYNC_ERROR_GENERIC, "Error reading xml data from helper"); 320 goto error_ readxml;322 goto error_xml; 321 323 } 322 324 uid[uidsize] = '\0'; … … 324 326 if (fread(hash, hashsize, 1, out) < 1) { 325 327 osync_context_report_error(ctx, OSYNC_ERROR_GENERIC, "Error reading xml data from helper"); 326 goto error_ readxml;328 goto error_xml; 327 329 } 328 330 hash[hashsize] = '\0'; 329 331 330 xmlDoc *doc = xmlParseMemory(xmldata, size);332 OSyncXMLFormat *doc = osync_xmlformat_parse(xmldata, size, &error); 331 333 if (!doc) { 332 334 osync_context_report_error(ctx, OSYNC_ERROR_GENERIC, "Invalid XML data from helper"); 333 goto error_invalidxml; 334 } 335 336 OSyncChange *chg = osync_change_new(); 335 osync_error_unref(&error); 336 goto error_xml; 337 } 338 /* osync_merge_merge() seems to like its input sorted... */ 339 osync_xmlformat_sort(doc); 340 341 OSyncData *odata = osync_data_new((char *)doc, osync_xmlformat_size(), plgdata->objformat, &error); 342 if (!odata) { 343 osync_context_report_error(ctx, OSYNC_ERROR_GENERIC, "No memory"); 344 osync_error_unref(&error); 345 /* osync_data_new() does not increase the reference count of 346 its 'data' member, but osync_data_unref() will decrease it, 347 so this is the only case where 'doc' has to be unreferenced 348 manually */ 349 osync_xmlformat_unref(doc); 350 goto error_xml; 351 } 352 353 OSyncChange *chg = osync_change_new(&error); 337 354 if (!chg) { 338 355 osync_context_report_error(ctx, OSYNC_ERROR_GENERIC, "No memory"); 356 osync_error_unref(&error); 339 357 goto error_chg; 340 358 } 341 359 342 360 osync_change_set_uid(chg, uid); 343 osync_change_set_member(chg, plgdata->member); 344 osync_change_set_objtype_string(chg, "event"); 345 osync_change_set_objformat_string(chg, "xml-event"); 346 osync_change_set_data(chg, (char*)doc, sizeof(doc), 1); 347 361 osync_change_set_data(chg, odata); 362 osync_data_unref(odata); 363 osync_change_set_objtype(chg, osync_objtype_sink_get_name(sink)); 348 364 osync_change_set_hash(chg, hash); 349 if (osync_hashtable_detect_change(plgdata->hashtable, chg)) { 365 366 osync_change_set_changetype(chg, osync_hashtable_get_changetype(plgdata->hashtable, uid, hash)); 367 osync_hashtable_report(plgdata->hashtable, uid); 368 369 if (osync_change_get_changetype(chg) != OSYNC_CHANGE_TYPE_UNMODIFIED) { 350 370 osync_context_report_change(ctx, chg); 351 osync_hashtable_update_hash(plgdata->hashtable, chg);352 } 353 354 xmlFreeDoc(doc);371 osync_hashtable_update_hash(plgdata->hashtable, osync_change_get_changetype(chg), uid, hash); 372 } 373 374 osync_change_unref(chg); 355 375 free(hash); 356 376 free(uid); 357 377 free(xmldata); 358 378 359 /* end of loop */360 continue;361 362 /* error handling in the loop */379 /* end of loop */ 380 continue; 381 382 /* error handling in the loop */ 363 383 error_chg: 364 xmlFreeDoc(doc); 365 error_invalidxml: 366 error_readxml: 384 osync_data_unref(odata); 385 error_xml: 367 386 free(hash); 368 387 error_hash: … … 373 392 } 374 393 375 osync_hashtable_report_deleted(plgdata->hashtable, ctx, "event"); 394 char **uids = osync_hashtable_get_deleted(plgdata->hashtable); 395 int i; 396 for (i = 0; uids[i]; i++) { 397 OSyncChange *change = osync_change_new(&error); 398 if (!change) { 399 osync_context_report_error(ctx, OSYNC_ERROR_GENERIC, "ERROR is: %s", osync_error_print(&error)); 400 goto error_fdopen; 401 } 402 OSyncData *data = osync_data_new(NULL, 0, plgdata->objformat, &error); 403 if (!data) { 404 osync_context_report_error(ctx, OSYNC_ERROR_GENERIC, "ERROR is: %s", osync_error_print(&error)); 405 goto error_fdopen; 406 } 407 osync_data_set_objtype(data, "event"); 408 409 osync_change_set_data(change, data); 410 osync_change_set_changetype(change, OSYNC_CHANGE_TYPE_DELETED); 411 osync_change_set_uid(change, uids[i]); 412 osync_context_report_change(ctx, change); 413 osync_hashtable_update_hash(plgdata->hashtable, OSYNC_CHANGE_TYPE_DELETED, uids[i], NULL); 414 osync_change_unref(change); 415 osync_data_unref(data); 416 g_free(uids[i]); 417 } 418 g_free(uids); 376 419 377 420 fclose(out); … … 385 428 osync_context_report_success(ctx); 386 429 430 osync_trace(TRACE_EXIT, "%s", __func__); 387 431 return; 388 432 … … 394 438 waitpid(pid, NULL, 0); 395 439 error: 440 osync_trace(TRACE_EXIT, "%s", __func__); 396 441 return; 397 442 } 398 443 399 static osync_bool gc_commit_change(OSyncContext *ctx, OSyncChange *change) 400 { 401 struct gc_plgdata *plgdata = (struct gc_plgdata*)osync_context_get_plugin_data(ctx); 444 static void gc_commit_change(void *data, OSyncPluginInfo *info, 445 OSyncContext *ctx, OSyncChange *change) 446 { 447 osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, data, info, ctx, change); 448 449 OSyncObjTypeSink *sink = osync_plugin_info_get_sink(info); 450 struct gc_plgdata *plgdata = data; 402 451 403 452 pid_t pid; … … 409 458 int status; 410 459 char sizeline[1024]; 411 412 osync_hashtable_get_hash(plgdata->hashtable, change); 460 char *hash; 461 462 hash = osync_hashtable_get_hash(plgdata->hashtable, osync_change_get_uid(change)); 413 463 414 464 switch (osync_change_get_changetype(change)) { 415 case CHANGE_ADDED:465 case OSYNC_CHANGE_TYPE_ADDED: 416 466 cmd = "add"; 417 467 arg = NULL; 418 468 break; 419 case CHANGE_MODIFIED:469 case OSYNC_CHANGE_TYPE_MODIFIED: 420 470 cmd = "edit"; 421 arg = osync_change_get_hash(change);471 arg = hash; 422 472 break; 423 case CHANGE_DELETED:473 case OSYNC_CHANGE_TYPE_DELETED: 424 474 cmd = "delete"; 425 arg = osync_change_get_hash(change);475 arg = hash; 426 476 break; 427 477 default: … … 437 487 } 438 488 489 g_free(hash); 490 439 491 out = fdopen(output, "r"); 440 492 if (!out) { … … 445 497 446 498 switch (osync_change_get_changetype(change)) { 447 case CHANGE_ADDED:448 case CHANGE_MODIFIED:499 case OSYNC_CHANGE_TYPE_ADDED: 500 case OSYNC_CHANGE_TYPE_MODIFIED: 449 501 { 450 xmlDoc *doc = (xmlDoc*)osync_change_get_data(change); 451 xmlChar *data; 502 OSyncXMLFormat *doc = (OSyncXMLFormat *)osync_data_get_data_ptr(osync_change_get_data(change)); 452 503 int size; 504 char *buffer; 505 506 osync_xmlformat_assemble(doc, &buffer, &size); 507 osync_trace(TRACE_INTERNAL, "input to helper:\n%s", buffer); 508 if (write(input, buffer, size) < size) { 509 osync_context_report_error(ctx, OSYNC_ERROR_GENERIC, "Couldn't write data to helper"); 510 close(input); 511 g_free(buffer); 512 goto error_write; 513 } 514 515 close(input); 516 g_free(buffer); 517 453 518 int xmlsize, uidsize, hashsize; 454 519 char *xmldata, *uid, *hash; 455 456 xmlDocDumpMemory(doc, &data, &size);457 if (write(input, data, size) < size) {458 osync_context_report_error(ctx, OSYNC_ERROR_GENERIC, "Couldn't write data to helper");459 close(input);460 goto error_write;461 }462 463 close(input);464 520 465 521 if (!fgets(sizeline, sizeof(sizeline), out)) { … … 531 587 } 532 588 break; 533 case CHANGE_DELETED:589 case OSYNC_CHANGE_TYPE_DELETED: 534 590 close(input); 535 591 break; … … 538 594 } 539 595 540 osync_hashtable_update_hash(plgdata->hashtable, change); 596 osync_hashtable_update_hash(plgdata->hashtable, 597 osync_change_get_changetype(change), 598 osync_change_get_uid(change), 599 osync_change_get_hash(change)); 541 600 542 601 fclose(out); … … 551 610 osync_context_report_success(ctx); 552 611 553 return TRUE; 612 osync_trace(TRACE_EXIT, "%s", __func__); 613 return; 554 614 555 615 error_read: … … 560 620 waitpid(pid, NULL, 0); 561 621 error: 622 osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(&error)); 623 return; 624 } 625 626 static void gc_disconnect(void *data, OSyncPluginInfo *info, OSyncContext *ctx) 627 { 628 osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, data, info, ctx); 629 struct gc_plgdata *plgdata = data; 630 631 osync_hashtable_free(plgdata->hashtable); 632 plgdata->hashtable = NULL; 633 634 osync_context_report_success(ctx); 635 osync_trace(TRACE_EXIT, "%s", __func__); 636 } 637 638 static void gc_finalize(void *data) 639 { 640 osync_trace(TRACE_ENTRY, "%s(%p)", __func__, data); 641 struct gc_plgdata *plgdata = data; 642 643 free_plg(plgdata); 644 osync_trace(TRACE_EXIT, "%s", __func__); 645 } 646 647 static void *gc_initialize(OSyncPlugin *plugin, 648 OSyncPluginInfo *info, 649 OSyncError **error) 650 { 651 osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, plugin, info, error); 652 struct gc_plgdata *plgdata; 653 const char *cfg; 654 655 plgdata = osync_try_malloc0(sizeof(struct gc_plgdata), error); 656 if (!plgdata) 657 goto out; 658 659 cfg = osync_plugin_info_get_config(info); 660 if (!cfg) { 661 osync_error_set(error, OSYNC_ERROR_GENERIC, 662 "Unable to get config data."); 663 goto error_freeplg; 664 } 665 666 if (!gc_parse_config(plgdata, cfg, error)) 667 goto error_freeplg; 668 669 OSyncFormatEnv *formatenv = osync_plugin_info_get_format_env(info); 670 plgdata->objformat = osync_format_env_find_objformat(formatenv, "xmlformat-event"); 671 if (!plgdata->objformat) 672 goto error_freeplg; 673 osync_objformat_ref(plgdata->objformat); 674 675 plgdata->sink = osync_objtype_sink_new("event", error); 676 if (!plgdata->sink) 677 goto error_freeplg; 678 679 osync_objtype_sink_add_objformat(plgdata->sink, "xmlformat-event"); 680 681 OSyncObjTypeSinkFunctions functions; 682 memset(&functions, 0, sizeof(functions)); 683 functions.connect = gc_connect; 684 functions.disconnect = gc_disconnect; 685 functions.get_changes = gc_get_changes; 686 functions.commit = gc_commit_change; 687 688 osync_objtype_sink_set_functions(plgdata->sink, functions, plgdata); 689 osync_plugin_info_add_objtype(info, plgdata->sink); 690 691 osync_trace(TRACE_EXIT, "%s", __func__); 692 693 return plgdata; 694 695 error_freeplg: 696 free_plg(plgdata); 697 out: 698 osync_trace(TRACE_EXIT_ERROR, "%s: %s", __func__, osync_error_print(error)); 699 return NULL; 700 } 701 702 static osync_bool gc_discover(void *data, OSyncPluginInfo *info, OSyncError **error) 703 { 704 osync_trace(TRACE_ENTRY, "%s(%p, %p, %p)", __func__, data, info, error); 705 706 struct gc_plgdata *plgdata = data; 707 708 osync_objtype_sink_set_available(plgdata->sink, TRUE); 709 710 OSyncVersion *version = osync_version_new(error); 711 osync_version_set_plugin(version, "google-calendar"); 712 osync_plugin_info_set_version(info, version); 713 osync_version_unref(version); 714 715 osync_trace(TRACE_EXIT, "%s", __func__); 716 return TRUE; 717 } 718 719 osync_bool get_sync_info(OSyncPluginEnv *env, OSyncError **error) 720 { 721 osync_trace(TRACE_ENTRY, "%s(%p, %p)", __func__, env, error); 722 OSyncPlugin *plugin = osync_plugin_new(error); 723 if (!plugin) 724 goto error; 725 726 osync_plugin_set_name(plugin, "google-calendar"); 727 osync_plugin_set_longname(plugin, "Google Calendar"); 728 osync_plugin_set_description(plugin, "Google Calendar plugin"); 729 osync_plugin_set_config_type(plugin, OSYNC_PLUGIN_NEEDS_CONFIGURATION); 730 731 osync_plugin_set_initialize(plugin, gc_initialize); 732 osync_plugin_set_finalize(plugin, gc_finalize); 733 osync_plugin_set_discover(plugin, gc_discover); 734 735 osync_plugin_env_register_plugin(env, plugin); 736 osync_plugin_unref(plugin); 737 738 osync_trace(TRACE_EXIT, "%s", __func__); 739 return TRUE; 740 741 error: 742 osync_trace(TRACE_EXIT_ERROR, "Unable to register: %s", osync_error_print(error)); 743 osync_error_unref(error); 562 744 return FALSE; 563 745 } 564 746 565 static void gc_disconnect(OSyncContext *ctx) 566 { 567 struct gc_plgdata *plgdata = (struct gc_plgdata*)osync_context_get_plugin_data(ctx); 568 569 osync_hashtable_close(plgdata->hashtable); 570 571 osync_context_report_success(ctx); 572 } 573 574 static void gc_finalize(void *data) 575 { 576 struct gc_plgdata *plgdata = (struct gc_plgdata*)data; 577 578 osync_hashtable_free(plgdata->hashtable); 579 g_free(data); 580 } 581 582 void get_info(OSyncEnv *env) 583 { 584 OSyncPluginInfo *info = osync_plugin_new_info(env); 585 info->version = 1; 586 info->name = "google-calendar"; 587 588 info->longname = "Google Calendar"; 589 info->description = "Google Calendar plugin"; 590 info->config_type = NEEDS_CONFIGURATION; 591 592 info->functions.initialize = gc_initialize; 593 info->functions.connect = gc_connect; 594 info->functions.disconnect = gc_disconnect; 595 info->functions.finalize = gc_finalize; 596 info->functions.get_changeinfo = gc_get_changeinfo; 597 598 osync_plugin_accept_objtype(info, "event"); 599 osync_plugin_accept_objformat(info, "event", "xml-event", NULL); 600 osync_plugin_set_commit_objformat(info, "event", "xml-event", gc_commit_change); 601 osync_plugin_set_access_objformat(info, "event", "xml-event", gc_commit_change); 602 } 747 int get_version(void) 748 { 749 return 1; 750 } plugins/google-calendar/src/google-cal-helper.py
r1898 r2345 214 214 self.element = element 215 215 216 self.title = self.elementValue(' Event/Summary/Content/text()')217 self.content = self.elementValue(' Event/Description/Content/text()')218 219 dtstart = self.elementValue(' Event/DateStarted/Content/text()')216 self.title = self.elementValue('Summary/Content/text()') 217 self.content = self.elementValue('Description/Content/text()') 218 219 dtstart = self.elementValue('DateStarted/Content/text()') 220 220 self.dtstart = osyncToXsdate(dtstart) 221 221 222 dtend = self.elementValue(' Event/DateEnd/Content/text()')222 dtend = self.elementValue('DateEnd/Content/text()') 223 223 if not dtend: 224 224 dtend = dtstart 225 225 self.dtend = osyncToXsdate(dtend) 226 226 227 self.whereString = self.elementValue(' Event/Location/Content/text()')227 self.whereString = self.elementValue('Location/Content/text()') 228 228 229 229 #TODO: UID, editUri, dtstart, dtend, recurrency, eventStatus … … 232 232 def dumpOsync(self): 233 233 di = md.getDOMImplementation() 234 doc = di.createDocument(None, 'vcal', None) 235 vcal = doc.documentElement 236 event = self.addElement(doc, vcal, 'Event') 237 238 self.addElementContent(doc, event, 'Summary', self.title) 239 self.addElementContent(doc, event, 'Description', self.content) 234 doc = di.createDocument(None, 'Event', None) 235 event = doc.documentElement 236 237 if self.title: 238 self.addElementContent(doc, event, 'Summary', self.title) 239 if self.content: 240 self.addElementContent(doc, event, 'Description', self.content) 240 241 241 242 self.addElementContent(doc, event, 'DateStarted', xsdateToOsync(self.dtstart)) … … 244 245 self.addElementContent(doc, event, 'RecurrenceRule', 245 246 self.dtrecur) 246 247 self.addElementContent(doc, event, 'Location', self.whereString)247 if self.whereString: 248 self.addElementContent(doc, event, 'Location', self.whereString) 248 249 249 250 #TODO: UID, editUri, dtstart, dtend, eventStatus
