Bumped copyright dates for 2013
[barry.git] / opensync-plugin / src / environment.cc
blobbcb1bf7edd32dd44e8f501d63768edd46e2eac03
1 //
2 // \file environment.cc
3 // Container / environment class for the sync module.
4 //
6 /*
7 Copyright (C) 2006-2013, 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>
31 #include "i18n.h"
33 using namespace Barry;
35 //////////////////////////////////////////////////////////////////////////////
36 // DatabaseSyncState
38 DatabaseSyncState::DatabaseSyncState(OSyncMember *pm, const char *description)
39 : m_dbId(0),
40 m_Sync(false),
41 m_Desc(description)
43 m_CacheFilename = m_MapFilename =
44 osync_member_get_configdir(pm);
45 m_CacheFilename += "/barry_" + m_Desc + "_cache.txt";
46 m_MapFilename += "/barry_" + m_Desc + "_idmap.txt";
49 DatabaseSyncState::~DatabaseSyncState()
53 bool DatabaseSyncState::LoadCache()
55 Trace trace("LoadCache", m_Desc.c_str());
57 m_Cache.clear();
58 std::ifstream ifs(m_CacheFilename.c_str());
59 if( !ifs )
60 return false;
62 while( ifs ) {
63 uint32_t recordId = 0;
64 ifs >> recordId;
65 if( recordId ) {
66 m_Cache[recordId] = false;
70 if( !ifs.eof() ) {
71 m_Cache.clear(); // assume full sync
72 trace.log("Load failed!");
73 return false;
75 return true;
78 bool DatabaseSyncState::SaveCache()
80 Trace trace("SaveCache", m_Desc.c_str());
82 std::ofstream ofs(m_CacheFilename.c_str());
83 if( !ofs )
84 return false;
86 cache_type::const_iterator i = m_Cache.begin();
87 for( ; i != m_Cache.end(); ++i ) {
88 ofs << i->first << std::endl;
90 return !ofs.bad() && !ofs.fail();
93 bool DatabaseSyncState::LoadMap()
95 return m_IdMap.Load(m_MapFilename.c_str());
98 bool DatabaseSyncState::SaveMap()
100 return m_IdMap.Save(m_MapFilename.c_str());
103 // cycle through the map and search the state table for each rid,
104 // and remove any that do not exist
105 void DatabaseSyncState::CleanupMap()
107 idmap::iterator i = m_IdMap.begin();
108 for( ; i != m_IdMap.end(); ++i ) {
109 if( !m_Table.GetIndex(i->second) ) {
110 // Record Id does not exist in state table, so it is
111 // not needed anymore in the ID map
112 m_IdMap.Unmap(i);
118 // Map2Uid
120 /// Searches for the given record ID, and returns the mapped UID. If not
121 /// found, it creates a new UID and returns it without mapping it.
123 std::string DatabaseSyncState::Map2Uid(uint32_t recordId) const
125 // search the idmap for the UID
126 std::string uid;
127 idmap::const_iterator mapped_id;
128 if( m_IdMap.RidExists(recordId, &mapped_id) ) {
129 uid = mapped_id->first;
131 else {
132 // not mapped, map it ourselves
133 char *puid = g_strdup_printf("%s-%u", m_Desc.c_str(), recordId);
134 uid = puid;
135 g_free(puid);
137 return uid;
140 unsigned long DatabaseSyncState::GetMappedRecordId(const std::string &uid)
142 Trace trace("DatabaseSyncState::GetMappedRecordId()", m_Desc.c_str());
144 // if already in map, use the matching rid
145 idmap::const_iterator it;
146 if( m_IdMap.UidExists(uid, &it) ) {
147 trace.logf(_("found existing uid in map: %lu"), it->second);
148 return it->second;
151 // nothing in the map, so try to convert the string to a number
152 unsigned long RecordId;
153 if( sscanf(uid.c_str(), "%lu", &RecordId) != 0 ) {
154 trace.logf("parsed uid as: %lu", RecordId);
155 if( m_IdMap.Map(uid, RecordId) != m_IdMap.end() )
156 return RecordId;
158 trace.logf(_("parsed uid already exists in map, skipping"));
161 // create one of our own, if we get here...
162 // do this in a loop to keep going until we find an ID that's unique
163 do {
164 RecordId = m_Table.MakeNewRecordId();
165 } while( m_IdMap.Map(uid, RecordId) == m_IdMap.end() );
167 trace.logf(_("made new record id: %lu"), RecordId);
168 return RecordId;
173 //////////////////////////////////////////////////////////////////////////////
174 // BarryEnvironment Public API
176 BarryEnvironment::BarryEnvironment(OSyncMember *pm)
177 : member(pm),
178 m_pin(-1),
179 m_DebugMode(false),
180 m_CalendarSync(pm, "calendar"),
181 m_ContactsSync(pm, "contacts")
185 BarryEnvironment::~BarryEnvironment()
189 void BarryEnvironment::DoConnect()
191 if( !m_con.get() )
192 throw std::logic_error(_("Tried to use empty Connector"));
194 m_con->Connect();
196 // Save the DBIDs and DBNames of the databases we will work with
197 if( m_CalendarSync.m_Sync ) {
198 m_CalendarSync.m_dbName = Barry::Calendar::GetDBName();
199 m_CalendarSync.m_dbId = m_con->GetDesktop().GetDBID(Barry::Calendar::GetDBName());
202 if( m_ContactsSync.m_Sync ) {
203 m_ContactsSync.m_dbId = m_con->GetDesktop().GetDBID(Barry::Contact::GetDBName());
204 m_ContactsSync.m_dbName = Barry::Contact::GetDBName();
208 void BarryEnvironment::SetPassword(const std::string &password)
210 m_password = password;
211 if( m_con.get() )
212 m_con->SetPassword(password.c_str());
215 void BarryEnvironment::Connect(const Barry::ProbeResult &result)
217 m_con.reset(new DesktopConnector(m_password.c_str(), "UTF-8", result));
218 DoConnect();
221 void BarryEnvironment::Reconnect()
223 m_con->Reconnect(2);
226 void BarryEnvironment::Disconnect()
228 m_con->Disconnect();
231 void BarryEnvironment::ClearDirtyFlags(Barry::RecordStateTable &table,
232 const std::string &dbname)
234 Trace trace("ClearDirtyFlags");
236 unsigned int dbId = m_con->GetDesktop().GetDBID(dbname);
238 Barry::RecordStateTable::StateMapType::const_iterator i = table.StateMap.begin();
239 for( ; i != table.StateMap.end(); ++i ) {
240 if( i->second.Dirty ) {
241 trace.logf(_("Clearing dirty flag for db %u, index %u"),
242 dbId, i->first);
243 m_con->GetDesktop().ClearDirty(dbId, i->first);
248 void BarryEnvironment::ClearCalendarDirtyFlags()
250 Trace trace("ClearCalendarDirtyFlags");
251 ClearDirtyFlags(m_CalendarSync.m_Table, Barry::Calendar::GetDBName());
254 void BarryEnvironment::ClearContactsDirtyFlags()
256 Trace trace("ClearContactsDirtyFlags");
257 ClearDirtyFlags(m_ContactsSync.m_Table, Barry::Contact::GetDBName());
260 DatabaseSyncState* BarryEnvironment::GetSyncObject(OSyncChange *change)
262 Trace trace("BarryEnvironment::GetSyncObject()");
264 OSyncObjType *type = osync_change_get_objtype(change);
265 const char *name = osync_objtype_get_name(type);
266 if( strcmp(name, "event") == 0 ) {
267 return &m_CalendarSync;
269 else if( strcmp(name, "contact") == 0 ) {
270 return &m_ContactsSync;
272 else {
273 return 0;
277 void BarryEnvironment::ParseConfig(const char *data, int size)
279 Trace trace("ParseConfig");
281 m_ConfigData.assign(data, size);
283 // The config data should contain:
284 // - Keyword: DebugMode
285 // - if the single word "DebugMode" is found, enable Debug
287 // - Keyword: Device <pin> ...
288 // - PIN of device to sync with
289 // - or a flag that says "autoconfig with first device found"
290 // which will autodetect, and update the config
291 // automatically with the found PIN... all future syncs
292 // will then have a PIN
293 // - checkboxes for (both can be on):
294 // - sync calendar items
295 // - sync contacts
297 std::istringstream iss(m_ConfigData);
298 std::string line;
299 while( std::getline(iss, line) ) {
301 if( line[0] == '#' )
302 continue;
304 std::istringstream ils(line);
305 int cal = 0, con = 0;
307 std::string key;
308 ils >> key;
310 if( key == "DebugMode" ) {
311 m_DebugMode = true;
313 else if( key == "Device" ) {
314 ils >> std::hex >> m_pin >> cal >> con;
316 std::ostringstream oss;
317 oss << std::hex << m_pin;
318 trace.log(oss.str().c_str());
320 if( cal ) {
321 m_CalendarSync.m_Sync = true;
322 trace.log(_("calendar syncing enabled"));
325 if( con ) {
326 m_ContactsSync.m_Sync = true;
327 trace.log(_("contacts syncing enabled"));
330 else if ( key == "Password" ) {
331 ils >> m_password;
332 trace.log(_("using password from config file"));
337 //void BarryEnvironment::BuildConfig()
339 // FIXME - build back into one long string