menu: added new Keywords tag to .desktop files
[barry.git] / desktop / src / bsyncjail.cc
blob793c7e2ed5a1a63eaa37b06452b1f2522237e2e6
1 ///
2 /// \file bsyncjail.cc
3 /// Helper program to isolate the actual syncing into its
4 /// own process. Communicates with the main barrydesktop
5 /// via wxWidgets IPC communication. This belongs in its
6 /// own process since the sync can hang, and may need to
7 /// be killed from the GUI.
8 ///
11 Copyright (C) 2010-2013, Net Direct Inc. (http://www.netdirect.ca/)
13 This program is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 2 of the License, or
16 (at your option) any later version.
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
22 See the GNU General Public License in the COPYING file at the
23 root directory of this project for more details.
26 #include <wx/wx.h>
27 #include <iostream>
28 #include <sstream>
29 #include "ipc.h"
30 #include "os22.h"
31 #include "os40.h"
32 #include "tempdir.h"
33 #include "ostypes.h"
34 #include "wxi18n.h"
36 using namespace std;
38 // command line arguments
39 string g_argv_version, g_argv_group_name;
40 OpenSync::Config::pst_type g_sync_types = PST_DO_NOT_SET;
41 SillyBuffer sb;
43 class ClientConnection : public wxConnection
45 public:
46 ClientConnection() {}
49 class Client : public wxClient
51 public:
52 Client() {}
53 ClientConnection* OnMakeConnection()
55 return new ClientConnection;
59 class BarrySyncJail : public OpenSync::SyncStatus
61 private:
62 TempDir m_temp;
63 std::auto_ptr<OpenSync::API> m_engine;
64 std::auto_ptr<wxClient> m_client;
65 wxConnectionBase *m_status_con, *m_conflict_con;
67 // communication variables
68 int m_sequenceID;
69 public:
70 BarrySyncJail();
71 ~BarrySyncJail();
74 // overrides
76 virtual bool OnInit();
77 virtual int OnExit();
80 // OpenSync::SyncStatus virtual overrides
82 virtual void HandleConflict(OpenSync::SyncConflict &conflict);
83 virtual void EntryStatus(const std::string &msg, bool error);
84 virtual void MappingStatus(const std::string &msg, bool error);
85 virtual void EngineStatus(const std::string &msg, bool error,
86 bool slowsync);
87 virtual void MemberStatus(long member_id,
88 const std::string &plugin_name,
89 const std::string &msg, bool error);
90 virtual void CheckSummary(OpenSync::SyncSummary &summary);
91 virtual void ReportError(const std::string &msg);
94 DECLARE_APP(BarrySyncJail)
96 //////////////////////////////////////////////////////////////////////////////
97 // BarrySyncJail
99 BarrySyncJail::BarrySyncJail()
100 : m_temp("bsyncjail")
101 , m_status_con(0)
102 , m_conflict_con(0)
103 , m_sequenceID(0)
105 OnInit();
108 BarrySyncJail::~BarrySyncJail()
112 bool BarrySyncJail::OnInit()
114 cerr << "OnInit()" << endl;
116 // connect to parent app
117 m_client.reset( new Client );
118 m_status_con = m_client->MakeConnection(_T("localhost"),
119 SERVER_SERVICE_NAME, TOPIC_STATUS);
120 m_conflict_con = m_client->MakeConnection(_T("localhost"),
121 SERVER_SERVICE_NAME, TOPIC_CONFLICT);
122 if( !m_status_con || !m_conflict_con ) {
123 cerr << _C("Unable to connect to server.") << endl;
124 return false;
127 // load opensync engine
128 try {
129 if( g_argv_version.substr(0, 3) == "0.2" )
130 m_engine.reset( new OpenSync::OpenSync22 );
131 else {
132 m_engine.reset( new OpenSync::OpenSync40 );
133 if( g_argv_version != m_engine->GetVersion() )
134 throw std::runtime_error(_C("Can't find matching engine for: ") + g_argv_version);
137 catch( std::exception &e ) {
138 m_status_con->Poke(STATUS_ITEM_ERROR, sb.buf(e.what()));
139 cerr << e.what() << endl;
140 return false;
143 if( !m_engine.get() ) {
144 m_status_con->Poke(STATUS_ITEM_ERROR, sb.buf(string(_C("Unknown engine number: ")) + g_argv_version));
145 return false;
148 // start the sync
149 try {
150 m_engine->Discover(g_argv_group_name);
151 m_engine->Sync(g_argv_group_name, *this, g_sync_types);
153 catch( std::exception &e ) {
154 m_status_con->Poke(STATUS_ITEM_ERROR, sb.buf(e.what()));
155 cerr << e.what() << endl;
156 return true;
159 return true;
162 int BarrySyncJail::OnExit()
164 cerr << "OnExit()" << endl;
166 // clean up the client connection... do this early, so that
167 // TempDir can clean up the files if necessary
168 m_client.reset();
170 return 0;
174 // OpenSync::SyncStatus virtual overrides
177 void BarrySyncJail::HandleConflict(OpenSync::SyncConflict &conflict)
179 OpenSync::SyncConflict::iterator i;
180 int size = 0;
181 wxChar *buf = 0;
183 // start with a new sequence ID
184 m_sequenceID++;
185 int offset = 0;
187 // msg 1: sequence ID, offset 0
188 // send available menu / functions possible, and number of
189 // changes that conflict
191 ostringstream oss;
192 oss << m_sequenceID << " " << offset << " " << conflict.size()
193 << " " << "SD";
194 if( conflict.IsAbortSupported() )
195 oss << "A";
196 if( conflict.IsIgnoreSupported() )
197 oss << "I";
198 if( conflict.IsKeepNewerSupported() )
199 oss << "N";
201 if( !m_conflict_con->Poke(CONFLICT_ITEM_START, sb.buf(oss.str())) )
202 goto connection_lost;
204 // all following messages contain the sequence ID,
205 // the change ID, and the change data
206 i = conflict.begin();
207 for( ; i != conflict.end(); ++i ) {
208 oss.str("");
209 offset++;
211 oss << m_sequenceID << " " << offset << " " << i->id << " \n";
212 oss << i->plugin_name << "\n";
213 oss << i->uid << "\n";
214 oss << i->printable_data;
216 if( !m_conflict_con->Poke(CONFLICT_ITEM_CHANGE, sb.buf(oss.str())) )
217 goto connection_lost;
220 // then wait on the server to tell us what choice was made
221 buf = m_conflict_con->Request(CONFLICT_ITEM_ANSWER, &size);
222 if( buf ) {
223 wxString msg(buf);
224 istringstream iss(string(msg.utf8_str()));
225 int sequenceID = 0;
226 string command;
227 int id;
229 iss >> sequenceID >> command;
230 if( !iss || sequenceID != m_sequenceID ) {
231 // invalid command from server, something is wrong
232 throw std::runtime_error(_C("Invalid server response: ") + string(msg.utf8_str()));
235 switch( command[0] )
237 case 'S': // Select
238 iss >> id;
239 if( !iss )
240 throw std::runtime_error(_C("Invalid Select command from server: ") + string(msg.utf8_str()));
241 conflict.Select(id);
242 break;
244 case 'D': // Duplicate
245 conflict.Duplicate();
246 break;
248 case 'A': // Abort
249 if( !conflict.IsAbortSupported() )
250 throw std::runtime_error(_C("Abort not supported, and server sent Abort command."));
251 conflict.Abort();
252 break;
254 case 'I': // Ignore
255 if( !conflict.IsIgnoreSupported() )
256 throw std::runtime_error(_C("Ignore not supported, and server sent Ignore command."));
257 conflict.Ignore();
258 break;
260 case 'N': // Keep Newer
261 if( !conflict.IsKeepNewerSupported() )
262 throw std::runtime_error(_C("Keep Newer not supported, and server sent Keep Newer command."));
263 conflict.KeepNewer();
264 break;
266 default:
267 throw std::runtime_error(_C("Invalid command from server: ") + string(msg.utf8_str()));
270 // all done!
271 return;
274 connection_lost:
275 if( conflict.IsAbortSupported() )
276 conflict.Abort();
277 else
278 throw std::runtime_error(_C("Lost connection with server"));
281 void BarrySyncJail::EntryStatus(const std::string &msg, bool error)
283 if( error )
284 ReportError(msg);
285 else
286 m_status_con->Poke(STATUS_ITEM_ENTRY, sb.buf(msg));
289 void BarrySyncJail::MappingStatus(const std::string &msg, bool error)
291 if( error )
292 ReportError(msg);
293 else
294 m_status_con->Poke(STATUS_ITEM_MAPPING, sb.buf(msg));
297 void BarrySyncJail::EngineStatus(const std::string &msg, bool error, bool slowsync)
299 if( error )
300 ReportError(msg);
301 else
302 m_status_con->Poke(STATUS_ITEM_ENGINE, sb.buf(msg));
304 // slow sync on 0.22 is unreliable... send a special notice
305 // to the GUI
306 if( slowsync && !m_engine->IsSlowSyncSupported() )
307 m_status_con->Poke(STATUS_ITEM_ENGINE, sb.buf(ENGINE_STATUS_SLOW_SYNC));
310 void BarrySyncJail::MemberStatus(long member_id,
311 const std::string &plugin_name,
312 const std::string &msg, bool error)
314 if( error )
315 ReportError(msg);
316 else
317 m_status_con->Poke(STATUS_ITEM_MEMBER, sb.buf(msg));
320 void BarrySyncJail::CheckSummary(OpenSync::SyncSummary &summary)
322 // FIXME: not currently supported... abort every time
323 // cerr << "FIXME: CheckSummary() not implemented, aborting" << endl;
324 // summary.Abort();
325 summary.Continue();
328 void BarrySyncJail::ReportError(const std::string &msg)
330 m_status_con->Poke(STATUS_ITEM_ERROR, sb.buf(msg));
331 cerr << "ReportError(): " << msg << endl;
335 int main(int argc, char *argv[])
337 INIT_I18N(PACKAGE);
339 wxApp::CheckBuildOptions(WX_BUILD_OPTIONS_SIGNATURE, "bsyncjail");
341 cerr << "bsyncjail startup" << endl;
343 if( argc != 4 ) {
344 cerr << _C("This is a helper program for barrydesktop, and\n"
345 "is not intended to be called directly.\n") << endl;
346 return 1;
349 g_argv_version = argv[1];
350 g_argv_group_name = argv[2];
351 g_sync_types = atoi(argv[3]);
353 wxInitializer initializer;
354 if( !initializer ) {
355 cerr << _C("Unable to initialize wxWidgets library, aborting.") << endl;
356 return 1;
359 BarrySyncJail app;
360 int ret = app.OnExit();
361 cerr << _C("bsyncjail exiting with code: ") << ret << endl;
362 return ret;