lib+tools: updated strings to support i18n translations
[barry.git] / desktop / src / os22.cc
blobe602f4b6513190be6554cd7a69684387d0671e4b
1 ///
2 /// \file os22.cc
3 /// Wrapper class for opensync 0.22 syncing behaviour
4 ///
6 /*
7 Copyright (C) 2009-2012, Net Direct Inc. (http://www.netdirect.ca/)
9 Used code from msynctool (GPL v2+) as a guide to the API,
10 and copied some of its status messages and one function directly:
11 static const char *OSyncChangeType2String(OSyncChangeType c);
12 Copyright (C) 2004-2005 Armin Bauer <armin.bauer@opensync.org>
14 This program is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; either version 2 of the License, or
17 (at your option) any later version.
19 This program is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
23 See the GNU General Public License in the COPYING file at the
24 root directory of this project for more details.
27 #include "os22.h"
28 #include "osprivatebase.h"
29 #include "osconv22.h"
30 #include <barry/vsmartptr.h>
31 #include <barry/common.h>
32 #include <iostream>
33 #include <sstream>
34 #include <memory>
35 #include <glib.h>
36 #include "i18n.h"
38 // use relative paths to backtrack enough to specify only 0.22 includes
39 #include <../opensync-1.0/opensync/opensync.h>
40 #include <../opensync-1.0/osengine/engine.h>
42 using namespace std;
43 using namespace Barry;
45 namespace OpenSync {
47 typedef Barry::vLateSmartPtr<OSyncEngine, void(*)(OSyncEngine*)> EngineHandle;
49 class OpenSync22Private
51 public:
52 // function pointers
53 const char* (*osync_get_version)();
54 OSyncEnv* (*osync_env_new)();
55 void (*osync_env_free)(OSyncEnv *env);
56 void (*osync_env_set_option)(OSyncEnv *env,
57 const char *name, const char *value);
58 osync_bool (*osync_env_finalize)(OSyncEnv *env,
59 OSyncError **error);
60 int (*osync_env_num_plugins)(OSyncEnv *env);
61 OSyncPlugin* (*osync_env_nth_plugin)(OSyncEnv *env, int nth);
62 const char* (*osync_plugin_get_name)(OSyncPlugin *plugin);
63 void (*osync_error_free)(OSyncError **error);
64 const char* (*osync_error_print)(OSyncError **error);
65 osync_bool (*osync_env_initialize)(OSyncEnv *env,
66 OSyncError **error);
67 int (*osync_env_num_groups)(OSyncEnv *env);
68 OSyncGroup* (*osync_env_nth_group)(OSyncEnv *env, int nth);
69 const char* (*osync_group_get_name)(OSyncGroup *group);
70 OSyncGroup* (*osync_env_find_group)(OSyncEnv *env,
71 const char *name);
72 int (*osync_group_num_members)(OSyncGroup *group);
73 OSyncMember* (*osync_group_nth_member)(OSyncGroup *group,
74 int nth);
75 long long int (*osync_member_get_id)(OSyncMember *member);
76 const char* (*osync_member_get_pluginname)(
77 OSyncMember *member);
78 OSyncFormatEnv* (*osync_conv_env_new)(OSyncEnv *env);
79 void (*osync_conv_env_free)(OSyncFormatEnv *env);
80 int (*osync_conv_num_objtypes)(OSyncFormatEnv *env);
81 OSyncObjType* (*osync_conv_nth_objtype)(OSyncFormatEnv *env,
82 int nth);
83 int (*osync_conv_num_objformats)(
84 OSyncObjType *type);
85 OSyncObjFormat* (*osync_conv_nth_objformat)(OSyncObjType *type,
86 int nth);
87 const char* (*osync_objformat_get_name)(
88 OSyncObjFormat *format);
89 const char* (*osync_objtype_get_name)(OSyncObjType *type);
90 OSyncGroup* (*osync_group_new)(OSyncEnv *env);
91 void (*osync_group_set_name)(OSyncGroup *group,
92 const char *name);
93 osync_bool (*osync_group_save)(OSyncGroup *group,
94 OSyncError **error);
95 osync_bool (*osync_group_delete)(OSyncGroup *group,
96 OSyncError **error);
97 OSyncMember* (*osync_member_new)(OSyncGroup *group);
98 osync_bool (*osync_member_instance_plugin)(
99 OSyncMember *member,
100 const char *pluginname,
101 OSyncError **error);
102 osync_bool (*osync_member_save)(OSyncMember *member,
103 OSyncError **error);
104 OSyncMember* (*osync_member_from_id)(OSyncGroup *group,
105 int id);
106 osync_bool (*osync_member_need_config)(OSyncMember *member,
107 OSyncConfigurationTypes *type,
108 OSyncError **error);
109 osync_bool (*osync_member_get_config_or_default)(
110 OSyncMember *member,
111 char **data, int *size,
112 OSyncError **error);
113 void (*osync_member_set_config)(OSyncMember *member,
114 const char *data, int size);
115 osync_bool (*osengine_mapping_ignore_supported)(
116 OSyncEngine *engine,
117 OSyncMapping *mapping);
118 osync_bool (*osengine_mapping_check_timestamps)(
119 OSyncEngine *engine,
120 OSyncMapping *mapping,
121 OSyncError **error);
122 OSyncChange* (*osengine_mapping_nth_change)(
123 OSyncMapping *mapping, int nth);
124 void (*osengine_mapping_solve)(OSyncEngine *engine,
125 OSyncMapping *mapping,
126 OSyncChange *change);
127 void (*osengine_mapping_duplicate)(
128 OSyncEngine *engine,
129 OSyncMapping *dupe_mapping);
130 osync_bool (*osengine_mapping_ignore_conflict)(
131 OSyncEngine *engine,
132 OSyncMapping *mapping,
133 OSyncError **error);
134 osync_bool (*osengine_mapping_solve_latest)(
135 OSyncEngine *engine,
136 OSyncMapping *mapping,
137 OSyncError **error);
138 const char* (*osync_change_get_uid)(OSyncChange *change);
139 osync_bool (*osengine_init)(OSyncEngine *engine,
140 OSyncError **error);
141 OSyncMember* (*osync_change_get_member)(OSyncChange *change);
142 int (*osync_change_get_datasize)(
143 OSyncChange *change);
144 OSyncEngine* (*osengine_new)(OSyncGroup *group,
145 OSyncError **error);
146 void (*osengine_free)(OSyncEngine *engine);
147 void (*osengine_finalize)(OSyncEngine *engine);
148 osync_bool (*osengine_sync_and_block)(OSyncEngine *engine,
149 OSyncError **error);
150 void (*osengine_set_memberstatus_callback)(
151 OSyncEngine *engine,
152 void (* function) (OSyncMemberUpdate *,
153 void *),
154 void *user_data);
155 void (*osengine_set_changestatus_callback)(
156 OSyncEngine *engine,
157 void (* function) (OSyncEngine *,
158 OSyncChangeUpdate *,
159 void *),
160 void *user_data);
161 void (*osengine_set_enginestatus_callback)(
162 OSyncEngine *engine,
163 void (* function) (OSyncEngine *,
164 OSyncEngineUpdate *,
165 void *),
166 void *user_data);
167 void (*osengine_set_mappingstatus_callback)(
168 OSyncEngine *engine,
169 void (* function) (OSyncMappingUpdate *,
170 void *),
171 void *user_data);
172 void (*osengine_set_conflict_callback)(
173 OSyncEngine *engine,
174 void (* function) (OSyncEngine *,
175 OSyncMapping *,
176 void *),
177 void *user_data);
178 int (*osengine_mapping_num_changes)(
179 OSyncMapping *mapping);
180 OSyncChangeType (*osync_change_get_changetype)(
181 OSyncChange *change);
182 char* (*osync_change_get_printable)(
183 OSyncChange *change);
184 void (*osync_group_set_objtype_enabled)(
185 OSyncGroup *group,
186 const char *objtypestr,
187 osync_bool enabled);
189 // data pointers
190 OSyncEnv *env;
192 Converter22 converter;
194 OpenSync22Private(OpenSync22 &api)
195 : env(0)
196 , converter(api)
201 class SyncConflict22Private : public SyncConflictPrivateBase
203 OpenSync22Private *m_priv;
204 OSyncEngine *m_engine;
205 OSyncMapping *m_mapping;
207 public:
208 SyncConflict22Private(OpenSync22Private *priv,
209 OSyncEngine *engine, OSyncMapping *mapping);
210 ~SyncConflict22Private();
212 virtual bool IsAbortSupported() const;
213 virtual bool IsIgnoreSupported() const;
214 virtual bool IsKeepNewerSupported() const;
216 virtual void Select(int change_id); // takes id of SyncChange object
217 virtual void Abort(); // not supported in 0.22
218 virtual void Duplicate();
219 virtual void Ignore();
220 virtual void KeepNewer();
222 void AppendChanges(std::vector<SyncChange> &list);
225 struct CallbackBundle22
227 OpenSync22Private *m_priv;
228 SyncStatus *m_status;
230 CallbackBundle22(OpenSync22Private *priv, SyncStatus &status)
231 : m_priv(priv)
232 , m_status(&status)
237 void member_status(OSyncMemberUpdate *, void *);
238 void entry_status(OSyncEngine *, OSyncChangeUpdate *, void *);
239 void engine_status(OSyncEngine *, OSyncEngineUpdate *,void *);
240 void mapping_status(OSyncMappingUpdate *, void *);
241 void conflict_handler(OSyncEngine *, OSyncMapping *, void *);
244 /////////////////////////////////////////////////////////////////////////////
245 // Static helper functions
247 static const char *OSyncChangeType2String(OSyncChangeType c)
249 switch (c) {
250 case CHANGE_ADDED: return _C("ADDED");
251 case CHANGE_UNMODIFIED: return _C("UNMODIFIED");
252 case CHANGE_DELETED: return _C("DELETED");
253 case CHANGE_MODIFIED: return _C("MODIFIED");
254 default:
255 case CHANGE_UNKNOWN: return "?";
259 /////////////////////////////////////////////////////////////////////////////
260 // SyncConflict22Private member functions
262 SyncConflict22Private::SyncConflict22Private(OpenSync22Private *priv,
263 OSyncEngine *engine, OSyncMapping *mapping)
264 : m_priv(priv)
265 , m_engine(engine)
266 , m_mapping(mapping)
270 SyncConflict22Private::~SyncConflict22Private()
274 bool SyncConflict22Private::IsAbortSupported() const
276 return false; // Abort not explicitly supported in 0.22
279 bool SyncConflict22Private::IsIgnoreSupported() const
281 return m_priv->osengine_mapping_ignore_supported(m_engine, m_mapping);
284 bool SyncConflict22Private::IsKeepNewerSupported() const
286 return m_priv->osengine_mapping_check_timestamps(m_engine, m_mapping, NULL);
289 void SyncConflict22Private::Select(int change_id)
291 OSyncChange *change = m_priv->osengine_mapping_nth_change(m_mapping, change_id);
292 if( !change ) {
293 throw std::runtime_error(_C("Bad change_id, or error getting nth change object."));
296 m_priv->osengine_mapping_solve(m_engine, m_mapping, change);
299 void SyncConflict22Private::Abort()
301 throw std::logic_error("Conflict::Abort() not supported in 0.22");
304 void SyncConflict22Private::Duplicate()
306 m_priv->osengine_mapping_duplicate(m_engine, m_mapping);
309 void SyncConflict22Private::Ignore()
311 if( !IsIgnoreSupported() )
312 throw std::logic_error("Ignore not supported, yet Ignore() called.");
314 OSyncError *error = NULL;
315 if( !m_priv->osengine_mapping_ignore_conflict(m_engine, m_mapping, &error)) {
316 ostringstream oss;
317 oss << _C("Conflict not ignored: ")
318 << m_priv->osync_error_print(&error);
319 m_priv->osync_error_free(&error);
320 throw std::runtime_error(oss.str());
324 void SyncConflict22Private::KeepNewer()
326 if( !IsKeepNewerSupported() )
327 throw std::logic_error("Keep Newer not supported, yet KeepNewer() called.");
329 OSyncError *error = NULL;
330 if( !m_priv->osengine_mapping_solve_latest(m_engine, m_mapping, &error)) {
331 ostringstream oss;
332 oss << _C("Conflict not resolved: ")
333 << m_priv->osync_error_print(&error);
334 m_priv->osync_error_free(&error);
335 throw std::runtime_error(oss.str());
339 void SyncConflict22Private::AppendChanges(std::vector<SyncChange> &list)
341 for( int i = 0; i < m_priv->osengine_mapping_num_changes(m_mapping); i++ ) {
342 OSyncChange *change = m_priv->osengine_mapping_nth_change(m_mapping, i);
343 if( m_priv->osync_change_get_changetype(change) != CHANGE_UNKNOWN ) {
345 SyncChange entry;
347 char *printable = m_priv->osync_change_get_printable(change);
348 if( printable ) {
349 entry.printable_data = printable;
350 g_free(printable);
353 OSyncMember *member = m_priv->osync_change_get_member(change);
355 entry.id = i;
356 entry.member_id = m_priv->osync_member_get_id(member);
357 entry.plugin_name = m_priv->osync_member_get_pluginname(member);
358 entry.uid = m_priv->osync_change_get_uid(change);
360 // add to list
361 list.push_back(entry);
367 /////////////////////////////////////////////////////////////////////////////
368 // Callback functions
370 void member_status(OSyncMemberUpdate *status, void *cbdata)
372 CallbackBundle22 *cb = (CallbackBundle22*) cbdata;
374 try {
375 bool error_event = false;
376 bool valid = true;
378 string fmt, trailer;
380 switch( status->type )
382 case MEMBER_CONNECTED:
383 fmt = _C("Member %lld (%s) just connected");
384 break;
385 case MEMBER_DISCONNECTED:
386 fmt = _C("Member %lld (%s) just disconnected");
387 break;
388 case MEMBER_SENT_CHANGES:
389 fmt = _C("Member %lld (%s) just sent all changes");
390 break;
391 case MEMBER_COMMITTED_ALL:
392 fmt = _C("Member %lld (%s) committed all changes");
393 break;
394 case MEMBER_CONNECT_ERROR:
395 fmt = _C("Member %lld (%s) had an error while connecting: %s");
396 trailer = cb->m_priv->osync_error_print(&status->error);
397 break;
398 case MEMBER_GET_CHANGES_ERROR:
399 fmt = _C("Member %lld (%s) had an error while getting changes: %s");
400 trailer = cb->m_priv->osync_error_print(&status->error);
401 error_event = true;
402 break;
403 case MEMBER_SYNC_DONE_ERROR:
404 fmt = _C("Member %lld (%s) had an error while calling sync done: %s");
405 trailer = cb->m_priv->osync_error_print(&status->error);
406 error_event = true;
407 break;
408 case MEMBER_DISCONNECT_ERROR:
409 fmt = _C("Member %lld (%s) had an error while disconnecting: %s");
410 trailer = cb->m_priv->osync_error_print(&status->error);
411 error_event = true;
412 break;
413 case MEMBER_COMMITTED_ALL_ERROR:
414 fmt = _C("Member %lld (%s) had an error while commiting changes: %s");
415 trailer = cb->m_priv->osync_error_print(&status->error);
416 error_event = true;
417 break;
418 default:
419 valid = false;
420 break;
423 // combine the message
424 string msg = string_vprintf(fmt.c_str(),
425 cb->m_priv->osync_member_get_id(status->member),
426 cb->m_priv->osync_member_get_pluginname(status->member),
427 trailer.c_str());
429 // call the status handler
430 if( msg.size() && valid ) {
431 cb->m_status->MemberStatus(
432 cb->m_priv->osync_member_get_id(status->member),
433 cb->m_priv->osync_member_get_pluginname(status->member),
434 msg, error_event);
437 catch( std::exception &e ) {
438 cb->m_status->ReportError(
439 string(_C("member_status error: ")) + e.what());
441 catch( ... ) {
442 cb->m_status->ReportError(
443 _C("Unknown exception caught in member_status()"));
448 void entry_status(OSyncEngine *engine, OSyncChangeUpdate *status, void *cbdata)
450 CallbackBundle22 *cb = (CallbackBundle22*) cbdata;
452 try {
453 OSyncMember *member = cb->m_priv->osync_change_get_member(status->change);
454 bool error_event = false;
456 string msg;
458 switch( status->type )
460 case CHANGE_RECEIVED_INFO:
461 msg = string_vprintf(_C("Received an entry %s without data from member %d (%s). Change type: %s"),
462 cb->m_priv->osync_change_get_uid(status->change),
463 status->member_id,
464 cb->m_priv->osync_member_get_pluginname(member),
465 OSyncChangeType2String(cb->m_priv->osync_change_get_changetype(status->change)));
466 break;
467 case CHANGE_RECEIVED:
468 msg = string_vprintf(_C("Received an entry %s with data of size %d from member %d (%s). Change type: %s"),
469 cb->m_priv->osync_change_get_uid(status->change),
470 cb->m_priv->osync_change_get_datasize(status->change),
471 status->member_id,
472 cb->m_priv->osync_member_get_pluginname(member),
473 OSyncChangeType2String(cb->m_priv->osync_change_get_changetype(status->change)));
474 break;
475 case CHANGE_SENT:
476 msg = string_vprintf(_C("Sent an entry %s of size %d to member %d (%s). Change type: %s"),
477 cb->m_priv->osync_change_get_uid(status->change),
478 cb->m_priv->osync_change_get_datasize(status->change),
479 status->member_id,
480 cb->m_priv->osync_member_get_pluginname(member),
481 OSyncChangeType2String(cb->m_priv->osync_change_get_changetype(status->change)));
482 break;
483 case CHANGE_WRITE_ERROR:
484 error_event = true;
485 msg = string_vprintf(_C("Error writing entry %s to member %d (%s): %s"),
486 cb->m_priv->osync_change_get_uid(status->change),
487 status->member_id,
488 cb->m_priv->osync_member_get_pluginname(member),
489 cb->m_priv->osync_error_print(&status->error));
490 break;
491 case CHANGE_RECV_ERROR:
492 error_event = true;
493 msg = string_vprintf(_C("Error reading entry %s from member %d (%s): %s"),
494 cb->m_priv->osync_change_get_uid(status->change),
495 status->member_id,
496 cb->m_priv->osync_member_get_pluginname(member),
497 cb->m_priv->osync_error_print(&(status->error)));
498 break;
501 // call the status handler
502 if( msg.size() ) {
503 cb->m_status->EntryStatus(msg, error_event);
506 catch( std::exception &e ) {
507 cb->m_status->ReportError(
508 string(_C("entry_status error:")) + e.what());
510 catch( ... ) {
511 cb->m_status->ReportError(
512 _C("Unknown exception caught in entry_status()"));
516 void engine_status(OSyncEngine *engine, OSyncEngineUpdate *status, void *cbdata)
518 CallbackBundle22 *cb = (CallbackBundle22*) cbdata;
520 try {
521 ostringstream oss;
522 bool error_event = false;
524 switch( status->type )
526 case ENG_PREV_UNCLEAN:
527 oss << _C("The previous synchronization was unclean. Slow-syncing.");
528 break;
529 case ENG_ENDPHASE_CON:
530 oss << _C("All clients connected or error");
531 break;
532 case ENG_END_CONFLICTS:
533 oss << _C("All conflicts have been reported");
534 break;
535 case ENG_ENDPHASE_READ:
536 oss << _C("All clients sent changes or error");
537 break;
538 case ENG_ENDPHASE_WRITE:
539 oss << _C("All clients have written");
540 break;
541 case ENG_ENDPHASE_DISCON:
542 oss << _C("All clients have disconnected");
543 break;
544 case ENG_SYNC_SUCCESSFULL:
545 oss << _C("The sync was successful");
546 break;
547 case ENG_ERROR:
548 oss << _C("The sync failed: ")
549 << cb->m_priv->osync_error_print(&status->error);
550 error_event = true;
551 break;
554 // call the status handler
555 if( oss.str().size() )
556 cb->m_status->EngineStatus(oss.str(),
557 error_event,
558 status->type == ENG_PREV_UNCLEAN);
560 catch( std::exception &e ) {
561 cb->m_status->ReportError(
562 string(_C("engine_status error: ")) + e.what());
564 catch( ... ) {
565 cb->m_status->ReportError(
566 _C("Unknown exception caught in engine_status()"));
570 void mapping_status(OSyncMappingUpdate *status, void *cbdata)
572 CallbackBundle22 *cb = (CallbackBundle22*) cbdata;
574 try {
575 ostringstream oss;
576 bool error_event = false;
578 switch( status->type )
580 case MAPPING_SOLVED:
581 oss << _C("Mapping solved");
582 break;
583 case MAPPING_SYNCED:
584 oss << _C("Mapping Synced");
585 break;
586 case MAPPING_WRITE_ERROR:
587 error_event = true;
588 oss << _C("Mapping Write Error: ")
589 << cb->m_priv->osync_error_print(&status->error);
590 break;
593 // call the status handler
594 if( oss.str().size() )
595 cb->m_status->MappingStatus(oss.str(), error_event);
597 catch( std::exception &e ) {
598 cb->m_status->ReportError(
599 string(_C("mapping_status error: ")) + e.what());
601 catch( ... ) {
602 cb->m_status->ReportError(
603 _C("Unknown exception caught in mapping_status()"));
607 void conflict_handler(OSyncEngine *engine, OSyncMapping *mapping, void *cbdata)
609 CallbackBundle22 *cb = (CallbackBundle22*) cbdata;
611 try {
612 // build the SyncConflict object
613 SyncConflict22Private scp(cb->m_priv, engine, mapping);
614 SyncConflict conflict(scp);
616 // append all conflicting changes as vector objects in the same
617 // order as the opensync library mapping
618 scp.AppendChanges(conflict);
620 // call the status handler
621 cb->m_status->HandleConflict(conflict);
623 catch( std::exception &e ) {
624 cb->m_status->ReportError(
625 string(_C("Conflict not resolved. ")) + e.what());
627 catch( ... ) {
628 cb->m_status->ReportError(
629 _C("Unknown exception caught in conflict_handler()"));
634 /////////////////////////////////////////////////////////////////////////////
635 // OpenSync22 - public members
637 bool OpenSync22::symbols_loaded = false;
639 OpenSync22::OpenSync22()
641 if( !Open("libosengine.so.0") )
642 throw DlError("Can't dlopen libosengine.so.0");
644 // the symbol table is now thoroughly polluted...
645 symbols_loaded = true;
647 // store locally in case of constructor exception in LoadSym
648 std::auto_ptr<OpenSync22Private> p(new OpenSync22Private(*this));
650 // load all required symbols...
651 // we don't need to use try/catch here, since the base
652 // class destructor will clean up for us if LoadSym() throws
653 LoadSym(p->osync_get_version, "osync_get_version");
654 LoadSym(p->osync_env_new, "osync_env_new");
655 LoadSym(p->osync_env_free, "osync_env_free");
656 LoadSym(p->osync_env_set_option, "osync_env_set_option");
657 LoadSym(p->osync_env_finalize, "osync_env_finalize");
658 LoadSym(p->osync_env_num_plugins, "osync_env_num_plugins");
659 LoadSym(p->osync_env_nth_plugin, "osync_env_nth_plugin");
660 LoadSym(p->osync_plugin_get_name, "osync_plugin_get_name");
661 LoadSym(p->osync_error_free, "osync_error_free");
662 LoadSym(p->osync_error_print, "osync_error_print");
663 LoadSym(p->osync_env_initialize, "osync_env_initialize");
664 LoadSym(p->osync_env_num_groups, "osync_env_num_groups");
665 LoadSym(p->osync_env_nth_group, "osync_env_nth_group");
666 LoadSym(p->osync_group_get_name, "osync_group_get_name");
667 LoadSym(p->osync_env_find_group, "osync_env_find_group");
668 LoadSym(p->osync_group_num_members, "osync_group_num_members");
669 LoadSym(p->osync_group_nth_member, "osync_group_nth_member");
670 LoadSym(p->osync_member_get_id, "osync_member_get_id");
671 LoadSym(p->osync_member_get_pluginname, "osync_member_get_pluginname");
672 LoadSym(p->osync_conv_env_new, "osync_conv_env_new");
673 LoadSym(p->osync_conv_env_free, "osync_conv_env_free");
674 LoadSym(p->osync_conv_num_objtypes, "osync_conv_num_objtypes");
675 LoadSym(p->osync_conv_nth_objtype, "osync_conv_nth_objtype");
676 LoadSym(p->osync_conv_num_objformats, "osync_conv_num_objformats");
677 LoadSym(p->osync_conv_nth_objformat, "osync_conv_nth_objformat");
678 LoadSym(p->osync_objformat_get_name, "osync_objformat_get_name");
679 LoadSym(p->osync_objtype_get_name, "osync_objtype_get_name");
680 LoadSym(p->osync_group_new, "osync_group_new");
681 LoadSym(p->osync_group_set_name, "osync_group_set_name");
682 LoadSym(p->osync_group_save, "osync_group_save");
683 LoadSym(p->osync_group_delete, "osync_group_delete");
684 LoadSym(p->osync_member_new, "osync_member_new");
685 LoadSym(p->osync_member_instance_plugin,"osync_member_instance_plugin");
686 LoadSym(p->osync_member_save, "osync_member_save");
687 LoadSym(p->osync_member_from_id, "osync_member_from_id");
688 LoadSym(p->osync_member_need_config, "osync_member_need_config");
689 LoadSym(p->osync_member_get_config_or_default,
690 "osync_member_get_config_or_default");
691 LoadSym(p->osync_member_set_config, "osync_member_set_config");
692 LoadSym(p->osengine_mapping_ignore_supported,
693 "osengine_mapping_ignore_supported");
694 LoadSym(p->osengine_mapping_check_timestamps,
695 "osengine_mapping_check_timestamps");
696 LoadSym(p->osengine_mapping_nth_change, "osengine_mapping_nth_change");
697 LoadSym(p->osengine_mapping_solve, "osengine_mapping_solve");
698 LoadSym(p->osengine_mapping_duplicate, "osengine_mapping_duplicate");
699 LoadSym(p->osengine_mapping_ignore_conflict,
700 "osengine_mapping_ignore_conflict");
701 LoadSym(p->osengine_mapping_solve_latest,
702 "osengine_mapping_solve_latest");
703 LoadSym(p->osync_change_get_uid, "osync_change_get_uid");
704 LoadSym(p->osengine_init, "osengine_init");
705 LoadSym(p->osync_change_get_member, "osync_change_get_member");
706 LoadSym(p->osync_change_get_datasize, "osync_change_get_datasize");
707 LoadSym(p->osengine_new, "osengine_new");
708 LoadSym(p->osengine_free, "osengine_free");
709 LoadSym(p->osengine_finalize, "osengine_finalize");
710 LoadSym(p->osengine_sync_and_block, "osengine_sync_and_block");
711 LoadSym(p->osengine_set_memberstatus_callback,
712 "osengine_set_memberstatus_callback");
713 LoadSym(p->osengine_set_changestatus_callback,
714 "osengine_set_changestatus_callback");
715 LoadSym(p->osengine_set_enginestatus_callback,
716 "osengine_set_enginestatus_callback");
717 LoadSym(p->osengine_set_mappingstatus_callback,
718 "osengine_set_mappingstatus_callback");
719 LoadSym(p->osengine_set_conflict_callback,
720 "osengine_set_conflict_callback");
721 LoadSym(p->osengine_mapping_num_changes,
722 "osengine_mapping_num_changes");
723 LoadSym(p->osync_change_get_changetype, "osync_change_get_changetype");
724 LoadSym(p->osync_change_get_printable, "osync_change_get_printable");
725 LoadSym(p->osync_group_set_objtype_enabled,
726 "osync_group_set_objtype_enabled");
728 // do common initialization of opensync environment
729 SetupEnvironment(p.get());
731 // this pointer is ours now
732 m_priv = p.release();
735 OpenSync22::~OpenSync22()
737 // clean up opensync environment, closing plugins, etc.
738 if( m_priv->env ) {
739 m_priv->osync_env_finalize(m_priv->env, NULL);
740 m_priv->osync_env_free(m_priv->env);
743 // free private class data
744 delete m_priv;
745 m_priv = 0;
748 void OpenSync22::SetupEnvironment(OpenSync22Private *p)
750 // we are fully responsible for this pointer, since
751 // we run inside the constructor... only on success
752 // will responsibility be transferred to the destructor
753 p->env = p->osync_env_new();
754 if( !p->env )
755 throw std::runtime_error(_C("Error allocating opensync 0.22 environment"));
757 p->osync_env_set_option(p->env, "GROUPS_DIRECTORY", NULL);
758 p->osync_env_set_option(p->env, "LOAD_GROUPS", "TRUE");
759 p->osync_env_set_option(p->env, "LOAD_PLUGINS", "TRUE");
760 p->osync_env_set_option(p->env, "LOAD_FORMATS", "TRUE");
762 OSyncError *error = NULL;
763 if( !p->osync_env_initialize(p->env, &error) ) {
764 // grab error message
765 std::runtime_error err(m_priv->osync_error_print(&error));
767 // cleanup
768 p->osync_error_free(&error);
769 p->osync_env_free(m_priv->env);
771 // throw
772 throw err;
776 const char* OpenSync22::GetVersion() const
778 return m_priv->osync_get_version();
781 const char* OpenSync22::GetEngineName() const
783 return "0.22";
786 void OpenSync22::GetPluginNames(string_list_type &plugins)
788 // start fresh
789 plugins.clear();
791 OSyncPlugin *p;
792 for( int i = 0; i < m_priv->osync_env_num_plugins(m_priv->env); i++) {
793 p = m_priv->osync_env_nth_plugin(m_priv->env, i);
794 plugins.push_back(m_priv->osync_plugin_get_name(p));
798 void OpenSync22::GetFormats(format_list_type &formats)
800 // start fresh
801 formats.clear();
803 // cycle through all object types and simulate a 0.4x-like
804 // list based on the attached formats
806 OSyncFormatEnv *fenv = m_priv->osync_conv_env_new(m_priv->env);
807 if( !fenv ) {
808 throw std::runtime_error(string("GetFormats(): ") + _C("Unable to load format environment in GetFormats (22)"));
811 for( int i = 0; i < m_priv->osync_conv_num_objtypes(fenv); i++ ) {
812 OSyncObjType *type = m_priv->osync_conv_nth_objtype(fenv, i);
814 for( int i = 0; i < m_priv->osync_conv_num_objformats(type); i++ ) {
815 OSyncObjFormat *format = m_priv->osync_conv_nth_objformat(type, i);
816 const char *objformat_name = m_priv->osync_objformat_get_name(format);
818 if( !formats.Find(objformat_name) ) {
819 Format new_format;
820 new_format.name = objformat_name;
821 new_format.object_type = m_priv->osync_objtype_get_name(type);
822 formats.push_back(new_format);
827 m_priv->osync_conv_env_free(fenv);
830 void OpenSync22::GetGroupNames(string_list_type &groups)
832 // start fresh
833 groups.clear();
835 OSyncGroup *g;
836 for( int i = 0; i < m_priv->osync_env_num_groups(m_priv->env); i++ ) {
837 g = m_priv->osync_env_nth_group(m_priv->env, i);
838 groups.push_back(m_priv->osync_group_get_name(g));
842 void OpenSync22::GetMembers(const std::string &group_name,
843 member_list_type &members)
845 // start fresh
846 members.clear();
848 OSyncGroup *group = m_priv->osync_env_find_group(m_priv->env, group_name.c_str());
849 if( !group ) {
850 throw std::runtime_error(string("GetMembers(): ") + _C("Unable to find group with name: ") + group_name);
853 for( int i = 0; i < m_priv->osync_group_num_members(group); i++ ) {
854 OSyncMember *member = m_priv->osync_group_nth_member(group, i);
856 Member new_member;
858 new_member.group_name = group_name;
859 new_member.id = m_priv->osync_member_get_id(member);
860 new_member.plugin_name = m_priv->osync_member_get_pluginname(member);
862 // we are switching opensync's long long int ID to
863 // our long... to double check they are equal after
864 // the conversion
865 if( new_member.id != m_priv->osync_member_get_id(member) ) {
866 throw std::logic_error("GetMembers(): OpenSync's member ID is too large to fit in OpenSyncAPI (22)");
869 // add to member list
870 members.push_back(new_member);
874 void OpenSync22::AddGroup(const std::string &group_name)
876 if( m_priv->osync_env_find_group(m_priv->env, group_name.c_str()) )
877 throw std::runtime_error(string("AddGroup(): ") + _C("Group already exists: ") + group_name);
879 OSyncGroup *group = m_priv->osync_group_new(m_priv->env);
880 m_priv->osync_group_set_name(group, group_name.c_str());
882 OSyncError *error = NULL;
883 if( !m_priv->osync_group_save(group, &error) ) {
884 // grab error message
885 std::runtime_error err(string("AddGroup(): ") + _C("Unable to save group: ") + m_priv->osync_error_print(&error));
887 // cleanup
888 m_priv->osync_error_free(&error);
890 throw err;
894 void OpenSync22::DeleteGroup(const std::string &group_name)
896 OSyncGroup *group = m_priv->osync_env_find_group(m_priv->env, group_name.c_str());
897 if( !group )
898 throw std::runtime_error(string("DeleteGroup(): ") + _C("Group not found: ") + group_name);
900 OSyncError *error = NULL;
901 if( !m_priv->osync_group_delete(group, &error) ) {
902 std::runtime_error err(string("DeleteGroup(): ") + _C("Unable to delete group: ") + m_priv->osync_error_print(&error));
903 m_priv->osync_error_free(&error);
904 throw err;
908 Converter& OpenSync22::GetConverter()
910 return m_priv->converter;
913 long OpenSync22::AddMember(const std::string &group_name,
914 const std::string &plugin_name,
915 const std::string &member_name)
917 OSyncGroup *group = m_priv->osync_env_find_group(m_priv->env, group_name.c_str());
918 if( !group )
919 throw std::runtime_error(string("AddMember(): ") + _C("Group not found: ") + group_name);
921 OSyncMember *member = m_priv->osync_member_new(group);
923 OSyncError *error = NULL;
924 if( !m_priv->osync_member_instance_plugin(member, plugin_name.c_str(), &error) ) {
925 std::runtime_error err(string("AddMember(): ") + _C("Unable to connect plugin with member: ") + member_name + "/" + plugin_name + ": " + m_priv->osync_error_print(&error));
926 m_priv->osync_error_free(&error);
927 throw err;
930 if( !m_priv->osync_member_save(member, &error) ) {
931 std::runtime_error err(string("AddMember(): ") + _C("Unable to save member: ") + member_name + "/" + plugin_name + ": " + m_priv->osync_error_print(&error));
932 m_priv->osync_error_free(&error);
933 throw err;
936 return m_priv->osync_member_get_id(member);
939 bool OpenSync22::IsConfigurable(const std::string &group_name,
940 long member_id)
942 OSyncGroup *group = m_priv->osync_env_find_group(m_priv->env, group_name.c_str());
943 if( !group )
944 throw std::runtime_error(_C("Group not found: ") + group_name);
946 OSyncMember *member = m_priv->osync_member_from_id(group, member_id);
947 if( !member ) {
948 ostringstream oss;
949 oss << "IsConfigurable(): " << _C("Member not found: ") << member_id;
950 throw std::runtime_error(oss.str());
953 OSyncConfigurationTypes type = NO_CONFIGURATION;
954 OSyncError *error = NULL;
955 if( !m_priv->osync_member_need_config(member, &type, &error) ) {
956 std::runtime_error err(string(_C("Unable to determine needed config: ")) + m_priv->osync_error_print(&error));
957 m_priv->osync_error_free(&error);
958 throw err;
961 return type != NO_CONFIGURATION;
964 std::string OpenSync22::GetConfiguration(const std::string &group_name,
965 long member_id)
967 if( !IsConfigurable(group_name, member_id) ) {
968 throw std::runtime_error(string("GetConfiguration(): ") + string_vprintf(_C("Member %ld of group '%s' does not accept configuration."),
969 member_id,
970 group_name.c_str()));
973 OSyncGroup *group = m_priv->osync_env_find_group(m_priv->env, group_name.c_str());
974 if( !group )
975 throw std::runtime_error(string("GetConfiguration(): ") + _C("Group not found: ") + group_name);
977 OSyncMember *member = m_priv->osync_member_from_id(group, member_id);
978 if( !member ) {
979 throw std::runtime_error(string("GetConfiguration(): ") + string_vprintf(_C("Member %ld not found."), member_id));
982 OSyncError *error = NULL;
983 char *data = NULL;
984 int size = 0;
985 if( !m_priv->osync_member_get_config_or_default(member, &data, &size, &error)) {
986 std::runtime_error err(string("GetConfiguration(): ") + _C("Unable to retrieve config: ") + m_priv->osync_error_print(&error));
987 m_priv->osync_error_free(&error);
988 throw err;
991 std::string config(data, size);
992 g_free(data);
994 return config;
997 void OpenSync22::SetConfiguration(const std::string &group_name,
998 long member_id,
999 const std::string &config_data)
1001 if( !IsConfigurable(group_name, member_id) ) {
1002 throw std::runtime_error(string("SetConfiguration(): ") + string_vprintf(_C("Member %ld of group '%s' does not accept configuration."),
1003 member_id,
1004 group_name.c_str()));
1007 OSyncGroup *group = m_priv->osync_env_find_group(m_priv->env, group_name.c_str());
1008 if( !group )
1009 throw std::runtime_error(string("SetConfiguration(): ") + _C("Group not found: ") + group_name);
1011 OSyncMember *member = m_priv->osync_member_from_id(group, member_id);
1012 if( !member ) {
1013 throw std::runtime_error(string("SetConfiguration(): ") + string_vprintf(_C("Member %ld not found."), member_id));
1016 m_priv->osync_member_set_config(member, config_data.c_str(), config_data.size());
1018 OSyncError *error = NULL;
1019 if( !m_priv->osync_member_save(member, &error) ) {
1020 std::runtime_error err(string("SetConfiguration(): ") + _C("Unable to save member's config: ") + m_priv->osync_error_print(&error));
1021 m_priv->osync_error_free(&error);
1022 throw err;
1026 void OpenSync22::Discover(const std::string &group_name)
1028 // Discover is a successful noop on 0.22
1031 void OpenSync22::Sync(const std::string &group_name,
1032 SyncStatus &status_callback,
1033 Config::pst_type sync_types)
1035 OSyncGroup *group = m_priv->osync_env_find_group(m_priv->env, group_name.c_str());
1036 if( !group )
1037 throw std::runtime_error(string("Sync(): ") + _C("Group not found: ") + group_name);
1039 // enable/disable each objtype, as per sync_types
1040 if( !(sync_types & PST_DO_NOT_SET) ) {
1041 cerr << "enabling objtypes: " << sync_types << endl;
1042 m_priv->osync_group_set_objtype_enabled(group, "contact",
1043 (sync_types & PST_CONTACTS) ? TRUE : FALSE);
1044 m_priv->osync_group_set_objtype_enabled(group, "event",
1045 (sync_types & PST_EVENTS) ? TRUE : FALSE);
1046 m_priv->osync_group_set_objtype_enabled(group, "note",
1047 (sync_types & PST_NOTES) ? TRUE : FALSE);
1048 m_priv->osync_group_set_objtype_enabled(group, "todo",
1049 (sync_types & PST_TODOS) ? TRUE : FALSE);
1052 OSyncError *error = NULL;
1053 EngineHandle engine(m_priv->osengine_free);
1054 engine = m_priv->osengine_new(group, &error);
1055 if( !engine.get() ) {
1056 std::ostringstream oss;
1057 oss << _C("Error while synchronizing: ")
1058 << m_priv->osync_error_print(&error);
1059 m_priv->osync_error_free(&error);
1060 throw std::runtime_error(oss.str());
1063 CallbackBundle22 cbdata(m_priv, status_callback);
1065 m_priv->osengine_set_memberstatus_callback(engine.get(),
1066 &member_status, &cbdata);
1067 m_priv->osengine_set_changestatus_callback(engine.get(),
1068 &entry_status, &cbdata);
1069 m_priv->osengine_set_enginestatus_callback(engine.get(),
1070 &engine_status, &cbdata);
1071 m_priv->osengine_set_mappingstatus_callback(engine.get(),
1072 &mapping_status, &cbdata);
1073 m_priv->osengine_set_conflict_callback(engine.get(),
1074 &conflict_handler, &cbdata);
1076 if( !m_priv->osengine_init(engine.get(), &error) ) {
1077 ostringstream oss;
1078 oss << _C("Error initializing osengine: ")
1079 << m_priv->osync_error_print(&error);
1080 m_priv->osync_error_free(&error);
1081 throw std::runtime_error(oss.str());
1084 // successfully initialized, so finalize must be called
1085 EngineHandle initialized_engine(m_priv->osengine_finalize);
1086 initialized_engine = engine.get();
1088 if( !m_priv->osengine_sync_and_block(engine.get(), &error) ) {
1089 ostringstream oss;
1090 oss << _C("Error during sync: ")
1091 << m_priv->osync_error_print(&error);
1092 m_priv->osync_error_free(&error);
1093 throw std::runtime_error(oss.str());
1097 } // namespace OpenSync