tools: add playbook driver switch
[barry/progweb.git] / opensync-plugin / src / environment.cc
blob81cba7c5757898f9799819bdfaf8bd0f2110fe63
1 //
2 // \file environment.cc
3 // Container / environment class for the sync module.
4 //
6 /*
7 Copyright (C) 2006-2012, Net Direct Inc. (http://www.netdirect.ca/)
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 See the GNU General Public License in the COPYING file at the
19 root directory of this project for more details.
22 #include "environment.h"
23 #include "trace.h"
24 #include <glib.h>
25 #include <string>
26 #include <fstream>
27 #include <sstream>
28 #include <iomanip>
29 #include <string.h>
30 #include <unistd.h>
32 using namespace Barry;
34 //////////////////////////////////////////////////////////////////////////////
35 // DatabaseSyncState
37 DatabaseSyncState::DatabaseSyncState(OSyncMember *pm, const char *description)
38 : m_dbId(0),
39 m_Sync(false),
40 m_Desc(description)
42 m_CacheFilename = m_MapFilename =
43 osync_member_get_configdir(pm);
44 m_CacheFilename += "/barry_" + m_Desc + "_cache.txt";
45 m_MapFilename += "/barry_" + m_Desc + "_idmap.txt";
48 DatabaseSyncState::~DatabaseSyncState()
52 bool DatabaseSyncState::LoadCache()
54 Trace trace("LoadCache", m_Desc.c_str());
56 m_Cache.clear();
57 std::ifstream ifs(m_CacheFilename.c_str());
58 if( !ifs )
59 return false;
61 while( ifs ) {
62 uint32_t recordId = 0;
63 ifs >> recordId;
64 if( recordId ) {
65 m_Cache[recordId] = false;
69 if( !ifs.eof() ) {
70 m_Cache.clear(); // assume full sync
71 trace.log("Load failed!");
72 return false;
74 return true;
77 bool DatabaseSyncState::SaveCache()
79 Trace trace("SaveCache", m_Desc.c_str());
81 std::ofstream ofs(m_CacheFilename.c_str());
82 if( !ofs )
83 return false;
85 cache_type::const_iterator i = m_Cache.begin();
86 for( ; i != m_Cache.end(); ++i ) {
87 ofs << i->first << std::endl;
89 return !ofs.bad() && !ofs.fail();
92 bool DatabaseSyncState::LoadMap()
94 return m_IdMap.Load(m_MapFilename.c_str());
97 bool DatabaseSyncState::SaveMap()
99 return m_IdMap.Save(m_MapFilename.c_str());
102 // cycle through the map and search the state table for each rid,
103 // and remove any that do not exist
104 void DatabaseSyncState::CleanupMap()
106 idmap::iterator i = m_IdMap.begin();
107 for( ; i != m_IdMap.end(); ++i ) {
108 if( !m_Table.GetIndex(i->second) ) {
109 // Record Id does not exist in state table, so it is
110 // not needed anymore in the ID map
111 m_IdMap.Unmap(i);
117 // Map2Uid
119 /// Searches for the given record ID, and returns the mapped UID. If not
120 /// found, it creates a new UID and returns it without mapping it.
122 std::string DatabaseSyncState::Map2Uid(uint32_t recordId) const
124 // search the idmap for the UID
125 std::string uid;
126 idmap::const_iterator mapped_id;
127 if( m_IdMap.RidExists(recordId, &mapped_id) ) {
128 uid = mapped_id->first;
130 else {
131 // not mapped, map it ourselves
132 char *puid = g_strdup_printf("%s-%u", m_Desc.c_str(), recordId);
133 uid = puid;
134 g_free(puid);
136 return uid;
139 unsigned long DatabaseSyncState::GetMappedRecordId(const std::string &uid)
141 Trace trace("DatabaseSyncState::GetMappedRecordId()", m_Desc.c_str());
143 // if already in map, use the matching rid
144 idmap::const_iterator it;
145 if( m_IdMap.UidExists(uid, &it) ) {
146 trace.logf("found existing uid in map: %lu", it->second);
147 return it->second;
150 // nothing in the map, so try to convert the string to a number
151 unsigned long RecordId;
152 if( sscanf(uid.c_str(), "%lu", &RecordId) != 0 ) {
153 trace.logf("parsed uid as: %lu", RecordId);
154 if( m_IdMap.Map(uid, RecordId) != m_IdMap.end() )
155 return RecordId;
157 trace.logf("parsed uid already exists in map, skipping");
160 // create one of our own, if we get here...
161 // do this in a loop to keep going until we find an ID that's unique
162 do {
163 RecordId = m_Table.MakeNewRecordId();
164 } while( m_IdMap.Map(uid, RecordId) == m_IdMap.end() );
166 trace.logf("made new record id: %lu", RecordId);
167 return RecordId;
172 //////////////////////////////////////////////////////////////////////////////
173 // BarryEnvironment Public API
175 BarryEnvironment::BarryEnvironment(OSyncMember *pm)
176 : member(pm),
177 m_pin(-1),
178 m_DebugMode(false),
179 m_CalendarSync(pm, "calendar"),
180 m_ContactsSync(pm, "contacts")
184 BarryEnvironment::~BarryEnvironment()
188 void BarryEnvironment::DoConnect()
190 if( !m_con.get() )
191 throw std::logic_error("Tried to use empty Connector");
193 m_con->Connect();
195 // Save the DBIDs and DBNames of the databases we will work with
196 if( m_CalendarSync.m_Sync ) {
197 m_CalendarSync.m_dbName = Barry::Calendar::GetDBName();
198 m_CalendarSync.m_dbId = m_con->GetDesktop().GetDBID(Barry::Calendar::GetDBName());
201 if( m_ContactsSync.m_Sync ) {
202 m_ContactsSync.m_dbId = m_con->GetDesktop().GetDBID(Barry::Contact::GetDBName());
203 m_ContactsSync.m_dbName = Barry::Contact::GetDBName();
207 void BarryEnvironment::SetPassword(const std::string &password)
209 m_password = password;
210 if( m_con.get() )
211 m_con->SetPassword(password.c_str());
214 void BarryEnvironment::Connect(const Barry::ProbeResult &result)
216 m_con.reset(new DesktopConnector(m_password.c_str(), "UTF-8", result));
217 DoConnect();
220 void BarryEnvironment::Reconnect()
222 m_con->Reconnect(2);
225 void BarryEnvironment::Disconnect()
227 m_con->Disconnect();
230 void BarryEnvironment::ClearDirtyFlags(Barry::RecordStateTable &table,
231 const std::string &dbname)
233 Trace trace("ClearDirtyFlags");
235 unsigned int dbId = m_con->GetDesktop().GetDBID(dbname);
237 Barry::RecordStateTable::StateMapType::const_iterator i = table.StateMap.begin();
238 for( ; i != table.StateMap.end(); ++i ) {
239 if( i->second.Dirty ) {
240 trace.logf("Clearing dirty flag for db %u, index %u",
241 dbId, i->first);
242 m_con->GetDesktop().ClearDirty(dbId, i->first);
247 void BarryEnvironment::ClearCalendarDirtyFlags()
249 Trace trace("ClearCalendarDirtyFlags");
250 ClearDirtyFlags(m_CalendarSync.m_Table, Barry::Calendar::GetDBName());
253 void BarryEnvironment::ClearContactsDirtyFlags()
255 Trace trace("ClearContactsDirtyFlags");
256 ClearDirtyFlags(m_ContactsSync.m_Table, Barry::Contact::GetDBName());
259 DatabaseSyncState* BarryEnvironment::GetSyncObject(OSyncChange *change)
261 Trace trace("BarryEnvironment::GetSyncObject()");
263 OSyncObjType *type = osync_change_get_objtype(change);
264 const char *name = osync_objtype_get_name(type);
265 if( strcmp(name, "event") == 0 ) {
266 return &m_CalendarSync;
268 else if( strcmp(name, "contact") == 0 ) {
269 return &m_ContactsSync;
271 else {
272 return 0;
276 void BarryEnvironment::ParseConfig(const char *data, int size)
278 Trace trace("ParseConfig");
280 m_ConfigData.assign(data, size);
282 // The config data should contain:
283 // - Keyword: DebugMode
284 // - if the single word "DebugMode" is found, enable Debug
286 // - Keyword: Device <pin> ...
287 // - PIN of device to sync with
288 // - or a flag that says "autoconfig with first device found"
289 // which will autodetect, and update the config
290 // automatically with the found PIN... all future syncs
291 // will then have a PIN
292 // - checkboxes for (both can be on):
293 // - sync calendar items
294 // - sync contacts
296 std::istringstream iss(m_ConfigData);
297 std::string line;
298 while( std::getline(iss, line) ) {
300 if( line[0] == '#' )
301 continue;
303 std::istringstream ils(line);
304 int cal = 0, con = 0;
306 std::string key;
307 ils >> key;
309 if( key == "DebugMode" ) {
310 m_DebugMode = true;
312 else if( key == "Device" ) {
313 ils >> std::hex >> m_pin >> cal >> con;
315 std::ostringstream oss;
316 oss << std::hex << m_pin;
317 trace.log(oss.str().c_str());
319 if( cal ) {
320 m_CalendarSync.m_Sync = true;
321 trace.log("calendar syncing enabled");
324 if( con ) {
325 m_ContactsSync.m_Sync = true;
326 trace.log("contacts syncing enabled");
329 else if ( key == "Password" ) {
330 ils >> m_password;
331 trace.log("using password from config file");
336 //void BarryEnvironment::BuildConfig()
338 // FIXME - build back into one long string