Bug Summary

File:libsynthesis/src/sysync/binfileimplclient.cpp
Warning:line 1486, column 9
Value stored to 'err' is never read

Annotated Source Code

1/**
2 * @File binfileimplclient.cpp
3 *
4 * @Author Lukas Zeller (luz@plan44.ch)
5 *
6 * @brief TBinfileImplClient
7 * Represents a client session (agent) that saves profile, target, resume info
8 * and optionally changelog in TBinFile binary files
9 *
10 * Copyright (c) 2003-2011 by Synthesis AG + plan44.ch
11 *
12 * @Date 2005-09-30 : luz : created from TBinfileImplClient
13 */
14/*
15 */
16
17// includes
18#include "prefix_file.h"
19#include "binfileimplclient.h"
20#include "binfileimplds.h"
21#include "syserial.h"
22#include <cstddef>
23
24
25namespace sysync {
26
27
28// Support for EngineModule common interface
29// =========================================
30
31#ifdef ENGINEINTERFACE_SUPPORT1
32
33#ifndef ENGINE_LIBRARY1
34#ifdef RELEASE_VERSION
35 #error "this is here for Q&D testing with outlook client only"
36#endif
37// factory function implementation - declared in TEngineInterface
38ENGINE_IF_CLASSTEngineModuleBase *newClientEngine(void)
39{
40 return new TBinfileEngineInterface;
41} // newEngine
42
43#ifdef RELEASE_VERSION
44 #error "this is only here for Q&D testing with outlook client - remove it later, global factory function may no longer be used by engineInterface targets!!"
45#else
46/// @brief returns a new application base.
47TSyncAppBase *TBinfileEngineInterface::newSyncAppBase(void)
48{
49 return sysync::newSyncAppBase(); // use global factory function
50} // TBinfileEngineInterface::newSyncAppBase
51#endif
52
53#endif // not ENGINE_LIBRARY
54
55
56
57// create appropriate root key
58TSettingsKeyImpl *TBinfileEngineInterface::newSettingsRootKey(void)
59{
60 return new TBinfileAgentRootKey(this); // return base class which can return some engine infos
61} // TBinfileEngineInterface::newSettingsRootKey
62
63
64
65// Target key
66// ----------
67
68// constructor
69TBinfileTargetKey::TBinfileTargetKey(
70 TEngineInterface *aEngineInterfaceP,
71 sInt32 aTargetIndex,
72 TBinfileDBSyncTarget *aTargetP,
73 TBinfileClientConfig *aBinfileClientConfigP,
74 TBinfileDSConfig *aBinfileDSConfigP
75) :
76 inherited(aEngineInterfaceP),
77 fTargetIndex(aTargetIndex),
78 fTargetP(aTargetP),
79 fBinfileClientConfigP(aBinfileClientConfigP),
80 fBinfileDSConfigP(aBinfileDSConfigP)
81{
82 // nop
83} // TBinfileTargetKey::TBinfileTargetKey
84
85
86// destructor - close key
87TBinfileTargetKey::~TBinfileTargetKey()
88{
89 // closing key
90 if (fTargetP) {
91 if (fDirty && fTargetIndex>=0) {
92 // write back changed record
93 fBinfileClientConfigP->writeTarget(fTargetIndex,*fTargetP);
94 }
95 // now delete the target record
96 delete fTargetP;
97 }
98} // TBinfileTargetKey::~TBinfileTargetKey
99
100
101// return ID of current key
102TSyError TBinfileTargetKey::GetKeyID(sInt32 &aID)
103{
104 aID = fTargetP ? fTargetP->localDBTypeID : KEYVAL_ID_UNKNOWN;
105 return LOCERR_OK;
106} // TBinfileTargetKey::GetKeyID
107
108
109// - read display name
110static TSyError readDispName(
111 TStructFieldsKey *aStructFieldsKeyP, const TStructFieldInfo *aFldInfoP,
112 appPointer aBuffer, memSize aBufSize, memSize &aValSize
113)
114{
115 // get from config
116 TBinfileTargetKey *targetKeyP = static_cast<TBinfileTargetKey *>(aStructFieldsKeyP);
117 cAppCharP dispName = "";
118 #ifndef MINIMAL_CODE
119 dispName = targetKeyP->getBinfileDSConfig()->fDisplayName.c_str();
120 #endif
121 if (*dispName==0) {
122 // no display name, get technical name instead
123 dispName = targetKeyP->getBinfileDSConfig()->getName();
124 }
125 return TStructFieldsKey::returnString(dispName, aBuffer, aBufSize, aValSize);
126} // readDispName
127
128
129// - read path where binfiles are, for plugin config files passed around engine
130static TSyError readBinFileDirTarget(
131 TStructFieldsKey *aStructFieldsKeyP, const TStructFieldInfo *aFldInfoP,
132 appPointer aBuffer, memSize aBufSize, memSize &aValSize
133)
134{
135 TBinfileTargetKey *targetKeyP = static_cast<TBinfileTargetKey *>(aStructFieldsKeyP);
136 // get info
137 string binFilesDir;
138 targetKeyP->getBinfileClientConfig()->getBinFilesPath(binFilesDir);
139 return TStructFieldsKey::returnString(binFilesDir.c_str(), aBuffer, aBufSize, aValSize);
140} // readBinFileDirTarget
141
142
143// - read availability flag for this datastore
144static TSyError readIsAvailable(
145 TStructFieldsKey *aStructFieldsKeyP, const TStructFieldInfo *aFldInfoP,
146 appPointer aBuffer, memSize aBufSize, memSize &aValSize
147)
148{
149 TBinfileTargetKey *targetKeyP = static_cast<TBinfileTargetKey *>(aStructFieldsKeyP);
150 // - get profile by ID
151 bool avail = false;
152 if (targetKeyP && targetKeyP->getTarget()) {
153 TBinfileDBSyncProfile profile;
154 targetKeyP->getBinfileClientConfig()->getProfileByID(targetKeyP->getProfileID(),profile);
155 avail = targetKeyP->getBinfileClientConfig()->isTargetAvailable(&profile,targetKeyP->getTarget()->localDBTypeID);
156 }
157 return TStructFieldsKey::returnInt(avail, sizeof(avail), aBuffer, aBufSize, aValSize);
158} // readIsAvailable
159
160
161// - read danger flags for this datastore (will return them even if not enabled)
162static TSyError readTargetDangerFlags(
163 TStructFieldsKey *aStructFieldsKeyP, const TStructFieldInfo *aFldInfoP,
164 appPointer aBuffer, memSize aBufSize, memSize &aValSize
165)
166{
167 TBinfileTargetKey *targetKeyP = static_cast<TBinfileTargetKey *>(aStructFieldsKeyP);
168 bool zapsServer, zapsClient;
169 lineartime_t lastSync;
170 uInt32 dbid;
171 // get info
172 uInt8 danger=0;
173 TBinfileDBSyncTarget *targetP;
174 if (targetKeyP && (targetP=targetKeyP->getTarget())) {
175 targetKeyP->getBinfileClientConfig()->getTargetLastSyncTime(*targetP, lastSync, zapsServer, zapsClient, dbid);
176 danger =
177 (zapsServer ? DANGERFLAG_WILLZAPSERVER : 0) +
178 (zapsClient ? DANGERFLAG_WILLZAPCLIENT : 0);
179 }
180 return TStructFieldsKey::returnInt(danger, sizeof(danger), aBuffer, aBufSize, aValSize);
181} // readTargetDangerFlags
182
183
184// - write a readonly bitmask (rdonly_xxx), if this returns LOCERR_OK, readonly is enabled
185static TSyError writeTargetReadOnlyCheck(
186 TStructFieldsKey *aStructFieldsKeyP, const TStructFieldInfo *aFldInfoP,
187 cAppPointer aBuffer, memSize aValSize
188)
189{
190 TBinfileTargetKey *targetKeyP = static_cast<TBinfileTargetKey *>(aStructFieldsKeyP);
191 // get readonly mask to check for
192 uInt16 readOnlyMask = *((uInt16 *)aBuffer);
193 // check in profile
194 bool rdOnly=false;
195 if (targetKeyP && targetKeyP->getTarget()) {
196 TBinfileDBSyncProfile profile;
197 targetKeyP->getBinfileClientConfig()->getProfileByID(targetKeyP->getProfileID(),profile);
198 rdOnly = targetKeyP->getBinfileClientConfig()->isReadOnly(
199 &profile,
200 readOnlyMask
201 );
202 }
203 // if feature is enabled for this profile, return LOCERR_OK, DB_NoContent otherwise
204 return rdOnly ? LOCERR_OK : DB_NoContent;
205} // writeTargetReadOnlyCheck
206
207
208// - write a feature number (APPFTR_xxx), if this returns LOCERR_OK, feature is available, otherwise not
209static TSyError writeTargetFeatureCheck(
210 TStructFieldsKey *aStructFieldsKeyP, const TStructFieldInfo *aFldInfoP,
211 cAppPointer aBuffer, memSize aValSize
212)
213{
214 TBinfileTargetKey *targetKeyP = static_cast<TBinfileTargetKey *>(aStructFieldsKeyP);
215 // get feature to check for
216 uInt16 featureNo = *((uInt16 *)aBuffer);
217 // extra check for those that only make sense together with certain fDSAvailFlag
218 bool avail=true;
219 uInt16 dsAvailFlags = targetKeyP->getBinfileDSConfig()->fDSAvailFlag;
220 if (featureNo==APP_FTR_EVENTRANGE && (dsAvailFlags & dsavail_events)==0)
221 avail=false; // event range makes sense for events only
222 if (featureNo==APP_FTR_EMAILRANGE && (dsAvailFlags & dsavail_emails)==0)
223 avail=false; // email range makes sense for emails only
224 // check on profile (and global) level
225 if (avail && targetKeyP && targetKeyP->getTarget()) {
226 TBinfileDBSyncProfile profile;
227 targetKeyP->getBinfileClientConfig()->getProfileByID(targetKeyP->getProfileID(),profile);
228 avail = targetKeyP->getBinfileClientConfig()->isFeatureEnabled(
229 &profile,
230 featureNo
231 );
232 }
233 // if feature is enabled for this profile, return LOCERR_OK, DB_NoContent otherwise
234 return avail ? LOCERR_OK : DB_NoContent;
235} // writeTargetFeatureCheck
236
237
238// macro simplifying typing in the table below
239#define OFFS_SZ_TG(n)(__builtin_offsetof(TBinfileDBSyncTarget, n)), sizeof(((TBinfileDBSyncTarget
*)__null)->n)
(offsetof(TBinfileDBSyncTarget,n)__builtin_offsetof(TBinfileDBSyncTarget, n)), sizeof(((TBinfileDBSyncTarget *)NULL__null)->n)
240
241// accessor table for target key and for TARGETSETTING() script function
242const TStructFieldInfo TargetFieldInfos[] =
243{
244 // valName, valType, writable, fieldOffs, valSiz
245 { "profileID", VALTYPE_INT32, false, OFFS_SZ_TG(remotepartyID)(__builtin_offsetof(TBinfileDBSyncTarget, remotepartyID)), sizeof
(((TBinfileDBSyncTarget *)__null)->remotepartyID)
}, // read-only profile ID
246 { "enabled", VALTYPE_ENUM, true, OFFS_SZ_TG(enabled)(__builtin_offsetof(TBinfileDBSyncTarget, enabled)), sizeof((
(TBinfileDBSyncTarget *)__null)->enabled)
},
247 { "forceslow", VALTYPE_ENUM, true, OFFS_SZ_TG(forceSlowSync)(__builtin_offsetof(TBinfileDBSyncTarget, forceSlowSync)), sizeof
(((TBinfileDBSyncTarget *)__null)->forceSlowSync)
},
248 { "syncmode", VALTYPE_ENUM, true, OFFS_SZ_TG(syncmode)(__builtin_offsetof(TBinfileDBSyncTarget, syncmode)), sizeof(
((TBinfileDBSyncTarget *)__null)->syncmode)
},
249 { "limit1", VALTYPE_INT32, true, OFFS_SZ_TG(limit1)(__builtin_offsetof(TBinfileDBSyncTarget, limit1)), sizeof(((
TBinfileDBSyncTarget *)__null)->limit1)
},
250 { "limit2", VALTYPE_INT32, true, OFFS_SZ_TG(limit2)(__builtin_offsetof(TBinfileDBSyncTarget, limit2)), sizeof(((
TBinfileDBSyncTarget *)__null)->limit2)
},
251 { "extras", VALTYPE_INT32, true, OFFS_SZ_TG(extras)(__builtin_offsetof(TBinfileDBSyncTarget, extras)), sizeof(((
TBinfileDBSyncTarget *)__null)->extras)
},
252 { "localpath", VALTYPE_TEXT, true, OFFS_SZ_TG(localDBPath)(__builtin_offsetof(TBinfileDBSyncTarget, localDBPath)), sizeof
(((TBinfileDBSyncTarget *)__null)->localDBPath)
},
253 { "remotepath", VALTYPE_TEXT, true, OFFS_SZ_TG(remoteDBpath)(__builtin_offsetof(TBinfileDBSyncTarget, remoteDBpath)), sizeof
(((TBinfileDBSyncTarget *)__null)->remoteDBpath)
},
254 #if defined(DESKTOP_CLIENT1) || TARGETS_DB_VERSION6>4
255 { "localcontainer", VALTYPE_TEXT, true, OFFS_SZ_TG(localContainerName)(__builtin_offsetof(TBinfileDBSyncTarget, localContainerName)
), sizeof(((TBinfileDBSyncTarget *)__null)->localContainerName
)
},
256 #endif
257 // read-only status info
258 { "dbname", VALTYPE_TEXT, false, OFFS_SZ_TG(dbname)(__builtin_offsetof(TBinfileDBSyncTarget, dbname)), sizeof(((
TBinfileDBSyncTarget *)__null)->dbname)
},
259 { "lastSync", VALTYPE_TIME64, false, OFFS_SZ_TG(lastSync)(__builtin_offsetof(TBinfileDBSyncTarget, lastSync)), sizeof(
((TBinfileDBSyncTarget *)__null)->lastSync)
},
260 { "lastChangeCheck", VALTYPE_TIME64, false, OFFS_SZ_TG(lastChangeCheck)(__builtin_offsetof(TBinfileDBSyncTarget, lastChangeCheck)), sizeof
(((TBinfileDBSyncTarget *)__null)->lastChangeCheck)
},
261 { "resumeAlertCode", VALTYPE_INT16, true, OFFS_SZ_TG(resumeAlertCode)(__builtin_offsetof(TBinfileDBSyncTarget, resumeAlertCode)), sizeof
(((TBinfileDBSyncTarget *)__null)->resumeAlertCode)
},
262 // programmatic danger flags (will sync zap client or server data?)
263 { "dangerFlags", VALTYPE_INT8, false, 0,0, &readTargetDangerFlags, NULL__null },
264 // special programmatic availability and feature checks
265 { "isAvailable", VALTYPE_ENUM, false, 0,0, &readIsAvailable, NULL__null }, // datastore availability
266 { "checkForReadOnly", VALTYPE_INT16, true, 0,0, NULL__null, &writeTargetReadOnlyCheck }, // target level readonly check
267 { "checkForFeature", VALTYPE_INT16, true, 0,0, NULL__null, &writeTargetFeatureCheck }, // target level feature check
268 // display name from config
269 { "dispName", VALTYPE_TEXT, false, 0,0, &readDispName, NULL__null },
270 // path where binfiles are, for plugin config files passed around engine
271 { "binfilesDir", VALTYPE_TEXT, false, 0,0, &readBinFileDirTarget, NULL__null },
272 // new fields of TARGETS_DB_VERSION 6 and beyond
273 #if TARGETS_DB_VERSION6>5
274 { "remoteDispName", VALTYPE_TEXT, false, OFFS_SZ_TG(remoteDBdispName)(__builtin_offsetof(TBinfileDBSyncTarget, remoteDBdispName)),
sizeof(((TBinfileDBSyncTarget *)__null)->remoteDBdispName
)
},
275 // filtering
276 { "filterCapDesc", VALTYPE_TEXT, false, OFFS_SZ_TG(filterCapDesc)(__builtin_offsetof(TBinfileDBSyncTarget, filterCapDesc)), sizeof
(((TBinfileDBSyncTarget *)__null)->filterCapDesc)
},
277 { "remoteFilters", VALTYPE_TEXT, true, OFFS_SZ_TG(remoteFilters)(__builtin_offsetof(TBinfileDBSyncTarget, remoteFilters)), sizeof
(((TBinfileDBSyncTarget *)__null)->remoteFilters)
},
278 { "localFilters", VALTYPE_TEXT, true, OFFS_SZ_TG(localFilters)(__builtin_offsetof(TBinfileDBSyncTarget, localFilters)), sizeof
(((TBinfileDBSyncTarget *)__null)->localFilters)
},
279 #endif
280};
281const sInt32 numTargetFieldInfos = sizeof(TargetFieldInfos)/sizeof(TStructFieldInfo);
282
283// get table describing the fields in the struct
284const TStructFieldInfo *TBinfileTargetKey::getFieldsTable(void)
285{
286 return TargetFieldInfos;
287} // TBinfileTargetKey::getFieldsTable
288
289sInt32 TBinfileTargetKey::numFields(void)
290{
291 return numTargetFieldInfos;
292} // TBinfileTargetKey::numFields
293
294
295
296// get actual struct base address
297uInt8P TBinfileTargetKey::getStructAddr(void)
298{
299 return (uInt8P)fTargetP;
300} // TBinfileTargetKey::getStructAddr
301
302
303// Profiles container key
304// ----------------------
305
306// constructor
307TBinfileTargetsKey::TBinfileTargetsKey(TEngineInterface *aEngineInterfaceP, sInt32 aProfileID) :
308 inherited(aEngineInterfaceP),
309 fProfileID(aProfileID),
310 fTargetIterator(-1)
311{
312 // get pointer to BinFileClientConfig
313 fBinfileClientConfigP =
314 static_cast<TBinfileClientConfig *>(
315 aEngineInterfaceP->getSyncAppBase()->getRootConfig()->fAgentConfigP
316 );
317} // TBinfileTargetsKey::TBinfileTargetsKey
318
319
320// target can be opened only by (dbtype-)ID
321TSyError TBinfileTargetsKey::OpenSubkey(
322 TSettingsKeyImpl *&aSettingsKeyP,
323 sInt32 aID, uInt16 aMode
324)
325{
326 // safety check to see if targets are open at all
327 if (!fBinfileClientConfigP->fTargetsBinFile.isOpen())
328 return LOCERR_WRONGUSAGE;
329 TBinfileDBSyncTarget *targetP = new TBinfileDBSyncTarget;
330 TSyError sta = LOCERR_OK;
331 sInt32 targetIndex = -1;
332 while(true) {
333 switch (aID) {
334 case KEYVAL_ID_FIRST:
335 fTargetIterator = 0; // go to first
336 goto getnthtarget;
337 // then fetch next
338 case KEYVAL_ID_NEXT:
339 // increment
340 fTargetIterator++;
341 getnthtarget:
342 // get n-th target as indicated by iterator
343 if (fTargetIterator>=0)
344 targetIndex = fBinfileClientConfigP->findTargetIndex(fProfileID,fTargetIterator);
345 if (targetIndex>=0)
346 goto gettarget; // next target found in iteration, get it
347 // no more targets found
348 sta=DB_NoContent; // no more targets
349 break;
350 default:
351 // get target by ID
352 if (aID<0) {
353 sta=LOCERR_WRONGUSAGE;
354 break;
355 }
356 // find target by dbtypeid
357 targetIndex = fBinfileClientConfigP->findTargetIndexByDBInfo(fProfileID,aID,NULL__null);
358 gettarget:
359 // get target by index
360 targetIndex = fBinfileClientConfigP->getTarget(targetIndex,*targetP);
361 // check error
362 if (targetIndex<0)
363 sta=DB_NotFound; // target not found
364 break;
365 }
366 if (sta==LOCERR_OK && targetIndex>=0) {
367 // we have loaded a target, create subkey handler and pass data
368 /* %%% old: search by name
369 // - find related datastore config (by dbname)
370 TBinfileDSConfig *dsCfgP = static_cast<TBinfileDSConfig *>(
371 fBinfileClientConfigP->getLocalDS(targetP->dbname)
372 );
373 */
374 // - find related datastore config (by dbtypeid)
375 TBinfileDSConfig *dsCfgP = static_cast<TBinfileDSConfig *>(
376 fBinfileClientConfigP->getLocalDS(NULL__null,targetP->localDBTypeID)
377 );
378 if (dsCfgP==NULL__null) {
379 // this target entry is not configured in the config -> skip it while iterating,
380 // or return "DB error" if explicitly addressed
381 // - re-enter iteration if iterating
382 if (aID==KEYVAL_ID_FIRST)
383 aID=KEYVAL_ID_NEXT;
384 if (aID==KEYVAL_ID_NEXT)
385 continue; // re-iterate
386 // otherwise return DB error to signal inconsistency between target and config
387 sta=DB_Error;
388 }
389 else {
390 aSettingsKeyP = new TBinfileTargetKey(fEngineInterfaceP,targetIndex,targetP,fBinfileClientConfigP,dsCfgP);
391 if (aSettingsKeyP)
392 targetP=NULL__null; // ownership passed
393 else
394 sta=LOCERR_OUTOFMEM; // cannot create object
395 }
396 }
397 // done, no re-iteration needed
398 break;
399 } // while true
400 // get rid of it if we couldn't pass it to the subkey handler
401 if (targetP)
402 delete targetP;
403 // done
404 return sta;
405} // TBinfileTargetsKey::OpenSubkey
406
407
408
409#ifdef AUTOSYNC_SUPPORT
410
411// Autosync level key
412// ------------------
413
414// constructor
415TBinfileASLevelKey::TBinfileASLevelKey(
416 TEngineInterface *aEngineInterfaceP,
417 sInt32 aLevelIndex,
418 TBinfileDBSyncProfile *aProfileP,
419 TBinfileClientConfig *aBinfileClientConfigP
420) :
421 inherited(aEngineInterfaceP),
422 fLevelIndex(aLevelIndex),
423 fProfileP(aProfileP),
424 fBinfileClientConfigP(aBinfileClientConfigP)
425{
426} // TBinfileASLevelKey::TBinfileASLevelKey
427
428
429// destructor - close key
430TBinfileASLevelKey::~TBinfileASLevelKey()
431{
432 // closing key
433 // NOP here
434} // TBinfileASLevelKey::~TBinfileASLevelKey
435
436
437// return ID of current key
438TSyError TBinfileASLevelKey::GetKeyID(sInt32 &aID)
439{
440 aID = fLevelIndex; // ID is level index
441 return LOCERR_OK;
442} // TBinfileASLevelKey::GetKeyID
443
444
445// macro simplifying typing in the table below
446#define OFFS_SZ_AS(n) (offsetof(TAutoSyncLevel,n)__builtin_offsetof(TAutoSyncLevel, n)), sizeof(dP_as->n)
447// dummy pointer needed for sizeof
448static const TAutoSyncLevel *dP_as=NULL__null;
449
450// accessor table for profiles
451static const TStructFieldInfo ASLevelFieldInfos[] =
452{
453 // valName, valType, writable, fieldOffs, valSiz
454 { "mode", VALTYPE_ENUM, true, OFFS_SZ_AS(Mode) },
455 { "startDayTime", VALTYPE_INT16, true, OFFS_SZ_AS(StartDayTime) },
456 { "endDayTime", VALTYPE_INT16, true, OFFS_SZ_AS(EndDayTime) },
457 { "weekdayMask", VALTYPE_INT8, true, OFFS_SZ_AS(WeekdayMask) },
458 { "chargeLevel", VALTYPE_INT8, true, OFFS_SZ_AS(ChargeLevel) },
459 { "memLevel", VALTYPE_INT8, true, OFFS_SZ_AS(MemLevel) },
460 { "flags", VALTYPE_INT8, true, OFFS_SZ_AS(Flags) },
461};
462
463
464// get table describing the fields in the struct
465const TStructFieldInfo *TBinfileASLevelKey::getFieldsTable(void)
466{
467 return ASLevelFieldInfos;
468} // TBinfileASLevelKey::getFieldsTable
469
470sInt32 TBinfileASLevelKey::numFields(void)
471{
472 return sizeof(ASLevelFieldInfos)/sizeof(TStructFieldInfo);
473} // TBinfileASLevelKey::numFields
474
475
476
477// get actual struct base address
478uInt8P TBinfileASLevelKey::getStructAddr(void)
479{
480 return (uInt8P)&(fProfileP->AutoSyncLevel[fLevelIndex]);
481} // TBinfileASLevelKey::getStructAddr
482
483
484// Autosync levels container key
485// -----------------------------
486
487// constructor
488TBinfileASLevelsKey::TBinfileASLevelsKey(TEngineInterface *aEngineInterfaceP, TBinfileDBSyncProfile *aProfileP) :
489 inherited(aEngineInterfaceP),
490 fASLevelIterator(-1),
491 fProfileP(aProfileP)
492{
493 // get pointer to BinFileClientConfig
494 fBinfileClientConfigP =
495 static_cast<TBinfileClientConfig *>(
496 aEngineInterfaceP->getSyncAppBase()->getRootConfig()->fAgentConfigP
497 );
498} // TBinfileASLevelsKey::TBinfileASLevelsKey
499
500
501// autosync levels can be opened only by ID
502TSyError TBinfileASLevelsKey::OpenSubkey(
503 TSettingsKeyImpl *&aSettingsKeyP,
504 sInt32 aID, uInt16 aMode
505)
506{
507 TSyError sta = LOCERR_OK;
508
509 switch (aID) {
510 case KEYVAL_ID_FIRST:
511 fASLevelIterator = 0; // go to first
512 goto getlevel;
513 // then fetch next
514 case KEYVAL_ID_NEXT:
515 // increment
516 fASLevelIterator++;
517 getlevel:
518 // use iterator as ID (ID=level index)
519 aID = fASLevelIterator;
520 default:
521 // open specified ID
522 if (aID<0) {
523 sta=LOCERR_WRONGUSAGE;
524 }
525 else if (aID>=NUM_AUTOSYNC_LEVELS3)
526 sta=DB_NoContent; // no more autosync levels
527 else {
528 fASLevelIterator = aID;
529 aSettingsKeyP = new TBinfileASLevelKey(fEngineInterfaceP,aID,fProfileP,fBinfileClientConfigP);
530 }
531 break;
532 }
533 // done
534 return sta;
535} // TBinfileASLevelsKey::OpenSubkey
536
537#endif // AUTOSYNC_SUPPORT
538
539
540// Profile key
541// -----------
542
543// constructor
544TBinfileProfileKey::TBinfileProfileKey(
545 TEngineInterface *aEngineInterfaceP,
546 sInt32 aProfileIndex, // if <0, aProfileP is the running session's profile record
547 TBinfileDBSyncProfile *aProfileP,
548 TBinfileClientConfig *aBinfileClientConfigP
549) :
550 inherited(aEngineInterfaceP),
551 fProfileIndex(aProfileIndex),
552 fProfileP(aProfileP),
553 fBinfileClientConfigP(aBinfileClientConfigP)
554{
555} // TBinfileProfileKey::TBinfileProfileKey
556
557
558// destructor - close key
559TBinfileProfileKey::~TBinfileProfileKey()
560{
561 // closing key
562 if (fProfileP) {
563 if (fDirty && fProfileIndex>=0) {
564 // write back changed record
565 fBinfileClientConfigP->writeProfile(fProfileIndex,*fProfileP);
566 }
567 // now delete the profile record if it is not a running session's (because then it is just passed)
568 if (fProfileIndex>=0)
569 delete fProfileP;
570 }
571} // TBinfileProfileKey::~TBinfileProfileKey
572
573
574// return ID of current key
575TSyError TBinfileProfileKey::GetKeyID(sInt32 &aID)
576{
577 aID = getProfileID();
578 return LOCERR_OK;
579} // TBinfileProfileKey::GetKeyID
580
581
582// open subkey by name (not by path!)
583// - this is the actual implementation
584TSyError TBinfileProfileKey::OpenSubKeyByName(
585 TSettingsKeyImpl *&aSettingsKeyP,
586 cAppCharP aName, stringSize aNameSize,
587 uInt16 aMode
588) {
589 if (fProfileP && strucmp(aName,"targets",aNameSize)==0)
590 aSettingsKeyP = new TBinfileTargetsKey(fEngineInterfaceP,fProfileP->profileID);
591 #ifdef AUTOSYNC_SUPPORT
592 else if (fProfileP && strucmp(aName,"autosynclevels",aNameSize)==0)
593 aSettingsKeyP = new TBinfileASLevelsKey(fEngineInterfaceP,fProfileP);
594 #endif
595 else
596 return inherited::OpenSubKeyByName(aSettingsKeyP,aName,aNameSize,aMode);
597 // opened a key
598 return LOCERR_OK;
599} // TBinfileProfileKey::OpenSubKeyByName
600
601
602// - read path where binfiles are, for plugin config files passed around engine
603static TSyError readBinFileDirProfile(
604 TStructFieldsKey *aStructFieldsKeyP, const TStructFieldInfo *aFldInfoP,
605 appPointer aBuffer, memSize aBufSize, memSize &aValSize
606)
607{
608 TBinfileProfileKey *profileKeyP = static_cast<TBinfileProfileKey *>(aStructFieldsKeyP);
609 // get info
610 string binFilesDir;
611 profileKeyP->getBinfileClientConfig()->getBinFilesPath(binFilesDir);
612 return TStructFieldsKey::returnString(binFilesDir.c_str(), aBuffer, aBufSize, aValSize);
613} // readBinFileDirProfile
614
615
616
617// - read danger flags for the profile (combined danger of all enabled datastores)
618static TSyError readDangerFlags(
619 TStructFieldsKey *aStructFieldsKeyP, const TStructFieldInfo *aFldInfoP,
620 appPointer aBuffer, memSize aBufSize, memSize &aValSize
621)
622{
623 TBinfileProfileKey *profileKeyP = static_cast<TBinfileProfileKey *>(aStructFieldsKeyP);
624 bool zapsServer, zapsClient;
625 lineartime_t lastSync;
626 // get info
627 uInt8 danger=0;
628 profileKeyP->getBinfileClientConfig()->getProfileLastSyncTime(
629 profileKeyP->getProfileID(),
630 lastSync, zapsServer, zapsClient
631 );
632 danger =
633 (zapsServer ? DANGERFLAG_WILLZAPSERVER : 0) +
634 (zapsClient ? DANGERFLAG_WILLZAPCLIENT : 0);
635 return TStructFieldsKey::returnInt(danger, sizeof(danger), aBuffer, aBufSize, aValSize);
636} // readDangerFlags
637
638
639
640// - write a feature number (APPFTR_xxx), if this returns LOCERR_OK, feature is available, otherwise not
641static TSyError writeFeatureCheck(
642 TStructFieldsKey *aStructFieldsKeyP, const TStructFieldInfo *aFldInfoP,
643 cAppPointer aBuffer, memSize aValSize
644)
645{
646 TBinfileProfileKey *profileKeyP = static_cast<TBinfileProfileKey *>(aStructFieldsKeyP);
647 // get feature to check for
648 uInt16 featureNo = *((uInt16 *)aBuffer);
649 // if feature is enabled for this profile, return LOCERR_OK, DB_NoContent otherwise
650 return
651 profileKeyP->getBinfileClientConfig()->isFeatureEnabled(
652 profileKeyP->getProfile(),
653 featureNo
654 )
655 ? LOCERR_OK : DB_NoContent;
656} // writeFeatureCheck
657
658
659// - write a readonly bitmask (rdonly_xxx), if this returns LOCERR_OK, readonly is enabled
660static TSyError writeReadOnlyCheck(
661 TStructFieldsKey *aStructFieldsKeyP, const TStructFieldInfo *aFldInfoP,
662 cAppPointer aBuffer, memSize aValSize
663)
664{
665 TBinfileProfileKey *profileKeyP = static_cast<TBinfileProfileKey *>(aStructFieldsKeyP);
666 // get readonly mask to check for
667 uInt16 readOnlyMask = *((uInt16 *)aBuffer);
668 // check in profile
669 bool rdOnly=
670 profileKeyP->getBinfileClientConfig()->isReadOnly(
671 profileKeyP->getProfile(),
672 readOnlyMask
673 );
674 // if feature is enabled for this profile, return LOCERR_OK, DB_NoContent otherwise
675 return rdOnly ? LOCERR_OK : DB_NoContent;
676} // writeReadOnlyCheck
677
678
679// macro simplifying typing in the table below
680#define OFFS_SZ_PF(n)(__builtin_offsetof(TBinfileDBSyncProfile, n)), sizeof(((TBinfileDBSyncProfile
*)__null)->n)
(offsetof(TBinfileDBSyncProfile,n)__builtin_offsetof(TBinfileDBSyncProfile, n)), sizeof(((TBinfileDBSyncProfile *)NULL__null)->n)
681
682// accessor table for profiles and for PROFILESETTING script function
683const TStructFieldInfo ProfileFieldInfos[] =
684{
685 // valName, valType, writable, fieldOffs, valSiz
686 { "profileName", VALTYPE_TEXT, true, OFFS_SZ_PF(profileName)(__builtin_offsetof(TBinfileDBSyncProfile, profileName)), sizeof
(((TBinfileDBSyncProfile *)__null)->profileName)
},
687 { "protocol", VALTYPE_ENUM, true, OFFS_SZ_PF(protocol)(__builtin_offsetof(TBinfileDBSyncProfile, protocol)), sizeof
(((TBinfileDBSyncProfile *)__null)->protocol)
},
688 { "serverURI", VALTYPE_TEXT, true, OFFS_SZ_PF(serverURI)(__builtin_offsetof(TBinfileDBSyncProfile, serverURI)), sizeof
(((TBinfileDBSyncProfile *)__null)->serverURI)
},
689 { "URIpath", VALTYPE_TEXT, true, OFFS_SZ_PF(URIpath)(__builtin_offsetof(TBinfileDBSyncProfile, URIpath)), sizeof(
((TBinfileDBSyncProfile *)__null)->URIpath)
},
690 { "serverUser", VALTYPE_TEXT, true, OFFS_SZ_PF(serverUser)(__builtin_offsetof(TBinfileDBSyncProfile, serverUser)), sizeof
(((TBinfileDBSyncProfile *)__null)->serverUser)
},
691 { "serverPassword", VALTYPE_TEXT_OBFUS, true, OFFS_SZ_PF(serverPassword)(__builtin_offsetof(TBinfileDBSyncProfile, serverPassword)), sizeof
(((TBinfileDBSyncProfile *)__null)->serverPassword)
},
692 { "transportUser", VALTYPE_TEXT, true, OFFS_SZ_PF(transportUser)(__builtin_offsetof(TBinfileDBSyncProfile, transportUser)), sizeof
(((TBinfileDBSyncProfile *)__null)->transportUser)
},
693 { "transportPassword", VALTYPE_TEXT_OBFUS, true, OFFS_SZ_PF(transportPassword)(__builtin_offsetof(TBinfileDBSyncProfile, transportPassword)
), sizeof(((TBinfileDBSyncProfile *)__null)->transportPassword
)
},
694 { "socksHost", VALTYPE_TEXT, true, OFFS_SZ_PF(socksHost)(__builtin_offsetof(TBinfileDBSyncProfile, socksHost)), sizeof
(((TBinfileDBSyncProfile *)__null)->socksHost)
},
695 { "proxyHost", VALTYPE_TEXT, true, OFFS_SZ_PF(proxyHost)(__builtin_offsetof(TBinfileDBSyncProfile, proxyHost)), sizeof
(((TBinfileDBSyncProfile *)__null)->proxyHost)
},
696 { "proxyUser", VALTYPE_TEXT, true, OFFS_SZ_PF(proxyUser)(__builtin_offsetof(TBinfileDBSyncProfile, proxyUser)), sizeof
(((TBinfileDBSyncProfile *)__null)->proxyUser)
},
697 { "proxyPassword", VALTYPE_TEXT_OBFUS, true, OFFS_SZ_PF(proxyPassword)(__builtin_offsetof(TBinfileDBSyncProfile, proxyPassword)), sizeof
(((TBinfileDBSyncProfile *)__null)->proxyPassword)
},
698 { "encoding", VALTYPE_ENUM, true, OFFS_SZ_PF(encoding)(__builtin_offsetof(TBinfileDBSyncProfile, encoding)), sizeof
(((TBinfileDBSyncProfile *)__null)->encoding)
},
699 { "lastAuthMethod", VALTYPE_ENUM, true, OFFS_SZ_PF(lastAuthMethod)(__builtin_offsetof(TBinfileDBSyncProfile, lastAuthMethod)), sizeof
(((TBinfileDBSyncProfile *)__null)->lastAuthMethod)
},
700 { "lastNonce", VALTYPE_TEXT, true, OFFS_SZ_PF(lastNonce)(__builtin_offsetof(TBinfileDBSyncProfile, lastNonce)), sizeof
(((TBinfileDBSyncProfile *)__null)->lastNonce)
},
701 { "syncmlvers", VALTYPE_ENUM, true, OFFS_SZ_PF(lastSyncMLVersion)(__builtin_offsetof(TBinfileDBSyncProfile, lastSyncMLVersion)
), sizeof(((TBinfileDBSyncProfile *)__null)->lastSyncMLVersion
)
},
702 { "useProxy", VALTYPE_ENUM, true, OFFS_SZ_PF(useProxy)(__builtin_offsetof(TBinfileDBSyncProfile, useProxy)), sizeof
(((TBinfileDBSyncProfile *)__null)->useProxy)
},
703 { "useConnectionProxy", VALTYPE_ENUM, true, OFFS_SZ_PF(useConnectionProxy)(__builtin_offsetof(TBinfileDBSyncProfile, useConnectionProxy
)), sizeof(((TBinfileDBSyncProfile *)__null)->useConnectionProxy
)
},
704 { "transpFlags", VALTYPE_INT32, true, OFFS_SZ_PF(transpFlags)(__builtin_offsetof(TBinfileDBSyncProfile, transpFlags)), sizeof
(((TBinfileDBSyncProfile *)__null)->transpFlags)
},
705 { "profileFlags", VALTYPE_INT32, true, OFFS_SZ_PF(profileFlags)(__builtin_offsetof(TBinfileDBSyncProfile, profileFlags)), sizeof
(((TBinfileDBSyncProfile *)__null)->profileFlags)
},
706 // generic fields for app specific usage
707 { "profileExtra1", VALTYPE_INT32, true, OFFS_SZ_PF(profileExtra1)(__builtin_offsetof(TBinfileDBSyncProfile, profileExtra1)), sizeof
(((TBinfileDBSyncProfile *)__null)->profileExtra1)
},
708 { "profileExtra2", VALTYPE_INT32, true, OFFS_SZ_PF(profileExtra2)(__builtin_offsetof(TBinfileDBSyncProfile, profileExtra2)), sizeof
(((TBinfileDBSyncProfile *)__null)->profileExtra2)
},
709 { "profileData", VALTYPE_BUF, true, OFFS_SZ_PF(profileData)(__builtin_offsetof(TBinfileDBSyncProfile, profileData)), sizeof
(((TBinfileDBSyncProfile *)__null)->profileData)
},
710 // feature/availability/extras flags
711 { "dsAvailFlags", VALTYPE_INT16, true, OFFS_SZ_PF(dsAvailFlags)(__builtin_offsetof(TBinfileDBSyncProfile, dsAvailFlags)), sizeof
(((TBinfileDBSyncProfile *)__null)->dsAvailFlags)
},
712 { "readOnlyFlags", VALTYPE_INT8, true, OFFS_SZ_PF(readOnlyFlags)(__builtin_offsetof(TBinfileDBSyncProfile, readOnlyFlags)), sizeof
(((TBinfileDBSyncProfile *)__null)->readOnlyFlags)
},
713 { "remoteFlags", VALTYPE_INT8, false, OFFS_SZ_PF(remoteFlags)(__builtin_offsetof(TBinfileDBSyncProfile, remoteFlags)), sizeof
(((TBinfileDBSyncProfile *)__null)->remoteFlags)
},
714 { "featureFlags", VALTYPE_INT8, true, OFFS_SZ_PF(featureFlags)(__builtin_offsetof(TBinfileDBSyncProfile, featureFlags)), sizeof
(((TBinfileDBSyncProfile *)__null)->featureFlags)
},
715 // programmatic danger flags (will sync zap client or server data?)
716 { "dangerFlags", VALTYPE_INT8, false, 0,0, &readDangerFlags, NULL__null },
717 // special programmatic feature check
718 { "checkForFeature", VALTYPE_INT16, true, 0,0, NULL__null, &writeFeatureCheck },
719 { "checkForReadOnly", VALTYPE_INT16, true, 0,0, NULL__null, &writeReadOnlyCheck },
720 // path where binfiles are, for plugin config files passed around engine
721 { "binfilesDir", VALTYPE_TEXT, false, 0,0, &readBinFileDirProfile, NULL__null },
722 #ifdef AUTOSYNC_SUPPORT
723 // autosync
724 { "timedSyncMobile", VALTYPE_INT16, true, OFFS_SZ_PF(TimedSyncMobilePeriod)(__builtin_offsetof(TBinfileDBSyncProfile, TimedSyncMobilePeriod
)), sizeof(((TBinfileDBSyncProfile *)__null)->TimedSyncMobilePeriod
)
},
725 { "timedSyncCradled", VALTYPE_INT16, true, OFFS_SZ_PF(TimedSyncCradledPeriod)(__builtin_offsetof(TBinfileDBSyncProfile, TimedSyncCradledPeriod
)), sizeof(((TBinfileDBSyncProfile *)__null)->TimedSyncCradledPeriod
)
},
726 #endif
727};
728const sInt32 numProfileFieldInfos = sizeof(ProfileFieldInfos)/sizeof(TStructFieldInfo);
729
730
731// get table describing the fields in the struct
732const TStructFieldInfo *TBinfileProfileKey::getFieldsTable(void)
733{
734 return ProfileFieldInfos;
735} // TBinfileProfileKey::getFieldsTable
736
737sInt32 TBinfileProfileKey::numFields(void)
738{
739 return numProfileFieldInfos;
740} // TBinfileProfileKey::numFields
741
742
743
744// get actual struct base address
745uInt8P TBinfileProfileKey::getStructAddr(void)
746{
747 return (uInt8P)fProfileP;
748} // TBinfileProfileKey::getStructAddr
749
750
751// Profiles container key
752// ----------------------
753
754// constructor
755TBinfileProfilesKey::TBinfileProfilesKey(TEngineInterface *aEngineInterfaceP) :
756 inherited(aEngineInterfaceP), fProfileIterator(-1)
757{
758 // get pointer to BinFileClientConfig (can be NULL in case engine was never initialized with a config)
759 fBinfileClientConfigP =
760 static_cast<TBinfileClientConfig *>(
761 aEngineInterfaceP->getSyncAppBase()->getRootConfig()->fAgentConfigP
762 );
763 // default to not loosing or upgrading config
764 fMayLooseOldCfg=false;
765} // TBinfileProfilesKey::TBinfileProfilesKey
766
767
768// destructor
769TBinfileProfilesKey::~TBinfileProfilesKey()
770{
771 // make sure all settings are saved
772 if (
773 fBinfileClientConfigP && // it's possible that we get there before engine was ever initialized!
774 (fBinfileClientConfigP->fProfileBinFile.isOpen() || fBinfileClientConfigP->fTargetsBinFile.isOpen())
775 ) {
776 fBinfileClientConfigP->closeSettingsDatabases();
777 fBinfileClientConfigP->openSettingsDatabases(false);
778 }
779} // TBinfileProfilesKey::~TBinfileProfilesKey
780
781
782
783// profiles can be opened only by ID
784TSyError TBinfileProfilesKey::OpenSubkey(
785 TSettingsKeyImpl *&aSettingsKeyP,
786 sInt32 aID, uInt16 aMode
787)
788{
789 TBinfileDBSyncProfile *profileP = NULL__null;
790 TSyError sta = LOCERR_OK;
791
792 // safety check to see if config is here and profiles are open
793 if (!fBinfileClientConfigP || !(fBinfileClientConfigP->fProfileBinFile.isOpen()))
794 return LOCERR_WRONGUSAGE;
795 // now create a profile record (which will be passed to subkey on success)
796 profileP = new TBinfileDBSyncProfile;
797 // check what to do
798 switch (aID) {
799 case KEYVAL_ID_NEW:
800 // create a new empty profile
801 fProfileIterator = fBinfileClientConfigP->newProfile("empty profile", false);
802 // now get it
803 goto getprofile;
804 case KEYVAL_ID_NEW_DEFAULT:
805 // create new profile with default values
806 fProfileIterator = fBinfileClientConfigP->newProfile("default profile", true);
807 // now get it
808 goto getprofile;
809 case KEYVAL_ID_NEW_DUP:
810 // create duplicate of last opened profile (if any)
811 fProfileIterator = fBinfileClientConfigP->newProfile("duplicated profile", false, fProfileIterator);
812 // now get it
813 goto getprofile;
814 case KEYVAL_ID_FIRST:
815 fProfileIterator = 0; // go to first
816 goto getprofile;
817 // then fetch next
818 case KEYVAL_ID_NEXT:
819 // increment
820 fProfileIterator++;
821 getprofile:
822 // get profile by index
823 if (fProfileIterator>=0)
824 fProfileIterator=fBinfileClientConfigP->getProfile(fProfileIterator,*profileP);
825 goto checkerror;
826 default:
827 if (aID<0) {
828 sta=LOCERR_WRONGUSAGE;
829 break;
830 }
831 // open by ID
832 fProfileIterator=fBinfileClientConfigP->getProfileByID(aID,*profileP);
833 checkerror:
834 // check error
835 if (fProfileIterator<0)
836 sta=DB_NoContent; // no more profiles
837 break;
838 }
839 if (sta==LOCERR_OK && fProfileIterator>=0) {
840 // we have loaded a profile, create subkey handler and pass data
841 aSettingsKeyP = new TBinfileProfileKey(fEngineInterfaceP,fProfileIterator,profileP,fBinfileClientConfigP);
842 if (aSettingsKeyP)
843 profileP=NULL__null; // ownership passed
844 else
845 sta=LOCERR_OUTOFMEM; // cannot create object
846 }
847 // get rid of it if we couldn't pass it to the subkey handler
848 if (profileP)
849 delete profileP;
850 // done
851 return sta;
852} // TBinfileProfilesKey::OpenSubkey
853
854
855// delete profile by ID
856TSyError TBinfileProfilesKey::DeleteSubkey(sInt32 aID)
857{
858 sInt32 profileIndex = fBinfileClientConfigP->getProfileIndex(aID);
859 if (profileIndex<0) return DB_NotFound;
860 fBinfileClientConfigP->deleteProfile(profileIndex);
861 fProfileIterator = -1; // invalidate iterator
862 return LOCERR_OK;
863} // TBinfileProfilesKey::DeleteSubkey
864
865
866// - write a feature number (APPFTR_xxx), if this returns LOCERR_OK, feature is available, otherwise not
867static TSyError writeGlobalFeatureCheck(
868 TStructFieldsKey *aStructFieldsKeyP, const TStructFieldInfo *aFldInfoP,
869 cAppPointer aBuffer, memSize aValSize
870)
871{
872 // get feature to check for
873 uInt16 featureNo = *((uInt16 *)aBuffer);
874 // if feature is enabled for this profile, return LOCERR_OK, DB_NoContent otherwise
875 return
876 aStructFieldsKeyP->getEngineInterface()->getSyncAppBase()->isFeatureEnabled(featureNo)
877 ? LOCERR_OK : DB_NoContent;
878} // writeGlobalFeatureCheck
879
880// - write provisioning string
881static TSyError writeProvisioningString(
882 TStructFieldsKey *aStructFieldsKeyP, const TStructFieldInfo *aFldInfoP,
883 cAppPointer aBuffer, memSize aValSize
884)
885{
886 TBinfileProfilesKey *profilesKeyP = static_cast<TBinfileProfilesKey *>(aStructFieldsKeyP);
887 // execute the provisioning string
888 // Note: if a new profile is created, the iterator is set such that KEYVAL_ID_NEXT
889 // will return the profile just added/updated by provisioning
890 sInt32 touchedProfile;
891 cAppCharP p=cAppCharP(aBuffer);
892 TSyError sta = LOCERR_CFGPARSE;
893 while (p && *p) {
894 // push this line
895 if (profilesKeyP->getBinfileClientConfig()->executeProvisioningString(p, touchedProfile)) {
896 // parsed ok
897 sta = LOCERR_OK; // at least one line is ok
898 profilesKeyP->setNextProfileindex(touchedProfile); // such that KEYVAL_ID_NEXT will get the new/modified profile
899 }
900 // search for next line
901 // - skip to end
902 while (*p && *p!=0x0A && *p!=0x0D) ++p;
903 // - skip line end
904 while (*p==0x0A || *p==0x0D) ++p;
905 }
906 return sta;
907} // writeProvisioningString
908
909// - read registration status code
910static TSyError readVarCfgStatus(
911 TStructFieldsKey *aStructFieldsKeyP, const TStructFieldInfo *aFldInfoP,
912 appPointer aBuffer, memSize aBufSize, memSize &aValSize
913)
914{
915 aValSize=2;
916 if (aBufSize>=aValSize) {
917 // get ptr
918 TBinfileProfilesKey *profilesKeyP = static_cast<TBinfileProfilesKey *>(aStructFieldsKeyP);
919 // sanity check
920 if (!(profilesKeyP->fBinfileClientConfigP))
921 return LOCERR_WRONGUSAGE; // it's possible that we get there before engine was ever initialized!
922 // try to access variable part of config (profiles/targets)
923 localstatus sta = profilesKeyP->fBinfileClientConfigP->loadVarConfig(profilesKeyP->fMayLooseOldCfg);
924 if (sta==LOCERR_OK) {
925 // make sure profiles have all targets currently found in config
926 profilesKeyP->fBinfileClientConfigP->checkProfiles();
927 }
928 // copy from config
929 *((uInt16*)aBuffer)=sta;
930 }
931 return LOCERR_OK;
932} // readVarCfgStatus
933
934
935// - read "overwrite" flag
936static TSyError readMayLooseOldConfig(
937 TStructFieldsKey *aStructFieldsKeyP, const TStructFieldInfo *aFldInfoP,
938 appPointer aBuffer, memSize aBufSize, memSize &aValSize
939)
940{
941 return TStructFieldsKey::returnInt(static_cast<TBinfileProfilesKey *>(aStructFieldsKeyP)->fMayLooseOldCfg, 1, aBuffer, aBufSize, aValSize);
942} // readMayLooseOldConfig
943
944
945// - write "overwrite" flag
946static TSyError writeMayLooseOldConfig(
947 TStructFieldsKey *aStructFieldsKeyP, const TStructFieldInfo *aFldInfoP,
948 cAppPointer aBuffer, memSize aValSize
949)
950{
951 // set flag
952 static_cast<TBinfileProfilesKey *>(aStructFieldsKeyP)->fMayLooseOldCfg =
953 *((uInt8 *)aBuffer);
954 return LOCERR_OK;
955} // writeMayLooseOldConfig
956
957
958
959// does not work at this time, but intention would be to get rid of the warning below
960// #pragma GCC diagnostic ignored "-Wno-invalid-offsetof"
961
962// accessor table for profiles
963static const TStructFieldInfo ProfilesFieldInfos[] =
964{
965 // valName, valType, writable, fieldOffs, valSiz
966 { "settingsstatus", VALTYPE_INT16, false, 0, 0, &readVarCfgStatus, NULL__null },
967 //{ "overwrite", VALTYPE_INT8, true, offsetof(TBinfileProfilesKey,fMayLooseOldCfg), 1 }, //%%% this use of offsetof is not clean, so we use a getter/setter instead
968 { "overwrite", VALTYPE_INT8, true, 0, 0, &readMayLooseOldConfig, &writeMayLooseOldConfig },
969 { "provisioningstring", VALTYPE_TEXT, true, 0, 0, NULL__null, &writeProvisioningString },
970 { "checkForFeature", VALTYPE_INT16, true, 0, 0, NULL__null, &writeGlobalFeatureCheck }, // global level feature check
971};
972
973// get table describing the fields in the struct
974const TStructFieldInfo *TBinfileProfilesKey::getFieldsTable(void)
975{
976 return ProfilesFieldInfos;
977} // TBinfileProfilesKey::getFieldsTable
978
979sInt32 TBinfileProfilesKey::numFields(void)
980{
981 return sizeof(ProfilesFieldInfos)/sizeof(TStructFieldInfo);
982} // TBinfileProfilesKey::numFields
983
984// get actual struct base address
985uInt8P TBinfileProfilesKey::getStructAddr(void)
986{
987 return (uInt8P)this;
988} // TBinfileProfilesKey::getStructAddr
989
990
991
992// Log entry key
993// -------------
994
995// constructor
996TBinfileLogKey::TBinfileLogKey(
997 TEngineInterface *aEngineInterfaceP,
998 TLogFileEntry *aLogEntryP,
999 TBinfileClientConfig *aBinfileClientConfigP
1000) :
1001 inherited(aEngineInterfaceP),
1002 fLogEntryP(aLogEntryP),
1003 fBinfileClientConfigP(aBinfileClientConfigP)
1004{
1005} // TBinfileLogKey::TBinfileLogKey
1006
1007
1008// destructor - close key
1009TBinfileLogKey::~TBinfileLogKey()
1010{
1011 // closing key
1012 // - dispose log entry memory
1013 if (fLogEntryP) delete fLogEntryP;
1014} // TBinfileLogKey::~TBinfileLogKey
1015
1016
1017// - read DB display name related to this log entry
1018static TSyError readLogDispName(
1019 TStructFieldsKey *aStructFieldsKeyP, const TStructFieldInfo *aFldInfoP,
1020 appPointer aBuffer, memSize aBufSize, memSize &aValSize
1021)
1022{
1023 TBinfileLogKey *logentryKeyP = static_cast<TBinfileLogKey *>(aStructFieldsKeyP);
1024
1025 // get config of datastore via DBID
1026 TLocalDSConfig *dscfgP = logentryKeyP->getBinfileClientConfig()->getLocalDS(NULL__null,logentryKeyP->getLogEntry()->dbID);
1027 cAppCharP dispName = "";
1028 #ifndef MINIMAL_CODE
1029 dispName = dscfgP->fDisplayName.c_str();
1030 #endif
1031 if (*dispName==0) {
1032 // no display name, get technical name instead
1033 dispName = dscfgP->getName();
1034 }
1035 return TStructFieldsKey::returnString(dispName, aBuffer, aBufSize, aValSize);
1036} // readLogDispName
1037
1038
1039// - read DB display name related to this log entry
1040static TSyError readLogProfileName(
1041 TStructFieldsKey *aStructFieldsKeyP, const TStructFieldInfo *aFldInfoP,
1042 appPointer aBuffer, memSize aBufSize, memSize &aValSize
1043)
1044{
1045 TBinfileLogKey *logentryKeyP = static_cast<TBinfileLogKey *>(aStructFieldsKeyP);
1046
1047 // get profile data via profile ID
1048 TBinfileDBSyncProfile profile;
1049 logentryKeyP->getBinfileClientConfig()->getProfileByID(logentryKeyP->getLogEntry()->profileID,profile);
1050 return TStructFieldsKey::returnString(profile.profileName, aBuffer, aBufSize, aValSize);
1051} // readLogProfileName
1052
1053
1054
1055
1056// macro simplifying typing in the table below
1057#define OFFS_SZ_LOG(n)(__builtin_offsetof(TLogFileEntry, n)), sizeof(((TLogFileEntry
*)__null)->n)
(offsetof(TLogFileEntry,n)__builtin_offsetof(TLogFileEntry, n)), sizeof(((TLogFileEntry *)NULL__null)->n)
1058
1059// accessor table for log entries
1060static const TStructFieldInfo LogEntryFieldInfos[] =
1061{
1062 // valName, valType, writable, fieldOffs, valSiz
1063 // - direct access
1064 { "time", VALTYPE_TIME64, false, OFFS_SZ_LOG(time)(__builtin_offsetof(TLogFileEntry, time)), sizeof(((TLogFileEntry
*)__null)->time)
},
1065 { "dbtypeid", VALTYPE_INT32, false, OFFS_SZ_LOG(dbID)(__builtin_offsetof(TLogFileEntry, dbID)), sizeof(((TLogFileEntry
*)__null)->dbID)
},
1066 { "profileid", VALTYPE_INT32, false, OFFS_SZ_LOG(profileID)(__builtin_offsetof(TLogFileEntry, profileID)), sizeof(((TLogFileEntry
*)__null)->profileID)
},
1067 { "status", VALTYPE_INT16, false, OFFS_SZ_LOG(status)(__builtin_offsetof(TLogFileEntry, status)), sizeof(((TLogFileEntry
*)__null)->status)
},
1068 { "mode", VALTYPE_INT16, false, OFFS_SZ_LOG(mode)(__builtin_offsetof(TLogFileEntry, mode)), sizeof(((TLogFileEntry
*)__null)->mode)
},
1069 { "dirmode", VALTYPE_INT16, false, OFFS_SZ_LOG(dirmode)(__builtin_offsetof(TLogFileEntry, dirmode)), sizeof(((TLogFileEntry
*)__null)->dirmode)
},
1070 { "locAdded", VALTYPE_INT32, false, OFFS_SZ_LOG(locAdded)(__builtin_offsetof(TLogFileEntry, locAdded)), sizeof(((TLogFileEntry
*)__null)->locAdded)
},
1071 { "locUpdated", VALTYPE_INT32, false, OFFS_SZ_LOG(locUpdated)(__builtin_offsetof(TLogFileEntry, locUpdated)), sizeof(((TLogFileEntry
*)__null)->locUpdated)
},
1072 { "locDeleted", VALTYPE_INT32, false, OFFS_SZ_LOG(locDeleted)(__builtin_offsetof(TLogFileEntry, locDeleted)), sizeof(((TLogFileEntry
*)__null)->locDeleted)
},
1073 { "remAdded", VALTYPE_INT32, false, OFFS_SZ_LOG(remAdded)(__builtin_offsetof(TLogFileEntry, remAdded)), sizeof(((TLogFileEntry
*)__null)->remAdded)
},
1074 { "remUpdated", VALTYPE_INT32, false, OFFS_SZ_LOG(remUpdated)(__builtin_offsetof(TLogFileEntry, remUpdated)), sizeof(((TLogFileEntry
*)__null)->remUpdated)
},
1075 { "remDeleted", VALTYPE_INT32, false, OFFS_SZ_LOG(remDeleted)(__builtin_offsetof(TLogFileEntry, remDeleted)), sizeof(((TLogFileEntry
*)__null)->remDeleted)
},
1076 { "inBytes", VALTYPE_INT32, false, OFFS_SZ_LOG(inBytes)(__builtin_offsetof(TLogFileEntry, inBytes)), sizeof(((TLogFileEntry
*)__null)->inBytes)
},
1077 { "outBytes", VALTYPE_INT32, false, OFFS_SZ_LOG(outBytes)(__builtin_offsetof(TLogFileEntry, outBytes)), sizeof(((TLogFileEntry
*)__null)->outBytes)
},
1078 { "locRejected", VALTYPE_INT32, false, OFFS_SZ_LOG(locRejected)(__builtin_offsetof(TLogFileEntry, locRejected)), sizeof(((TLogFileEntry
*)__null)->locRejected)
},
1079 { "remRejected", VALTYPE_INT32, false, OFFS_SZ_LOG(remRejected)(__builtin_offsetof(TLogFileEntry, remRejected)), sizeof(((TLogFileEntry
*)__null)->remRejected)
},
1080 // - procedural convenience
1081 { "dispName", VALTYPE_TEXT, false, 0, 0, &readLogDispName, NULL__null },
1082 { "profileName", VALTYPE_TEXT, false, 0, 0, &readLogProfileName, NULL__null },
1083};
1084
1085
1086// get table describing the fields in the struct
1087const TStructFieldInfo *TBinfileLogKey::getFieldsTable(void)
1088{
1089 return LogEntryFieldInfos;
1090} // TBinfileLogKey::getFieldsTable
1091
1092sInt32 TBinfileLogKey::numFields(void)
1093{
1094 return sizeof(LogEntryFieldInfos)/sizeof(TStructFieldInfo);
1095} // TBinfileLogKey::numFields
1096
1097
1098
1099// get actual struct base address
1100uInt8P TBinfileLogKey::getStructAddr(void)
1101{
1102 return (uInt8P)(fLogEntryP);
1103} // TBinfileLogKey::getStructAddr
1104
1105
1106
1107// Log entries container key
1108// -------------------------
1109
1110// constructor
1111TBinfileLogsKey::TBinfileLogsKey(TEngineInterface *aEngineInterfaceP) :
1112 inherited(aEngineInterfaceP),
1113 fLogEntryIterator(-1)
1114{
1115 fBinfileClientConfigP =
1116 static_cast<TBinfileClientConfig *>(
1117 aEngineInterfaceP->getSyncAppBase()->getRootConfig()->fAgentConfigP
1118 );
1119 // open the log file
1120 // - get base path
1121 string filepath;
1122 fBinfileClientConfigP->getBinFilesPath(filepath);
1123 filepath += LOGFILE_DB_NAME"sysynclib_" "log.bfi";
1124 // - try to open
1125 fLogFile.setFileInfo(filepath.c_str(),LOGFILE_DB_VERSION3,LOGFILE_DB_ID8,sizeof(TLogFileEntry));
1126 fLogFile.open(0,NULL__null,NULL__null);
1127 // Note: errors are not checked here, as no logfile is ok. We'll check before trying to read with isOpen()
1128} // TBinfileLogsKey::TBinfileLogsKey
1129
1130
1131// log entries can be opened only by reverse index (0=newest...n=oldest)
1132TSyError TBinfileLogsKey::OpenSubkey(
1133 TSettingsKeyImpl *&aSettingsKeyP,
1134 sInt32 aID, uInt16 aMode
1135)
1136{
1137 // if there is no logfile, we have no entries
1138 if (!fLogFile.isOpen()) return DB_NotFound;
1139 switch (aID) {
1140 case KEYVAL_ID_FIRST:
1141 fLogEntryIterator = 0; // go to latest (last in file!)
1142 goto getnthentry;
1143 // then fetch next
1144 case KEYVAL_ID_NEXT:
1145 // increment
1146 fLogEntryIterator++;
1147 goto getnthentry;
1148 default:
1149 fLogEntryIterator=aID;
1150 getnthentry:
1151 // get n-th-last log entry as indicated by iterator
1152 // - check index range
1153 sInt32 numrecs = fLogFile.getNumRecords();
1154 if (fLogEntryIterator<0) return LOCERR_WRONGUSAGE;
1155 if (fLogEntryIterator>=numrecs) return DB_NoContent;
1156 // - retrieve
1157 TLogFileEntry *entryP = new TLogFileEntry;
1158 if (fLogFile.readRecord(numrecs-1-fLogEntryIterator,entryP) != BFE_OK0) {
1159 delete entryP;
1160 return DB_Fatal;
1161 }
1162 // - create key and return it (loaded entry gets owned by key)
1163 aSettingsKeyP = new TBinfileLogKey(fEngineInterfaceP,entryP,fBinfileClientConfigP);
1164 }
1165 return LOCERR_OK;
1166} // TBinfileLogsKey::OpenSubkey
1167
1168
1169// delete profile by ID
1170TSyError TBinfileLogsKey::DeleteSubkey(sInt32 aID)
1171{
1172 // log can only be cleared entirely
1173 if (aID!=KEYVAL_ID_ALL) return LOCERR_WRONGUSAGE;
1174 // erase log
1175 fLogFile.truncate(0);
1176 return LOCERR_OK;
1177} // TBinfileLogsKey::DeleteSubkey
1178
1179
1180
1181// Binfile Agent root key
1182// ----------------------
1183
1184// Constructor
1185TBinfileAgentRootKey::TBinfileAgentRootKey(TEngineInterface *aEngineInterfaceP) :
1186 inherited(aEngineInterfaceP)
1187{
1188} // TBinfileAgentRootKey::TBinfileAgentRootKey
1189
1190
1191// open subkey by name (not by path!)
1192// - this is the actual implementation
1193TSyError TBinfileAgentRootKey::OpenSubKeyByName(
1194 TSettingsKeyImpl *&aSettingsKeyP,
1195 cAppCharP aName, stringSize aNameSize,
1196 uInt16 aMode
1197) {
1198 if (strucmp(aName,"profiles",aNameSize)==0) {
1199 // allow accessing profiles only for active binfiles
1200 if (
1201 static_cast<TBinfileClientConfig *>(
1202 fEngineInterfaceP->getSyncAppBase()->getRootConfig()->fAgentConfigP
1203 )->fBinfilesActive
1204 ) {
1205 aSettingsKeyP = new TBinfileProfilesKey(fEngineInterfaceP);
1206 }
1207 else {
1208 // cannot access profiles of inactive binfile layer
1209 return LOCERR_WRONGUSAGE;
1210 }
1211 }
1212 else if (strucmp(aName,"synclogs",aNameSize)==0)
1213 aSettingsKeyP = new TBinfileLogsKey(fEngineInterfaceP);
1214 else
1215 return inherited::OpenSubKeyByName(aSettingsKeyP,aName,aNameSize,aMode);
1216 // opened a key
1217 return LOCERR_OK;
1218} // TBinfileAgentRootKey::OpenSubKeyByName
1219
1220
1221// Client runtime settings key
1222// ---------------------------
1223
1224
1225// Constructor
1226TBinFileAgentParamsKey::TBinFileAgentParamsKey(TEngineInterface *aEngineInterfaceP, TSyncAgent *aClientSessionP) :
1227 inherited(aEngineInterfaceP,aClientSessionP)
1228{
1229} // TBinFileAgentParamsKey::TBinFileAgentParamsKey
1230
1231
1232// open subkey by name (not by path!)
1233TSyError TBinFileAgentParamsKey::OpenSubKeyByName(
1234 TSettingsKeyImpl *&aSettingsKeyP,
1235 cAppCharP aName, stringSize aNameSize,
1236 uInt16 aMode
1237) {
1238 if (strucmp(aName,"profile",aNameSize)==0) {
1239 // get binfileclient session pointer
1240 TBinfileImplClient *bfclientP = static_cast<TBinfileImplClient *>(fAgentP);
1241 // opens current session's active profile
1242 aSettingsKeyP = new TBinfileProfileKey(
1243 fEngineInterfaceP,
1244 -1, // signals passing active session's profile
1245 &bfclientP->fProfile, // pointer to the current session's profile
1246 bfclientP->fConfigP // the config
1247 );
1248 }
1249 else
1250 return inherited::OpenSubKeyByName(aSettingsKeyP,aName,aNameSize,aMode);
1251 // opened a key
1252 return LOCERR_OK;
1253} // TBinFileAgentParamsKey::OpenSubKeyByName
1254
1255
1256#endif // ENGINEINTERFACE_SUPPORT
1257
1258
1259
1260
1261// Config
1262// ======
1263
1264TBinfileClientConfig::TBinfileClientConfig(TConfigElement *aParentElement) :
1265 TAgentConfig("BinFileDBClient",aParentElement)
1266{
1267} // TBinfileClientConfig::TBinfileClientConfig
1268
1269
1270TBinfileClientConfig::~TBinfileClientConfig()
1271{
1272 clear();
1273} // TBinfileClientConfig::~TBinfileClientConfig
1274
1275
1276// init defaults
1277void TBinfileClientConfig::clear(void)
1278{
1279 // Only active in clients by default
1280 fBinfilesActive = IS_CLIENT(!getSyncAppBase()->isServer());
1281 #ifndef HARDCODED_CONFIG
1282 // init defaults
1283 fSeparateChangelogs = true; // for engine libraries with full config, use separated changelogs by default (auto-migration w/o side effects is built-in)
1284 fBinFilesPath.erase();
1285 #else
1286 fSeparateChangelogs = false; // for traditional hard-coded clients like WinMobile and PalmOS, use pre 3.4.0.10 behaviour (uses less memory)
1287 #endif
1288 fBinFileLog=false;
1289 // - clear inherited
1290 inherited::clear();
1291} // TBinfileClientConfig::clear
1292
1293
1294#ifndef HARDCODED_CONFIG
1295
1296// config element parsing
1297bool TBinfileClientConfig::localStartElement(const char *aElementName, const char **aAttributes, sInt32 aLine)
1298{
1299 // checking the elements
1300 // - binfiles path
1301 if (strucmp(aElementName,"binfilespath")==0)
1302 expectMacroString(fBinFilesPath);
1303 else if (strucmp(aElementName,"binfilelog")==0)
1304 expectBool(fBinFileLog);
1305 else if (strucmp(aElementName,"binfilesactive")==0)
1306 expectBool(fBinfilesActive);
1307 else if (strucmp(aElementName,"separatechangelogs")==0)
1308 expectBool(fSeparateChangelogs);
1309 // - none known here
1310 else
1311 return inherited::localStartElement(aElementName,aAttributes,aLine);
1312 // ok
1313 return true;
1314} // TBinfileClientConfig::localStartElement
1315
1316#endif
1317
1318
1319// update profile record contents
1320static uInt32 profileUpdateFunc(uInt32 aOldVersion, uInt32 aNewVersion, void *aOldRecordData, void *aNewRecordData, uInt32 aOldSize)
1321{
1322 if (aOldVersion<LOWEST_PROFILE_DB_VERSION4 || aOldVersion>PROFILE_DB_VERSION9) return 0; // unknown old or newer than current version, cannot update
1323 if (aNewVersion!=PROFILE_DB_VERSION9) return 0; // cannot update to other version than current
1324 // create default values for profile
1325 if (aOldRecordData && aNewRecordData) {
1326 TBinfileDBSyncProfile *profileP = (TBinfileDBSyncProfile *)aNewRecordData;
1327 // make an empty default profile
1328 TBinfileClientConfig::initProfile(*profileP, "dummy", true);
1329 #if (PROFILE_DB_VERSION9>=6) && (LOWEST_PROFILE_DB_VERSION4<6)
1330 // copy in old version's data
1331 if (aOldVersion<=5) {
1332 // between 5 and 6, sizes of user and pw fields have all changed in size, so we need
1333 // to copy field-by-field
1334 o_TBinfileDBSyncProfile *oP=(o_TBinfileDBSyncProfile *)aOldRecordData;
1335 // now copy
1336 profileP->profileID = oP->profileID;
1337 AssignCString(profileP->profileName,oP->profileName,maxnamesiz);
1338 profileP->encoding = oP->encoding;
1339 AssignCString(profileP->serverURI,oP->serverURI,maxurisiz);
1340 AssignCString(profileP->serverUser,oP->serverUser,maxupwsiz);
1341 memcpy(profileP->serverPassword,oP->serverPassword,o_maxupwsiz);
1342 AssignCString(profileP->transportUser,oP->transportUser,maxupwsiz);
1343 memcpy(profileP->transportPassword,oP->transportPassword,o_maxupwsiz);
1344 AssignCString(profileP->socksHost,oP->socksHost,maxurisiz);
1345 AssignCString(profileP->proxyHost,oP->proxyHost,maxurisiz);
1346 profileP->sessionID = oP->sessionID;
1347 profileP->lastSyncMLVersion = oP->lastSyncMLVersion;
1348 profileP->lastAuthMethod = oP->lastAuthMethod;
1349 profileP->lastAuthFormat = oP->lastAuthFormat;
1350 AssignCString(profileP->lastNonce,oP->lastNonce,maxnoncesiz);
1351 profileP->firstuse = oP->firstuse;
1352 if (aOldVersion>=5) { // can only be OldVersion==5
1353 // copy additional PROFILE_DB_VERSION 5 settings
1354 AssignCString(profileP->URIpath,oP->URIpath,maxpathsiz);
1355 profileP->protocol = oP->protocol;
1356 profileP->readOnlyFlags = oP->readOnlyFlags;
1357 AssignCString(profileP->localDBProfileName,oP->localDBProfileName,localDBpathMaxLen);
1358 profileP->useProxy = oP->useProxy;
1359 profileP->useConnectionProxy = oP->useConnectionProxy;
1360 // - Auto-Sync levels (3 levels, first match overrides lower level settings)
1361 profileP->AutoSyncLevel[0]=oP->AutoSyncLevel[0];
1362 profileP->AutoSyncLevel[1]=oP->AutoSyncLevel[1];
1363 profileP->AutoSyncLevel[2]=oP->AutoSyncLevel[2];
1364 profileP->TimedSyncMobilePeriod = oP->TimedSyncMobilePeriod;
1365 profileP->TimedSyncCradledPeriod = oP->TimedSyncCradledPeriod;
1366 // - IPP settings are not copied, they have changed a bit between 6 and 7
1367 }
1368 }
1369 #endif
1370 if (aOldVersion<7) {
1371 // as ippsettings have changed between 6 and 7, do not copy them, but erase them
1372 #if PROFILE_DB_VERSION9>=5
1373 profileP->ippSettings.id[0]=0;
1374 profileP->ippSettings.cred[0]=0;
1375 profileP->ippSettings.srv[0]=0;
1376 profileP->ippSettings.method=0;
1377 #endif
1378 }
1379 // From Version 7 onwards, only some fields were added at the end, so simple copy is ok
1380 if (aOldVersion==7) {
1381 memcpy(aNewRecordData,aOldRecordData,PROFILE_DB_VERSION_7_SZ__builtin_offsetof(TBinfileDBSyncProfile, proxyUser));
1382 }
1383 if (aOldVersion==8) {
1384 memcpy(aNewRecordData,aOldRecordData,PROFILE_DB_VERSION_8_SZ__builtin_offsetof(TBinfileDBSyncProfile, transpFlags));
1385 }
1386 /* when we have PROFILE_DB_VERSION > 9
1387 if (aOldVersion==9) {
1388 memcpy(aNewRecordData,aOldRecordData,PROFILE_DB_VERSION_9_SZ);
1389 }
1390 */
1391 }
1392 // updated ok (or updateable ok if no data pointers provided)
1393 return sizeof(TBinfileDBSyncProfile);
1394} // profileUpdateFunc
1395
1396
1397// update target record contents
1398static uInt32 targetUpdateFunc(uInt32 aOldVersion, uInt32 aNewVersion, void *aOldRecordData, void *aNewRecordData, uInt32 aOldSize)
1399{
1400 if (aOldVersion<LOWEST_TARGETS_DB_VERSION3 || aOldVersion>TARGETS_DB_VERSION6) return 0; // unknown old version, cannot update
1401 if (aNewVersion!=TARGETS_DB_VERSION6) return 0; // cannot update to other version than current
1402 // create default values for profile
1403 if (aOldRecordData && aNewRecordData) {
1404 TBinfileDBSyncTarget *targetP = (TBinfileDBSyncTarget *)aNewRecordData;
1405 // copy old data - beginning of record is identical
1406 memcpy(aNewRecordData,aOldRecordData,aOldSize);
1407 // now initialize fields that old version didn't have
1408 if (aOldVersion<4) {
1409 // init new version 4 fields
1410 targetP->resumeAlertCode = 0;
1411 // also wipe out version 3 "lastModCount", which now becomes "lastSuspendModCount"
1412 targetP->lastSuspendModCount = 0;
1413 }
1414 #if TARGETS_DB_VERSION6 >= 5
1415 if (aOldVersion<5) {
1416 // init new version 5 fields
1417 AssignCString(targetP->localContainerName,NULL__null,localDBpathMaxLen);
1418 }
1419 #endif
1420 #if TARGETS_DB_VERSION6 >= 6
1421 if (aOldVersion<6) {
1422 // init new version 6 fields
1423 AssignCString(targetP->dummyIdentifier1,NULL__null,remoteAnchorMaxLen);
1424 AssignCString(targetP->dummyIdentifier2,NULL__null,remoteAnchorMaxLen);
1425 AssignCString(targetP->remoteDBdispName,NULL__null,dispNameMaxLen);
1426 AssignCString(targetP->filterCapDesc,NULL__null,filterCapDescMaxLen);
1427 AssignCString(targetP->remoteFilters,NULL__null,filterExprMaxLen);
1428 AssignCString(targetP->localFilters,NULL__null,filterExprMaxLen);
1429 }
1430 #endif
1431 }
1432 // updated ok (or updateable ok if no data pointers provided)
1433 // - return size of new record
1434 return sizeof(TBinfileDBSyncTarget);
1435} // targetUpdateFunc
1436
1437
1438// get path where to store binfiles
1439void TBinfileClientConfig::getBinFilesPath(string &aPath)
1440{
1441 #ifndef HARDCODED_CONFIG
1442 if (!fBinFilesPath.empty())
1443 aPath = fBinFilesPath;
1444 else
1445 #endif
1446 {
1447 // use appdata directory as defined by the current platform/OS
1448 if (!getPlatformString(pfs_appdata_path,aPath)) {
1449 // we have no path
1450 aPath.erase();
1451 }
1452 }
1453 // make OS path of it (if not empty) and create directory if not existing yet
1454 if (!aPath.empty()) {
1455 // make sure it exists
1456 makeOSDirPath(aPath,true);
1457 }
1458}; // TBinfileClientConfig::getBinFilesPath
1459
1460
1461// open settings databases
1462localstatus TBinfileClientConfig::openSettingsDatabases(bool aDoLoose)
1463{
1464 if (!fBinfilesActive) {
1465 // databases can be opened only with active binfiles layer
1466 return LOCERR_WRONGUSAGE;
1467 }
1468 else {
1469 // safe for calling more than once
1470 if (fProfileBinFile.isOpen() && fTargetsBinFile.isOpen())
1471 return LOCERR_OK; // already open - ok
1472 // open profile and targets databases
1473 // - get base path
1474 string basepath;
1475 getBinFilesPath(basepath);
1476 string usedpath;
1477 bool newprofiles=false;
1478 bferr err;
1479 // - profiles
1480 usedpath=basepath + PROFILE_DB_NAME"sysynclib_" "prof.bfi";
1481 fProfileBinFile.setFileInfo(usedpath.c_str(),PROFILE_DB_VERSION9,PROFILE_DB_ID2,sizeof(TBinfileDBSyncProfile));
1482 err = fProfileBinFile.open(0,NULL__null,profileUpdateFunc);
1483 if (err!=BFE_OK0) {
1484 // create new one or overwrite incompatible one if allowed
1485 if (aDoLoose || err!=BFE_BADVERSION1) {
1486 err=fProfileBinFile.create(sizeof(TBinfileDBSyncProfile),0,NULL__null,true);
Value stored to 'err' is never read
1487 newprofiles=true;
1488 }
1489 else {
1490 // would create new file due to bad (newer or non-upgradeable older) version
1491 return LOCERR_CFGPARSE; // this is kind of a config parsing error
1492 }
1493 }
1494 // - targets
1495 usedpath=basepath + TARGETS_DB_NAME"sysynclib_" "targ.bfi";
1496 fTargetsBinFile.setFileInfo(usedpath.c_str(),TARGETS_DB_VERSION6,TARGETS_DB_ID1,sizeof(TBinfileDBSyncTarget));
1497 err = fTargetsBinFile.open(0,NULL__null,targetUpdateFunc);
1498 if (err!=BFE_OK0 || newprofiles) {
1499 // create new one or overwrite incompatible one
1500 // also ALWAYS create new targets if we HAVE created new profiles
1501 if (aDoLoose || newprofiles || err!=BFE_BADVERSION1) {
1502 err=fTargetsBinFile.create(sizeof(TBinfileDBSyncTarget),0,NULL__null,true);
1503 }
1504 else {
1505 // would create new file due to bad (newer or non-upgradeable older) version
1506 return LOCERR_CFGPARSE; // this is kind of a config parsing error
1507 }
1508 }
1509 return err;
1510 }
1511} // TBinfileClientConfig::openSettingsDatabases
1512
1513
1514// close settings databases
1515void TBinfileClientConfig::closeSettingsDatabases(void)
1516{
1517 // open profile and targets databases
1518 fProfileBinFile.close();
1519 fTargetsBinFile.close();
1520} // TBinfileClientConfig::closeSettingsDatabases
1521
1522
1523// resolve
1524void TBinfileClientConfig::localResolve(bool aLastPass)
1525{
1526 // resolve inherited
1527 inherited::localResolve(aLastPass);
1528} // TBinfileClientConfig::localResolve
1529
1530
1531
1532// MUST be called after creating config to load (or pre-load) variable parts of config
1533// such as binfile profiles. If aDoLoose==false, situations, where existing config
1534// is detected but cannot be re-used will return an error. With aDoLoose==true, config
1535// files etc. are created even if it means a loss of data.
1536localstatus TBinfileClientConfig::loadVarConfig(bool aDoLoose)
1537{
1538 // let inherited to it's stuff
1539 localstatus err=inherited::loadVarConfig(aDoLoose);
1540 if (fBinfilesActive) {
1541 // now do my own stuff
1542 if (err==LOCERR_OK) {
1543 err=openSettingsDatabases(aDoLoose);
1544 }
1545 }
1546 // return status
1547 return err;
1548} // TBinfileClientConfig::loadVarConfig
1549
1550
1551
1552// save app state (such as settings in datastore configs etc.)
1553void TBinfileClientConfig::saveAppState(void)
1554{
1555 if (fBinfilesActive) {
1556 // close and re-open the settings binfiles to make sure their
1557 // contents is permanently saved
1558 closeSettingsDatabases();
1559 openSettingsDatabases(false);
1560 }
1561} // TBinfileClientConfig::saveAppState
1562
1563
1564// API for settings management
1565
1566
1567// initialize a new-created profile database
1568void TBinfileClientConfig::initProfileDb(void)
1569{
1570 // create default profile
1571 newProfile("Default",true);
1572} // TBinfileClientConfig::initProfileDb
1573
1574
1575// Defaults for profile
1576#ifndef DEFAULT_ENCODINGSML_WBXML
1577#define DEFAULT_ENCODINGSML_WBXML SML_WBXML
1578#endif
1579#ifndef DEFAULT_SERVER_URI""
1580#define DEFAULT_SERVER_URI"" NULL__null
1581#endif
1582#ifndef DEFAULT_URI_PATH__null
1583#define DEFAULT_URI_PATH__null NULL__null
1584#endif
1585#ifndef DEFAULT_SERVER_USER""
1586#define DEFAULT_SERVER_USER"" NULL__null
1587#endif
1588#ifndef DEFAULT_SERVER_PASSWD""
1589#define DEFAULT_SERVER_PASSWD"" NULL__null
1590#endif
1591#ifndef DEFAULT_TRANSPORT_USER__null
1592#define DEFAULT_TRANSPORT_USER__null NULL__null
1593#endif
1594#ifndef DEFAULT_TRANSPORT_PASSWD__null
1595#define DEFAULT_TRANSPORT_PASSWD__null NULL__null
1596#endif
1597#ifndef DEFAULT_SOCKS_HOST__null
1598#define DEFAULT_SOCKS_HOST__null NULL__null
1599#endif
1600#ifndef DEFAULT_PROXY_HOST__null
1601#define DEFAULT_PROXY_HOST__null NULL__null
1602#endif
1603#ifndef DEFAULT_PROXY_USER__null
1604#define DEFAULT_PROXY_USER__null NULL__null
1605#endif
1606#ifndef DEFAULT_PROXY_PASSWD__null
1607#define DEFAULT_PROXY_PASSWD__null NULL__null
1608#endif
1609#ifndef DEFAULT_DATASTORES_ENABLEDfalse
1610#define DEFAULT_DATASTORES_ENABLEDfalse false
1611#endif
1612#ifndef DEFAULT_LOCALDB_PROFILE""
1613#define DEFAULT_LOCALDB_PROFILE"" NULL__null
1614#endif
1615#ifndef DEFAULT_USESYSTEMPROXYtrue
1616#define DEFAULT_USESYSTEMPROXYtrue true
1617#endif
1618
1619// create new profile with targets for all configured datastores
1620// - returns index of new profile
1621sInt32 TBinfileClientConfig::newProfile(const char *aProfileName, bool aSetDefaults, sInt32 aTemplateProfile)
1622{
1623 TBinfileDBSyncProfile profile;
1624 TBinfileDBSyncTarget target;
1625 sInt32 profileIndex;
1626 TBinfileDBSyncProfile templateprofile;
1627 TBinfileDBSyncTarget templatetarget;
1628
1629 // create profile record
1630 initProfile(profile,aProfileName,aSetDefaults);
1631 #ifdef EXPIRES_AFTER_DAYS
1632 // copy date of first use (to see if someone tried to tamper with...)
1633 uInt32 vers;
1634 getSyncAppBase()->getFirstUseInfo(SYSER_VARIANT_CODE2,profile.firstuse,vers);
1635 #endif
1636 // copy from template profile, if any
1637 if (aTemplateProfile>=0) {
1638 aTemplateProfile=getProfile(aTemplateProfile,templateprofile);
1639 if (aTemplateProfile>=0) {
1640 // copy user config
1641 profile.encoding=templateprofile.encoding;
1642 #ifndef HARD_CODED_SERVER_URI
1643 strncpy(profile.serverURI,templateprofile.serverURI,maxurisiz); // if hardcoded, don't copy from template
1644 #endif
1645 strncpy(profile.serverUser,templateprofile.serverUser,maxupwsiz);
1646 strncpy(profile.transportUser,templateprofile.transportUser,maxupwsiz);
1647 strncpy(profile.socksHost,templateprofile.socksHost,maxurisiz);
1648 strncpy(profile.proxyHost,templateprofile.proxyHost,maxurisiz);
1649 strncpy(profile.proxyUser,templateprofile.proxyUser,maxupwsiz);
1650 // additional proxy flags
1651 profile.useProxy=templateprofile.useProxy;
1652 profile.useConnectionProxy=templateprofile.useConnectionProxy;
1653 // improved URI settings
1654 strncpy(profile.URIpath,templateprofile.URIpath,maxpathsiz);
1655 profile.protocol=templateprofile.protocol;
1656 // feature flags
1657 profile.readOnlyFlags = 0; // no read-only flags by default
1658 profile.featureFlags=templateprofile.featureFlags; // inherit features
1659 profile.dsAvailFlags=templateprofile.dsAvailFlags; // inherit datastore availability
1660 // extras
1661 profile.transpFlags=templateprofile.transpFlags; // inherit transport related flags
1662 profile.profileFlags=templateprofile.profileFlags; // inherit general profile flags
1663 // Note: do not copy profileExtra1/2 and profileData - as these are too app specific
1664 // local DB profile (not used in PPC, only for Outlook client)
1665 strncpy(profile.localDBProfileName,templateprofile.localDBProfileName,localDBpathMaxLen);
1666 // autosync settings
1667 profile.AutoSyncLevel[0]=templateprofile.AutoSyncLevel[0];
1668 profile.AutoSyncLevel[1]=templateprofile.AutoSyncLevel[1];
1669 profile.AutoSyncLevel[2]=templateprofile.AutoSyncLevel[2];
1670 // timed sync settings
1671 profile.TimedSyncMobilePeriod=templateprofile.TimedSyncMobilePeriod;
1672 profile.TimedSyncCradledPeriod=templateprofile.TimedSyncCradledPeriod;
1673 /* %%% do not copy IPP settings, these should be provisioned by the SyncML server
1674 // IPP settings (not available in all clients, but present in all profile records
1675 profile.ippSettings=templateprofile.ippSettings;
1676 */
1677 }
1678 }
1679 #ifndef HARD_CODED_SERVER_URI
1680 // override with config-defined fixed server URL, if any
1681 if (!fServerURI.empty()) {
1682 strncpy(profile.serverURI,fServerURI.c_str(),maxurisiz);
1683 profile.readOnlyFlags = rdonly_URI; // make URI readonly
1684 }
1685 #endif
1686 // save profile record
1687 profileIndex=writeProfile(-1,profile);
1688 // create a target for each configured datastore
1689 // Note: create target also for not available datastores
1690 TLocalDSList::iterator pos;
1691 for (pos=fDatastores.begin();pos!=fDatastores.end();pos++) {
1692 if ((*pos)->isAbstractDatastore()) continue; // don't try to create targets for abstract datastores (like superdatastores)
1693 // non-abstract datastores at this point are always binfile-based by definition (this is a binfileimplclient, and this is one of its datastores)
1694 TBinfileDSConfig *cfgP = static_cast<TBinfileDSConfig *>(*pos);
1695 cfgP->initTarget(target,profile.profileID,aSetDefaults ? NULL__null : "",aSetDefaults && DEFAULT_DATASTORES_ENABLEDfalse); // remote datastore names default to local ones, empty if not default
1696 // copy from template
1697 if (aTemplateProfile>=0) {
1698 // find matching template target
1699 sInt32 tti=findTargetIndexByDBInfo(
1700 templateprofile.profileID, // profile to search targets for
1701 cfgP->fLocalDBTypeID,
1702 NULL__null // can be NULL if name does not matter
1703 );
1704 if (tti>=0) {
1705 getTarget(tti,templatetarget);
1706 // copy user config
1707 strncpy(target.remoteDBpath,templatetarget.remoteDBpath,remoteDBpathMaxLen);
1708 target.syncmode=templatetarget.syncmode;
1709 target.limit1=templatetarget.limit1;
1710 target.limit2=templatetarget.limit2;
1711 target.extras=templatetarget.extras;
1712 target.enabled=false;
1713 target.forceSlowSync=false;
1714 }
1715 }
1716 // save target record
1717 writeTarget(-1,target);
1718 }
1719 return profileIndex;
1720} // TBinfileClientConfig::newProfile
1721
1722
1723// helper
1724static void AssignDefault(char *aCStr, bool aWithDefaults, const char *aDefault, size_t aLen)
1725{
1726 if (aWithDefaults)
1727 AssignCString(aCStr,aDefault,aLen);
1728 else
1729 AssignCString(aCStr,NULL__null,aLen);
1730} // AssignDefault
1731
1732
1733// init empty profile record
1734void TBinfileClientConfig::initProfile(TBinfileDBSyncProfile &aProfile, const char *aName, bool aWithDefaults)
1735{
1736 // - wipe it to all zeroes to make sure we don't save any garbage under no circumstances
1737 memset((void *)&aProfile,0,sizeof(TBinfileDBSyncProfile));
1738 // - Name
1739 if (aName==0) aName="<untitled>";
1740 strncpy(aProfile.profileName,aName,maxnamesiz);
1741 // - encoding defaults to WBXML
1742 aProfile.encoding=DEFAULT_ENCODINGSML_WBXML;
1743 AssignDefault(aProfile.serverURI,aWithDefaults, DEFAULT_SERVER_URI"", maxurisiz);
1744 // - suffix (for hardcoded base URI versions)
1745 AssignDefault(aProfile.URIpath,aWithDefaults, DEFAULT_URI_PATH__null, maxpathsiz);
1746 #ifdef PROTOCOL_SELECTOR
1747 aProfile.protocol=PROTOCOL_SELECTOR;
1748 #else
1749 aProfile.protocol=transp_proto_uri;
1750 #endif
1751 aProfile.readOnlyFlags=0; // all read&write so far
1752 aProfile.remoteFlags=0; // no remote specifics known so far
1753 #ifdef FTRFLAGS_ALWAYS_AVAILABLE
1754 aProfile.featureFlags=FTRFLAGS_ALWAYS_AVAILABLE; // set default availability
1755 #else
1756 aProfile.featureFlags=0; // no special feature flags
1757 #endif
1758 #ifdef DSFLAGS_ALWAYS_AVAILABLE
1759 aProfile.dsAvailFlags=DSFLAGS_ALWAYS_AVAILABLE; // set default availability
1760 #else
1761 aProfile.dsAvailFlags=0; // no extra DS enabled
1762 #endif
1763 // - User name
1764 AssignDefault(aProfile.serverUser,aWithDefaults, DEFAULT_SERVER_USER"", maxupwsiz);
1765 // - password, mangled
1766 assignMangledToCString(aProfile.serverPassword, (const char *)(aWithDefaults ? DEFAULT_SERVER_PASSWD"" : NULL__null), maxupwsiz,true);
1767 // - Transport user
1768 AssignDefault(aProfile.transportUser,aWithDefaults, DEFAULT_TRANSPORT_USER__null, maxupwsiz);
1769 // - Transport password, mangled
1770 assignMangledToCString(aProfile.transportPassword, (const char *)(aWithDefaults ? DEFAULT_TRANSPORT_PASSWD__null : NULL__null), maxupwsiz,true);
1771 // - Socks Host
1772 AssignDefault(aProfile.socksHost,aWithDefaults, DEFAULT_SOCKS_HOST__null, maxurisiz);
1773 // - Proxy Host
1774 AssignDefault(aProfile.proxyHost,aWithDefaults, DEFAULT_PROXY_HOST__null, maxurisiz);
1775 // - local DB profile name
1776 AssignDefault(aProfile.localDBProfileName,true,DEFAULT_LOCALDB_PROFILE"",localDBpathMaxLen);
1777 // - additional proxy flags
1778 aProfile.useProxy=aProfile.proxyHost[0]!=0; // use if a default proxy is defined
1779 aProfile.useConnectionProxy=DEFAULT_USESYSTEMPROXYtrue; // use proxy from connection if available
1780 // - proxy user
1781 AssignDefault(aProfile.proxyUser,aWithDefaults, DEFAULT_PROXY_USER__null, maxupwsiz);
1782 // - proxy password, mangled
1783 assignMangledToCString(aProfile.proxyPassword, (const char *)(aWithDefaults ? DEFAULT_PROXY_PASSWD__null : NULL__null), maxupwsiz,true);
1784 // - extra flags
1785 aProfile.transpFlags = 0;
1786 aProfile.profileFlags = 0;
1787 // - general purpose reserved fields
1788 aProfile.profileExtra1 = 0;
1789 aProfile.profileExtra2 = 0;
1790 memset(&aProfile.profileData, 0, profiledatasiz);
1791 // - automatic sync scheduling
1792 aProfile.AutoSyncLevel[0].Mode=autosync_none; // not enabled
1793 aProfile.AutoSyncLevel[0].StartDayTime=8*60; // 8:00 AM
1794 aProfile.AutoSyncLevel[0].EndDayTime=17*60; // 5:00 PM (17:00)
1795 aProfile.AutoSyncLevel[0].WeekdayMask=0x3E; // Mo-Fr
1796 aProfile.AutoSyncLevel[0].ChargeLevel=60; // 60% battery level needed
1797 aProfile.AutoSyncLevel[0].MemLevel=10; // 10% memory must be free
1798 aProfile.AutoSyncLevel[0].Flags=0; // no flags so far
1799 aProfile.AutoSyncLevel[1].Mode=autosync_none; // not enabled
1800 aProfile.AutoSyncLevel[1].StartDayTime=0;
1801 aProfile.AutoSyncLevel[1].EndDayTime=0;
1802 aProfile.AutoSyncLevel[1].WeekdayMask=0;
1803 aProfile.AutoSyncLevel[1].ChargeLevel=0;
1804 aProfile.AutoSyncLevel[1].MemLevel=0;
1805 aProfile.AutoSyncLevel[1].Flags=0;
1806 aProfile.AutoSyncLevel[2].Mode=autosync_none; // not enabled
1807 aProfile.AutoSyncLevel[2].StartDayTime=0;
1808 aProfile.AutoSyncLevel[2].EndDayTime=0;
1809 aProfile.AutoSyncLevel[2].WeekdayMask=0;
1810 aProfile.AutoSyncLevel[2].ChargeLevel=0;
1811 aProfile.AutoSyncLevel[2].MemLevel=0;
1812 aProfile.AutoSyncLevel[2].Flags=0;
1813 // Timed sync settings
1814 aProfile.TimedSyncMobilePeriod=2*60; // every 2 hours
1815 aProfile.TimedSyncCradledPeriod=15; // every 15 minutes
1816 // IPP settings
1817 aProfile.ippSettings.srv[0]=0;
1818 aProfile.ippSettings.port=0;
1819 aProfile.ippSettings.period=5*60; // 5 mins
1820 aProfile.ippSettings.path[0]=0;
1821 aProfile.ippSettings.id[0]=0;
1822 aProfile.ippSettings.method=0; // none defined
1823 aProfile.ippSettings.cred[0]=0;
1824 aProfile.ippSettings.maxinterval=0;
1825 aProfile.ippSettings.timedds[0]=0;
1826 // Internals
1827 // - session ID
1828 aProfile.sessionID=0;
1829 // - last connection's parameters (used as default for next session)
1830 aProfile.lastSyncMLVersion=syncml_vers_unknown;
1831 aProfile.lastAuthMethod=auth_none;
1832 aProfile.lastAuthFormat=fmt_chr;
1833 AssignCString(aProfile.lastNonce,NULL__null,maxnoncesiz);
1834} // initProfile
1835
1836
1837// checks that all profiles are complete with targets for all configured datastores
1838// (in case of STD->PRO upgrade for example)
1839void TBinfileClientConfig::checkProfiles(void)
1840{
1841 for (sInt32 pidx=0; pidx<numProfiles(); pidx++) {
1842 checkProfile(pidx);
1843 }
1844} // TBinfileClientConfig::checkProfiles
1845
1846
1847// checks that profile is complete with targets for all configured datastores
1848// (in case of STD->PRO upgrade for example)
1849void TBinfileClientConfig::checkProfile(sInt32 aProfileIndex)
1850{
1851 TBinfileDBSyncProfile profile;
1852
1853 // get profile record
1854 if (getProfile(aProfileIndex,profile)>=0) {
1855 // make sure a target exists for each configured datastore
1856 // Note: also creates targets for currently unavailable datastores (profile.dsAvailFlags, license...)
1857 TLocalDSList::iterator pos;
1858 for (pos=fDatastores.begin();pos!=fDatastores.end();pos++) {
1859 TBinfileDSConfig *cfgP = static_cast<TBinfileDSConfig *>(*pos);
1860 // find matching template target
1861 findOrCreateTargetIndexByDBInfo(
1862 profile.profileID, // profile to search targets for
1863 cfgP->fLocalDBTypeID,
1864 NULL__null // can be NULL if name does not matter
1865 );
1866 }
1867 }
1868} // TBinfileClientConfig::newProfile
1869
1870
1871
1872// - write profile, returns index of profile
1873sInt32 TBinfileClientConfig::writeProfile(
1874 sInt32 aProfileIndex, // -1 if adding new profile
1875 TBinfileDBSyncProfile &aProfile // profile ID is set to new ID in aProfile
1876)
1877{
1878 uInt32 newindex=aProfileIndex;
1879 if (aProfileIndex<0) {
1880 // set new unqiue ID
1881 aProfile.profileID=fProfileBinFile.getNextUniqueID();
1882 // create new record
1883 fProfileBinFile.newRecord(newindex,&aProfile);
1884 // make sure header is up to date (in case we terminate improperly)
1885 fProfileBinFile.flushHeader();
1886 }
1887 else {
1888 // find record
1889 fProfileBinFile.updateRecord(aProfileIndex,&aProfile);
1890 }
1891 // return index of data
1892 return newindex;
1893} // TBinfileClientConfig::writeProfile
1894
1895
1896// - delete profile (and all of its targets)
1897bool TBinfileClientConfig::deleteProfile(sInt32 aProfileIndex)
1898{
1899 // remove all targets
1900 sInt32 idx;
1901 uInt32 profileID = getIDOfProfile(aProfileIndex);
1902 if (profileID==0) return false;
1903 do {
1904 // find first (still existing) target for this profile
1905 idx = findTargetIndex(profileID,0);
1906 if (idx<0) break; // no more targets
1907 // if we have separate changelogs or this is the last profile, also delete targets' changelogs
1908 if (fSeparateChangelogs || fProfileBinFile.getNumRecords()<=1) {
1909 // clean related changelogs
1910 cleanChangeLogForTarget(idx,profileID);
1911 }
1912 // delete target
1913 deleteTarget(idx);
1914 } while (true);
1915 // remove profile itself
1916 if (fProfileBinFile.deleteRecord(aProfileIndex)!=BFE_OK0) return false;
1917 if (fProfileBinFile.getNumRecords()==0) {
1918 // last profile deleted, remove file itself to clean up as much as possible
1919 fProfileBinFile.closeAndDelete();
1920 // re-create
1921 fProfileBinFile.create(sizeof(TBinfileDBSyncProfile),0,NULL__null,true);
1922 }
1923 else {
1924 // make sure header is up to date (in case we terminate improperly)
1925 fProfileBinFile.flushHeader();
1926 }
1927 // return
1928 return true;
1929} // TBinfileClientConfig::deleteProfile
1930
1931
1932// - get number of existing profiles
1933sInt32 TBinfileClientConfig::numProfiles(void)
1934{
1935 return fProfileBinFile.getNumRecords();
1936} // TBinfileClientConfig::numProfiles
1937
1938
1939// - get profile, returns index or -1 if no more profiles
1940sInt32 TBinfileClientConfig::getProfile(
1941 sInt32 aProfileIndex,
1942 TBinfileDBSyncProfile &aProfile
1943)
1944{
1945 if (fProfileBinFile.readRecord(aProfileIndex,&aProfile)!=BFE_OK0)
1946 return -1;
1947 return aProfileIndex;
1948} // TBinfileClientConfig::getProfile
1949
1950
1951// - get index of profile by ID
1952sInt32 TBinfileClientConfig::getProfileIndex(uInt32 aProfileID)
1953{
1954 TBinfileDBSyncProfile profile;
1955 return getProfileByID(aProfileID,profile);
1956} // TBinfileClientConfig::getProfileIndex
1957
1958
1959// - get profile by ID, returns index or -1 if no profile found
1960// Note: aProfile might be writte even if profile is not found
1961sInt32 TBinfileClientConfig::getProfileByID(
1962 uInt32 aProfileID,
1963 TBinfileDBSyncProfile &aProfile
1964)
1965{
1966 sInt32 aIndex=0;
1967 while (true) {
1968 aIndex = getProfile(aIndex,aProfile);
1969 if (aIndex<0) break; // not found
1970 // check ID
1971 if (aProfile.profileID == aProfileID) break;
1972 // next profile
1973 aIndex++;
1974 }
1975 return aIndex;
1976} // TBinfileClientConfig::getProfile
1977
1978
1979// - get profile index from name, returns index or -1 if no matching profile found
1980sInt32 TBinfileClientConfig::getProfileIndexByName(cAppCharP aProfileName)
1981{
1982 sInt32 np = numProfiles();
1983 sInt32 pi = np;
1984 TBinfileDBSyncProfile profile;
1985 while (pi>0) {
1986 pi--;
1987 getProfile(pi,profile);
1988 if (strucmp(profile.profileName,aProfileName)==0) {
1989 return pi; // found, return index
1990 }
1991 }
1992 return -1; // not found
1993} // TBinfileClientConfig::getProfileByName
1994
1995
1996// - get ID of profile from index, 0 if none found
1997uInt32 TBinfileClientConfig::getIDOfProfile(sInt32 aProfileIndex)
1998{
1999 // get profile ID
2000 TBinfileDBSyncProfile profile;
2001 if (fProfileBinFile.readRecord(aProfileIndex,&profile)!=BFE_OK0)
2002 return 0;
2003 return profile.profileID;
2004} // TBinfileClientConfig::getIDOfProfile
2005
2006
2007
2008// - get last sync (earliest of lastSync of all sync-enabled targets), 0=never
2009bool TBinfileClientConfig::getProfileLastSyncTime(uInt32 aProfileID, lineartime_t &aLastSync, bool &aZapsServer, bool &aZapsClient)
2010{
2011 sInt32 i,targetIndex;
2012 uInt32 dbid;
2013 lineartime_t targlast;
2014 aLastSync=maxLinearTime;
2015 aZapsServer=false;
2016 aZapsClient=false;
2017 bool zs,zc;
2018 i=0;
2019 do {
2020 targetIndex=findTargetIndex(aProfileID,i++);
2021 if (targetIndex<0) break;
2022 // get last sync of this target
2023 if (getTargetLastSyncTime(targetIndex,targlast,zs,zc,dbid)) {
2024 // enabled target
2025 if (targlast<aLastSync) aLastSync=targlast;
2026 aZapsServer = aZapsServer || zs;
2027 aZapsClient = aZapsClient || zc;
2028 }
2029 } while(true);
2030 return aLastSync!=maxLinearTime; // at least one enabled target
2031} // TBinfileClientConfig::getProfileLastSyncTime
2032
2033
2034// - get last sync (earliest of lastSync of all sync-enabled targets), 0=never
2035bool TBinfileClientConfig::getTargetLastSyncTime(sInt32 aTargetIndex, lineartime_t &aLastSync, bool &aZapsServer, bool &aZapsClient, uInt32 &aDBID)
2036{
2037 // get target
2038 TBinfileDBSyncTarget target;
2039 if (fTargetsBinFile.readRecord(aTargetIndex,&target)!=BFE_OK0)
2040 return false; // no such target
2041 return getTargetLastSyncTime(target, aLastSync, aZapsServer, aZapsClient, aDBID);
2042} // TBinfileClientConfig::getTargetLastSyncTime
2043
2044
2045// - get last sync (earliest of lastSync of all sync-enabled targets), 0=never
2046bool TBinfileClientConfig::getTargetLastSyncTime(TBinfileDBSyncTarget &aTarget, lineartime_t &aLastSync, bool &aZapsServer, bool &aZapsClient, uInt32 &aDBID)
2047{
2048 // returns info even if not enabled
2049 // Note: if suspended, zapping has already occurred (and has been confirmed, so don't report it here)
2050 aZapsServer=aTarget.syncmode==smo_fromclient && (aTarget.forceSlowSync || *(aTarget.remoteAnchor)==0) && aTarget.resumeAlertCode==0;
2051 aZapsClient=aTarget.syncmode==smo_fromserver && (aTarget.forceSlowSync || *(aTarget.remoteAnchor)==0) && aTarget.resumeAlertCode==0;
2052 // return info anyway
2053 aLastSync=aTarget.lastSync;
2054 aDBID=aTarget.localDBTypeID;
2055 return aTarget.enabled;
2056} // TBinfileClientConfig::getTargetLastSyncTime
2057
2058
2059
2060// - check for feature enabled (profile or license dependent)
2061bool TBinfileClientConfig::isFeatureEnabled(sInt32 aProfileIndex, uInt16 aFeatureNo)
2062{
2063 TBinfileDBSyncProfile profile;
2064 if (getProfile(aProfileIndex,profile)<0)
2065 return isFeatureEnabled((TBinfileDBSyncProfile *)NULL__null, aFeatureNo); // no profile, get general availablity
2066 else
2067 return isFeatureEnabled(&profile, aFeatureNo); // check if available in this profile
2068} // TBinfileClientConfig::isFeatureEnabled
2069
2070
2071// - check for feature enabled (profile or license dependent)
2072bool TBinfileClientConfig::isFeatureEnabled(TBinfileDBSyncProfile *aProfileP, uInt16 aFeatureNo)
2073{
2074 // first check for general (local) availability
2075 bool locAvail;
2076 switch (aFeatureNo) {
2077 #ifdef CGI_SERVER_OPTIONS1
2078 // we have the range options
2079 case APP_FTR_EVENTRANGE:
2080 case APP_FTR_EMAILRANGE:
2081 locAvail=true; break;
2082 #endif
2083 default:
2084 locAvail=false;
2085 }
2086 // if not locally available anyway - check for general (global) availability
2087 if (!locAvail && !getSyncAppBase()->isFeatureEnabled(aFeatureNo))
2088 return false; // this feature is not enabled at all
2089 #ifdef FTRFLAGS_ALWAYS_AVAILABLE
2090 // check for profile-level enabling
2091 // - get flag for feature No
2092 uInt8 ftrflag=0;
2093 switch (aFeatureNo) {
2094 case APP_FTR_AUTOSYNC:
2095 ftrflag=ftrflg_autosync; break;
2096 case APP_FTR_IPP:
2097 ftrflag=ftrflg_dmu; break;
2098 case APP_FTR_EVENTRANGE:
2099 case APP_FTR_EMAILRANGE:
2100 ftrflag=ftrflg_range; break;
2101 default : return true; // not a profile-level feature, but it is globally on -> is enabled
2102 }
2103 // - check if generally enabled even if not in profile flags
2104 if ((ftrflag & FTRFLAGS_ALWAYS_AVAILABLE)!=0)
2105 return true; // always available (hardcoded)
2106 // - now it depends on the profile flags
2107 return (aProfileP && (aProfileP->featureFlags & ftrflag)!=0);
2108 #else
2109 // no profile level feature enabling - everything that is globally enabled is also enabled in this profile
2110 return true;
2111 #endif
2112} // TBinfileClientConfig::isFeatureEnabled
2113
2114
2115// - check for feature enabled (profile or license dependent)
2116bool TBinfileClientConfig::isReadOnly(sInt32 aProfileIndex, uInt8 aReadOnlyMask)
2117{
2118 TBinfileDBSyncProfile profile;
2119 if (getProfile(aProfileIndex,profile)<0)
2120 return true; // make all read-only if we have no profile
2121 else
2122 return isReadOnly(&profile, aReadOnlyMask); // check if available in this profile
2123} // TBinfileClientConfig::isFeatureEnabled
2124
2125
2126// - check for readonly (profile or license dependent)
2127bool TBinfileClientConfig::isReadOnly(TBinfileDBSyncProfile *aProfileP, uInt8 aReadOnlyMask)
2128{
2129 // check special hardcoded cases
2130 #ifdef HARD_CODED_DBNAMES
2131 if (aReadOnlyMask & rdonly_dbpath) return true; // with hardcoded DB names, these are ALWAYS readonly
2132 #endif
2133 #ifdef HARD_CODED_SERVER_URI
2134 if (aReadOnlyMask & rdonly_URI) return true; // with hardcoded URI, this is ALWAYS readonly
2135 #endif
2136
2137 // just check profile flags
2138 if (!aProfileP) return true; // make all read-only if we have no profile
2139 return aProfileP->readOnlyFlags & aReadOnlyMask; // readonly if flag is set in profile
2140} // TBinfileClientConfig::isReadOnly
2141
2142
2143// - check if datastore of specified target is available
2144// in the given profile
2145bool TBinfileClientConfig::isTargetAvailable(
2146 TBinfileDBSyncProfile *aProfileP,
2147 uInt32 aLocalDBTypeID
2148) {
2149 TLocalDSList::iterator pos;
2150 for (pos=fDatastores.begin();pos!=fDatastores.end();pos++) {
2151 TBinfileDSConfig *cfgP = static_cast<TBinfileDSConfig *>(*pos);
2152 if (
2153 cfgP->fLocalDBTypeID==aLocalDBTypeID
2154 ) {
2155 // right datastore config found
2156 // - return it's availability status
2157 return cfgP->isAvailable(aProfileP);
2158 }
2159 }
2160 // datastore not found -> not available
2161 return false;
2162} // TBinfileClientConfig::isTargetAvailable
2163
2164
2165// - find available target for profile by DB ID/name. Returns target index or -1 if
2166// DBTypeID not available in this profile/license or not implemented at all
2167sInt32 TBinfileClientConfig::findAvailableTargetIndexByDBInfo(
2168 TBinfileDBSyncProfile *aProfileP, // profile to search targets for
2169 uInt32 aLocalDBTypeID,
2170 const char *aLocalDBName // can be NULL if name does not matter
2171)
2172{
2173 if (!isTargetAvailable(aProfileP,aLocalDBTypeID)) return -1;
2174 if (!aProfileP) return -1; // no profile, no target
2175 return findOrCreateTargetIndexByDBInfo(aProfileP->profileID,aLocalDBTypeID,aLocalDBName);
2176} // TBinfileClientConfig::findAvailableTargetIndexByDBInfo
2177
2178
2179// - find target for profile by DB ID/name. Returns target index or -1 if none found
2180sInt32 TBinfileClientConfig::findOrCreateTargetIndexByDBInfo(
2181 uInt32 aProfileID, // profile to search targets for
2182 uInt32 aLocalDBTypeID,
2183 const char *aLocalDBName // can be NULL if name does not matter
2184)
2185{
2186 sInt32 targidx;
2187 TBinfileDBSyncTarget target;
2188
2189 targidx=findTargetIndexByDBInfo(aProfileID,aLocalDBTypeID,aLocalDBName);
2190 if (targidx<0) {
2191 // does not exist yet, create it now
2192 TLocalDSList::iterator pos;
2193 for (pos=fDatastores.begin();pos!=fDatastores.end();pos++) {
2194 if ((*pos)->isAbstractDatastore()) continue; // only non-abstract datastores are guaranteed binfileds and have a target
2195 TBinfileDSConfig *cfgP = static_cast<TBinfileDSConfig *>(*pos);
2196 if (
2197 cfgP->fLocalDBTypeID==aLocalDBTypeID &&
2198 (aLocalDBName==NULL__null || cfgP->fLocalDBPath==aLocalDBName)
2199 ) {
2200 // right datastore found
2201 cfgP->initTarget(target,aProfileID,NULL__null,DEFAULT_DATASTORES_ENABLEDfalse); // init default
2202 // write new target and get a index back
2203 targidx=writeTarget(-1,target);
2204 // done
2205 break;
2206 }
2207 }
2208 }
2209 return targidx;
2210} // findOrCreateTargetIndexByDBInfo
2211
2212
2213// - find target for profile by DB ID/name. Returns target index or -1 if none found
2214sInt32 TBinfileClientConfig::findTargetIndexByDBInfo(
2215 uInt32 aProfileID, // profile to search targets for
2216 uInt32 aLocalDBTypeID,
2217 const char *aLocalDBName // can be NULL if name does not matter
2218)
2219{
2220 // now search targets
2221 TBinfileDBSyncTarget target;
2222 sInt32 maxidx = fTargetsBinFile.getNumRecords();
2223 sInt32 targidx;
2224 for (targidx=0; targidx<maxidx; targidx++) {
2225 fTargetsBinFile.readRecord(targidx,&target);
2226 if (
2227 target.remotepartyID == aProfileID &&
2228 target.localDBTypeID==aLocalDBTypeID &&
2229 (aLocalDBName==NULL__null || strucmp(target.localDBPath,aLocalDBName)==0)
2230 ) {
2231 // target found, return its index
2232 return targidx;
2233 }
2234 }
2235 // none found
2236 return -1;
2237} // TBinfileClientConfig::findTargetIndexByDBInfo
2238
2239
2240// - find n-th target for profile. Returns target index or -1 if none found
2241sInt32 TBinfileClientConfig::findTargetIndex(
2242 uInt32 aProfileID, // profile to search targets for
2243 sInt32 aTargetSeqNum // sequence number (0..n)
2244)
2245{
2246 // now search targets
2247 TBinfileDBSyncTarget target;
2248 sInt32 maxidx = fTargetsBinFile.getNumRecords();
2249 sInt32 targidx;
2250 for (targidx=0; targidx<maxidx; targidx++) {
2251 fTargetsBinFile.readRecord(targidx,&target);
2252 if (target.remotepartyID == aProfileID) {
2253 // belongs to that profile
2254 if (aTargetSeqNum<=0) {
2255 // n-th target found, return its index
2256 return targidx;
2257 }
2258 aTargetSeqNum--; // next in sequence
2259 }
2260 }
2261 // none found
2262 return -1;
2263} // TBinfileClientConfig::findTargetIndex
2264
2265
2266// - write target for profile, returns index of target
2267sInt32 TBinfileClientConfig::writeTarget(
2268 sInt32 aTargetIndex, // -1 if adding new target
2269 const TBinfileDBSyncTarget &aTarget
2270)
2271{
2272 uInt32 newindex;
2273
2274 if (aTargetIndex<0) {
2275 // create new record
2276 fTargetsBinFile.newRecord(newindex,&aTarget);
2277 // make sure header is up to date (in case we terminate improperly)
2278 fTargetsBinFile.flushHeader();
2279 return newindex;
2280 }
2281 else {
2282 // update record
2283 fTargetsBinFile.updateRecord(aTargetIndex,&aTarget);
2284 return aTargetIndex;
2285 }
2286} // TBinfileClientConfig::writeTarget
2287
2288
2289// - delete target
2290bool TBinfileClientConfig::deleteTarget(
2291 sInt32 aTargetIndex
2292)
2293{
2294 if (fTargetsBinFile.deleteRecord(aTargetIndex)!=BFE_OK0) return false;
2295 if (fTargetsBinFile.getNumRecords()==0) {
2296 // last target deleted, remove file itself to clean up as much as possible
2297 fTargetsBinFile.closeAndDelete();
2298 fTargetsBinFile.create(sizeof(TBinfileDBSyncTarget),0,NULL__null,true);
2299 }
2300 else {
2301 // make sure header is up to date (in case we terminate improperly)
2302 fTargetsBinFile.flushHeader();
2303 }
2304 return true; // ok
2305} // TBinfileClientConfig::deleteTarget
2306
2307
2308// - get target info
2309sInt32 TBinfileClientConfig::getTarget(
2310 sInt32 aTargetIndex,
2311 TBinfileDBSyncTarget &aTarget
2312)
2313{
2314 if (aTargetIndex<0) return -1; // no valid target index, do not even try to read
2315 if (fTargetsBinFile.readRecord(aTargetIndex,&aTarget)!=BFE_OK0)
2316 return -1;
2317 return aTargetIndex;
2318} // TBinfileClientConfig::getTarget
2319
2320
2321// get base name for profile-dependent names
2322string TBinfileClientConfig::relatedDBNameBase(cAppCharP aDBName, sInt32 aProfileID)
2323{
2324 string basefilename;
2325 // prepare base name
2326 getBinFilesPath(basefilename);
2327 basefilename += aDBName;
2328 if (fSeparateChangelogs && aProfileID>=0) {
2329 StringObjAppendPrintf(basefilename, "_%d",aProfileID);
2330 }
2331 return basefilename;
2332}
2333
2334
2335// completely clear changelog and pending maps for specified target
2336void TBinfileClientConfig::cleanChangeLogForTarget(sInt32 aTargetIndex, sInt32 aProfileID)
2337{
2338 TBinfileDBSyncTarget target;
2339 getTarget(aTargetIndex,target);
2340 cleanChangeLogForDBname(target.dbname, aProfileID);
2341} // TBinfileClientConfig::cleanChangeLogForTarget
2342
2343
2344// completely clear changelog and pending maps for specified database name and profile
2345void TBinfileClientConfig::cleanChangeLogForDBname(cAppCharP aDBName, sInt32 aProfileID)
2346{
2347 // open changelog. Name is datastore name with _XXX_clg.bfi suffix (XXX=profileID, if negative, combined changelog/maps/pendingitem will be deleted)
2348 string basefilename = relatedDBNameBase(aDBName, aProfileID);
2349 string filename;
2350 TBinFile binfile;
2351 // delete changelog
2352 filename = basefilename + CHANGELOG_DB_SUFFIX"_clg_" "sysynclib_" ".bfi";
2353 binfile.setFileInfo(filename.c_str(),CHANGELOG_DB_VERSION5,CHANGELOG_DB_ID4,0);
2354 binfile.closeAndDelete();
2355 // delete pending maps
2356 filename = basefilename + PENDINGMAP_DB_SUFFIX"_pmap_" "sysynclib_" ".bfi";
2357 binfile.setFileInfo(filename.c_str(),PENDINGMAP_DB_VERSION1,PENDINGMAP_DB_ID7,0);
2358 binfile.closeAndDelete();
2359 // delete pending item
2360 filename = basefilename + PENDINGITEM_DB_SUFFIX"_pitm_" "sysynclib_" ".bfi";
2361 binfile.setFileInfo(filename.c_str(),PENDINGITEM_DB_VERSION1,PENDINGITEM_DB_ID8,0);
2362 binfile.closeAndDelete();
2363} // TBinfileClientConfig::cleanChangeLogForDBname
2364
2365
2366
2367void TBinfileClientConfig::separateDBFile(cAppCharP aDBName, cAppCharP aDBSuffix, sInt32 aProfileID)
2368{
2369 TBinFile sourceFile;
2370 TBinFile targetFile;
2371 string sourceName = relatedDBNameBase(aDBName, -1) + aDBSuffix; // without profile ID in name
2372 string targetName = relatedDBNameBase(aDBName, aProfileID) + aDBSuffix; // with profile ID in name
2373 sourceFile.setFileInfo(sourceName.c_str(), 0, 0, 0);
2374 targetFile.setFileInfo(targetName.c_str(), 0, 0, 0);
2375 targetFile.createAsCopyFrom(sourceFile);
2376}
2377
2378
2379// separate changelogs and other related files into separate files for each profile
2380void TBinfileClientConfig::separateChangeLogsAndRelated(cAppCharP aDBName)
2381{
2382 // iterate over all profiles
2383 TBinfileDBSyncProfile profile;
2384 sInt32 idx = 0;
2385 // set up original basename
2386 while (true) {
2387 idx = getProfile(idx,profile);
2388 if (idx<0) break; // no more profiles
2389 // copy all dependent files of that profile and the given database
2390 // - copy changelog
2391 separateDBFile(aDBName,CHANGELOG_DB_SUFFIX"_clg_" "sysynclib_" ".bfi",profile.profileID);
2392 // - copy pendingmaps
2393 separateDBFile(aDBName,PENDINGMAP_DB_SUFFIX"_pmap_" "sysynclib_" ".bfi",profile.profileID);
2394 // - copy pendingitem
2395 separateDBFile(aDBName,PENDINGITEM_DB_SUFFIX"_pitm_" "sysynclib_" ".bfi",profile.profileID);
2396 // next profile
2397 idx++;
2398 }
2399 // - delete original files that were shared between profiles
2400 cleanChangeLogForDBname(aDBName,-1);
2401}
2402
2403
2404
2405
2406// remote provisioning (using generic code in include file)
2407#include "clientprovisioning_inc.cpp"
2408// Autosync mechanisms (using generic code in include file)
2409#include "clientautosync_inc.cpp"
2410
2411/*
2412 * Implementation of TBinfileImplClient
2413 */
2414
2415/* public TBinfileImplClient members */
2416
2417
2418TBinfileImplClient::TBinfileImplClient(TSyncAppBase *aSyncAppBaseP, TSyncSessionHandle *aSyncSessionHandleP, cAppCharP aSessionID) :
2419 TStdLogicAgent(aSyncAppBaseP, aSyncSessionHandleP, aSessionID),
2420 fConfigP(NULL__null)
2421{
2422 // get config for agent
2423 TRootConfig *rootcfgP = aSyncAppBaseP->getRootConfig();
2424 // - save direct link to agent config for easy reference
2425 fConfigP = static_cast<TBinfileClientConfig *>(rootcfgP->fAgentConfigP);
2426 // - make profile invalid
2427 fProfileIndex=-1;
2428 fProfileDirty=false;
2429 // Note: Datastores are already created from config
2430} // TBinfileImplClient::TBinfileImplClient
2431
2432
2433TBinfileImplClient::~TBinfileImplClient()
2434{
2435 // make sure everything is terminated BEFORE destruction of hierarchy begins
2436 TerminateSession();
2437} // TBinfileImplClient::~TBinfileImplClient
2438
2439
2440// Terminate session
2441void TBinfileImplClient::TerminateSession()
2442{
2443 if (!fTerminated && fConfigP->fBinfilesActive) {
2444 // save profile changes
2445 if (fProfileIndex>=0 && fProfileDirty) {
2446 fConfigP->fProfileBinFile.updateRecord(fProfileIndex,&fProfile);
2447 fProfileDirty=false;
2448 fProfileIndex=-1;
2449 }
2450 // now reset session
2451 InternalResetSession();
2452 // make sure all data is flushed
2453 fConfigP->fProfileBinFile.flushHeader();
2454 fConfigP->fTargetsBinFile.flushHeader();
2455 }
2456 inherited::TerminateSession();
2457} // TBinfileImplClient::TerminateSession
2458
2459
2460
2461#ifdef ENGINEINTERFACE_SUPPORT1
2462
2463// set profileID to client session before doing first SessionStep
2464void TBinfileImplClient::SetProfileSelector(uInt32 aProfileSelector)
2465{
2466 if (aProfileSelector==0)
2467 fProfileSelectorInternal = DEFAULT_PROFILE_ID0xFFFFFFFF;
2468 else
2469 fProfileSelectorInternal = fConfigP->getProfileIndex(aProfileSelector);
2470} // TBinfileImplClient::SetProfileSelector
2471
2472
2473/// @brief Get new session key to access details of this session
2474appPointer TBinfileImplClient::newSessionKey(TEngineInterface *aEngineInterfaceP)
2475{
2476 return new TBinFileAgentParamsKey(aEngineInterfaceP,this);
2477} // TBinfileImplClient::newSessionKey
2478
2479#endif // ENGINEINTERFACE_SUPPORT
2480
2481
2482// Reset session
2483void TBinfileImplClient::InternalResetSession(void)
2484{
2485 // reset all datastores now to make sure all DB activity is done
2486 // before we possibly close session-global databases
2487 // (Note: TerminateDatastores() will be called again by TSyncSession)
2488 TerminateDatastores();
2489 fRemoteFlags=0; // no remote-specifics enabled so far
2490} // TBinfileImplClient::InternalResetSession
2491
2492
2493// Virtual version
2494void TBinfileImplClient::ResetSession(void)
2495{
2496 if (fConfigP->fBinfilesActive) {
2497 // do my own stuff
2498 InternalResetSession();
2499 }
2500 // let ancestor do its stuff
2501 TStdLogicAgent::ResetSession();
2502} // TBinfileImplClient::ResetSession
2503
2504
2505// - load remote connect params (syncml version, type, format and last nonce)
2506// Note: agents that can cache this information between sessions will load
2507// last info here.
2508void TBinfileImplClient::loadRemoteParams(void)
2509{
2510 if (!fConfigP->fBinfilesActive || fProfileIndex<0) {
2511 // not active or no profile loaded, let ancestor handle case
2512 TStdLogicAgent::loadRemoteParams();
2513 }
2514 else {
2515 // copy profile cached values
2516 fSyncMLVersion=
2517 fProfile.lastSyncMLVersion >= numSyncMLVersions ?
2518 syncml_vers_unknown : // if profile has higher version than we support, reset to unknown
2519 fProfile.lastSyncMLVersion;
2520 fRemoteRequestedAuth=
2521 fProfile.lastAuthMethod >= numAuthTypes ?
2522 auth_md5 : // if auth is unknown, reset to MD5
2523 fProfile.lastAuthMethod;
2524 fRemoteRequestedAuthEnc=
2525 fProfile.lastAuthFormat >= numFmtTypes ?
2526 fmt_b64 : // if format is unknown, reset to B64
2527 fProfile.lastAuthFormat;
2528 fRemoteNonce=fProfile.lastNonce;
2529 fRemoteFlags=fProfile.remoteFlags; // init remote specific behaviour flags from profile
2530 }
2531 // modify some behaviour based on remote flags
2532 if (fRemoteFlags & remotespecs_noDS12Filters)
2533 fServerHasSINCEBEFORE = false; // prevent auto-generated SINCE/BEFORE
2534} // TBinfileImplClient::loadRemoteParams
2535
2536
2537// - save remote connect params for use in next session (if descendant implements it)
2538void TBinfileImplClient::saveRemoteParams(void)
2539{
2540 if (fConfigP->fBinfilesActive && fProfileIndex>=0) {
2541 // save values to profile
2542 // - SyncML version (save it only if it is "better" than what we knew so far)
2543 if (fSyncMLVersion > fProfile.lastSyncMLVersion) {
2544 fProfile.lastSyncMLVersion=fSyncMLVersion;
2545 }
2546 fProfile.lastAuthMethod=fRemoteRequestedAuth;
2547 fProfile.lastAuthFormat=fRemoteRequestedAuthEnc;
2548 fProfile.remoteFlags=fRemoteFlags; // save remote-specific behaviour flags
2549 fProfileDirty=true;
2550 AssignCString(fProfile.lastNonce,fRemoteNonce.c_str(),maxnoncesiz);
2551 }
2552} // TBinfileImplClient::saveRemoteParams
2553
2554
2555// check remote devinf to detect special behaviour needed for some servers.
2556localstatus TBinfileImplClient::checkRemoteSpecifics(SmlDevInfDevInfPtr_t aDevInfP, SmlDevInfDevInfPtr_t *aOverrideDevInfP)
2557{
2558 if (fConfigP->fBinfilesActive && aDevInfP) {
2559 // check for some specific servers we KNOW they need special treatment
2560 uInt8 setFlags = 0;
2561 uInt8 clearFlags = 0;
2562 if (strnncmp(smlPCDataToCharP(aDevInfP->devid),"OracleSyncServer")==0) {
2563 // Oracle OCS
2564 // - unqiue ID even if device might have non-unique ones
2565 // - no X-nnn type params
2566 // - no DS 1.2 <filter>
2567 PDEBUGPRINTFX(DBG_HOT+DBG_REMOTEINFO,("Detected Oracle OCS Server - suppress dynamic X-nnnn TYPE params, and <filter>")){ if (((0x00000001 +0x00000100) & getDbgMask()) == (0x00000001
+0x00000100)) getDbgLogger()->setNextMask(0x00000001 +0x00000100
).DebugPrintfLastMask ("Detected Oracle OCS Server - suppress dynamic X-nnnn TYPE params, and <filter>"
); }
;
2568 setFlags |= remotespecs_noXTypeParams+remotespecs_noDS12Filters;
2569 #ifndef GUARANTEED_UNIQUE_DEVICID
2570 // - Oracle OCS needs unique deviceID/locURI under ALL circumstances as they do
2571 // session tracking by locURI, so we always use a hash of deviceID + username
2572 // as visible deviceID
2573 PDEBUGPRINTFX(DBG_HOT+DBG_REMOTEINFO,("OCS with device that has not guaranteed unique ID - use user+devid hash for Source LocURI")){ if (((0x00000001 +0x00000100) & getDbgMask()) == (0x00000001
+0x00000100)) getDbgLogger()->setNextMask(0x00000001 +0x00000100
).DebugPrintfLastMask ("OCS with device that has not guaranteed unique ID - use user+devid hash for Source LocURI"
); }
;
2574 setFlags |= remotespecs_devidWithUserHash;
2575 #else
2576 clearFlags |= remotespecs_devidWithUserHash;
2577 #endif
2578 }
2579 else if (strnncmp(smlPCDataToCharP(aDevInfP->mod), "Beehive", 7)==0) {
2580 // Oracle Beehive, <mod> starts with "Beehive", i.e. "Beehive R1"
2581 // - no DS 1.2 <filter>
2582 PDEBUGPRINTFX(DBG_HOT+DBG_REMOTEINFO,("Detected Oracle Beehive - suppress <filter>")){ if (((0x00000001 +0x00000100) & getDbgMask()) == (0x00000001
+0x00000100)) getDbgLogger()->setNextMask(0x00000001 +0x00000100
).DebugPrintfLastMask ("Detected Oracle Beehive - suppress <filter>"
); }
;
2583 setFlags |= remotespecs_noDS12Filters;
2584 clearFlags |= remotespecs_noXTypeParams+remotespecs_devidWithUserHash;
2585 }
2586 else {
2587 // make sure oracle-specific flags are cleared for all other server types
2588 clearFlags |= remotespecs_noXTypeParams+remotespecs_noDS12Filters+remotespecs_devidWithUserHash;
2589 }
2590 // now apply
2591 sInt8 newFlags = (fRemoteFlags & ~clearFlags) | setFlags;
2592 if (newFlags != fRemoteFlags) {
2593 // change of remotespecs_devidWithUserHash needs session restart
2594 bool needrestart = (newFlags & remotespecs_devidWithUserHash) != (fRemoteFlags & remotespecs_devidWithUserHash);
2595 // remote flags need to be changed
2596 fRemoteFlags = newFlags;
2597 // save them into profile
2598 saveRemoteParams();
2599 // restart session when needed
2600 if (needrestart) {
2601 // - abort session, but have main loop retry starting it
2602 PDEBUGPRINTFX(DBG_ERROR,("Warning: must restart session with changed remotespecs_devidWithUserHash")){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("Warning: must restart session with changed remotespecs_devidWithUserHash"
); }
;
2603 AbortSession(LOCERR_RESTART,true);
2604 }
2605 }
2606 }
2607 // let session handle other details
2608 return inherited::checkRemoteSpecifics(aDevInfP, aOverrideDevInfP);
2609} // TBinfileImplClient::checkRemoteSpecifics
2610
2611
2612#ifdef IPP_SUPPORT
2613
2614// generates custom PUT in case IPP/DMU is enabled to request settings
2615void TBinfileImplClient::issueCustomGetPut(bool aGotDevInf, bool aSentDevInf)
2616{
2617 if (fConfigP->fBinfilesActive) {
2618 // get autosync PUT req string
2619 string req;
2620 fConfigP->autosync_get_putrequest(req);
2621 // now create a PUT
2622 if (!req.empty()) {
2623 TPutCommand *putcommandP = new TPutCommand(this);
2624 putcommandP->setMeta(newMetaType(IPP_PARAMS_ITEM_METATYPE"text/plain"));
2625 SmlItemPtr_t putItemP = putcommandP->addSourceLocItem(IPP_PARAMS_LOCURI_REQ"./vendor/synthesis/ipp10/" "req");
2626 // - add data to item
2627 putItemP->data = newPCDataString(req.c_str());
2628 putcommandP->allowFailure(); // do not abort session in case server does not understand the command
2629 ISSUE_COMMAND_ROOT(this,putcommandP){ TSmlCommand* p=putcommandP; putcommandP=__null; this->issueRootPtr
(p); }
;
2630 }
2631 }
2632 // let ancestors issue their custom gets and puts, if any
2633 inherited::issueCustomGetPut(aGotDevInf, aSentDevInf);
2634} // TBinfileImplClient::issueCustomGetPut
2635
2636#endif // IPP_SUPPORT
2637
2638
2639// handler of custom IPP/DMU put and result commands
2640void TBinfileImplClient::processPutResultItem(bool aIsPut, const char *aLocUri, TSmlCommand *aPutResultsCommandP, SmlItemPtr_t aPutResultsItemP, TStatusCommand &aStatusCommand)
2641{
2642 if (fConfigP->fBinfilesActive) {
2643 #ifdef IPP_SUPPORT
2644 // check for DMU specials
2645 if (strucmp(relativeURI(aLocUri),relativeURI(IPP_PARAMS_LOCURI_CFG"./vendor/synthesis/ipp10/" "cfg"))==0) {
2646 // get DMU string
2647 const char *ippstring = smlItemDataToCharP(aPutResultsItemP);
2648 PDEBUGPRINTFX(DBG_HOT,("received IPP config string: %s",ippstring)){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("received IPP config string: %s"
,ippstring); }
;
2649 // process it
2650 string tag,value;
2651 while (ippstring && *ippstring) {
2652 ippstring=nextTag(ippstring,tag,value);
2653 // set ipp params in current profile
2654 fConfigP->ipp_setparam(tag.c_str(),value.c_str(),fProfile.ippSettings);
2655 // make sure autosync profile copy gets updated as well
2656 if (fConfigP->fAutosyncProfileLastidx==fProfileIndex) {
2657 fConfigP->fAutosyncProfile = fProfile; // copy profile into autosync
2658 fConfigP->autosync_condchanged(); // do immediately check settings at next autosync step
2659 }
2660 // make sure profile gets saved
2661 fProfileDirty=true;
2662 }
2663 // is ok
2664 aStatusCommand.setStatusCode(200); // is ok
2665 aStatusCommand.dontSend(); // ..but do not send it (%%% as session would then end with error 9999)
2666 }
2667 else
2668 #endif
2669 #ifdef SETTINGS_PROVISIONING_VIA_PUT
2670 // check for provisioning strings arriving via PUT command
2671 if (strucmp(relativeURI(aLocUri),relativeURI(SETTINGS_LOCURI_CFG"./vendor/synthesis/settings10/" "cfg"))==0) {
2672 // get provisioning string
2673 const char *provstring = smlItemDataToCharP(aPutResultsItemP);
2674 PDEBUGPRINTFX(DBG_HOT,("received settings provisioning string: %s",provstring)){ if (((0x00000001) & getDbgMask()) == (0x00000001)) getDbgLogger
()->setNextMask(0x00000001).DebugPrintfLastMask ("received settings provisioning string: %s"
,provstring); }
;
2675 // process it
2676 // - but first save current profile
2677 fConfigP->writeProfile(fProfileIndex,fProfile);
2678 // - now modify profile (may include the current profile)
2679 sInt32 activeprofile;
2680 bool provok = fConfigP->executeProvisioningString(provstring, activeprofile);
2681 // - reload current profile (possibly modified)
2682 fConfigP->getProfile(fProfileIndex,fProfile);
2683 // is ok
2684 aStatusCommand.setStatusCode(provok ? 200 : 400); // ok or bad request
2685 aStatusCommand.dontSend(); // ..but do not send it (%%% as session would then end with error 9999)
2686 }
2687 else
2688 #endif
2689 {
2690 // let ancestors process it
2691 inherited::processPutResultItem(aIsPut,aLocUri,aPutResultsCommandP,aPutResultsItemP,aStatusCommand);
2692 }
2693 }
2694 else {
2695 // let ancestors process it
2696 inherited::processPutResultItem(aIsPut,aLocUri,aPutResultsCommandP,aPutResultsItemP,aStatusCommand);
2697 }
2698} // TBinfileImplClient::processPutResultItem
2699
2700
2701
2702
2703
2704#ifdef PROTOCOL_SELECTOR
2705// Names of protocols according to TTransportProtocols
2706const char * const Protocol_Names[num_transp_protos] = {
2707 "", // none, protocol contained in URI
2708 "http://",
2709 "https://",
2710 "wsp://", // WSP protocol
2711 "OBEX:IRDA", // OBEX/IRDA protocol
2712 "OBEX:BT", // OBEX/BT protocol
2713 "OBEX://", // OBEX/TCP protocol
2714};
2715#endif
2716
2717
2718// - selects a profile (returns LOCERR_NOCFG if profile not found)
2719// Note: This call must create and initialize all datastores that
2720// are to be synced with that profile.
2721localstatus TBinfileImplClient::SelectProfile(uInt32 aProfileSelector, bool aAutoSyncSession)
2722{
2723 uInt32 recidx,maxidx;
2724 // detect special tunnel session's selection
2725 bool tunnel = aProfileSelector==TUNNEL_PROFILE_ID0xFFFFFFFE;
2726 // select profile if active
2727 if (fConfigP->fBinfilesActive) {
2728 if (tunnel) {
2729 aProfileSelector=DEFAULT_PROFILE_ID0xFFFFFFFF;
2730 }
2731 // Note: profile database has already been opened in config resolve()
2732 if (aProfileSelector==DEFAULT_PROFILE_ID0xFFFFFFFF) {
2733 // default is first one
2734 aProfileSelector=0;
2735 }
2736 // try to load profile
2737 if (fConfigP->fProfileBinFile.readRecord(aProfileSelector,&fProfile)!=BFE_OK0)
2738 goto defaultprofile; // use default
2739 // Now we have the profile
2740 fProfileIndex=aProfileSelector;
2741 fRemotepartyID=fProfile.profileID;
2742 // Set session parameters
2743 #ifdef SYNCML_ENCODING_OVERRIDE
2744 fEncoding = SYNCML_ENCODING_OVERRIDE; // we use a globally defined encoding
2745 #else
2746 fEncoding = fProfile.encoding; // we use the profile's encoding
2747 #endif
2748
2749 #ifdef HARD_CODED_SERVER_URI
2750 // - Hard coded base URL of server
2751 fRemoteURI=DEFAULT_SERVER_URI""; // always use fixed URI
2752 #else
2753 // - configured URL
2754 // check config-level fixed URI first
2755 if (!fConfigP->fServerURI.empty()) {
2756 // override server URL from fixed value in config
2757 fRemoteURI = fConfigP->fServerURI; // config
2758 if (strucmp(fProfile.serverURI,fRemoteURI.c_str())!=0) {
2759 PDEBUGPRINTFX(DBG_ERROR,("Warning - <serverurl> config overrides/overwrites server URL in profile")){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("Warning - <serverurl> config overrides/overwrites server URL in profile"
); }
;
2760 // re-adjust profile
2761 AssignCString(fProfile.serverURI, fConfigP->fServerURI.c_str(), maxurisiz); // copy predefined URI back into profile
2762 fProfile.readOnlyFlags |= rdonly_URI; // make it read-only
2763 }
2764 }
2765 else {
2766 // use URL from profile
2767 fRemoteURI=fProfile.serverURI;
2768 }
2769 #endif // not HARD_CODED_SERVER_URI
2770 // check for URI that is a template and need inserts:
2771 size_t n;
2772 // - %%% check future other inserts here, \u should be last because if there's no \u, standard
2773 // CUSTOM_URI_SUFFIX mechanism may apply in else branch
2774 // - \u for URIpath
2775 n = fRemoteURI.find("\\u");
2776 if (n!=string::npos) {
2777 // URIPath may only not contain any special chars that might help to inject different server URLs
2778 string up = fProfile.URIpath;
2779 if (up.find_first_of(":/?.&=%,;")!=string::npos)
2780 fRemoteURI.erase(n, 2); // no insert, invalid chars in URIpath
2781 else
2782 fRemoteURI.replace(n, 2, up); // insert URIPath instead of \u
2783 }
2784 #ifdef CUSTOM_URI_SUFFIX
2785 else {
2786 // Only if original URI is not a template
2787 // - append custom URI suffix stored in serverURI field of profile (if one is set)
2788 if (*(fProfile.URIpath))
2789 {
2790 // - append delimiter first if one defined (CUSTOM_URI_SUFFIX not NULL)
2791 const char *p=CUSTOM_URI_SUFFIX;
2792 if (p) fRemoteURI.append(p);
2793 // - now append custom URI suffix
2794 fRemoteURI.append(fProfile.URIpath);
2795 }
2796 }
2797 #endif // CUSTOM_URI_SUFFIX
2798 #ifdef PROTOCOL_SELECTOR
2799 fRemoteURI.insert(0,Protocol_Names[fProfile.protocol]);
2800 fNoCRCPrefixLen=strlen(Protocol_Names[fProfile.protocol]);
2801 #endif // PROTOCOL_SELECTOR
2802 fServerUser=fProfile.serverUser;
2803 getUnmangled(fServerPassword,fProfile.serverPassword,maxupwsiz);
2804 // - HTTP auth
2805 fTransportUser=fProfile.transportUser;
2806 getUnmangled(fTransportPassword,fProfile.transportPassword,maxupwsiz);
2807 // - proxy
2808 fSocksHost.erase(); // default to none
2809 fProxyHost.erase();
2810 fProxyUser.erase();
2811 fProxyPassword.erase();
2812 #ifdef PROXY_SUPPORT1
2813 if (fProfile.useProxy)
2814 {
2815 fSocksHost=fProfile.socksHost;
2816 fProxyHost=fProfile.proxyHost;
2817 fProxyUser=fProfile.proxyUser;
2818 getUnmangled(fProxyPassword,fProfile.proxyPassword,maxupwsiz);;
2819 PDEBUGPRINTFX(DBG_TRANSP,("Sync Profile contains active proxy settings: http=%s, socks=%s, proxyuser=%s",fProxyHost.c_str(), fSocksHost.c_str(), fProxyUser.c_str())){ if (((0x00002000) & getDbgMask()) == (0x00002000)) getDbgLogger
()->setNextMask(0x00002000).DebugPrintfLastMask ("Sync Profile contains active proxy settings: http=%s, socks=%s, proxyuser=%s"
,fProxyHost.c_str(), fSocksHost.c_str(), fProxyUser.c_str());
}
;
2820 }
2821 #endif // PROXY_SUPPORT
2822 // check for forced legacy mode
2823 fLegacyMode = fProfile.profileFlags & PROFILEFLAG_LEGACYMODE;
2824 // check for lenient mode
2825 fLenientMode = fProfile.profileFlags & PROFILEFLAG_LENIENTMODE;
2826 // - get and increment session ID and save for next session
2827 // Note: as auth retries will increment the ID as well, we inc by 5
2828 // to avoid repeating the ID too soon
2829 fProfile.sessionID+=5;
2830 fProfileDirty=true;
2831 fClientSessionNo=fProfile.sessionID;
2832 // Note: loadRemoteParams will fetch the cached params from fProfile
2833 // Reset session after profile change (especially fRemoteURI)
2834 // and also remove any datastores we might have
2835 ResetAndRemoveDatastores();
2836 // in case of tunnel, don't touch datastores
2837 if (tunnel) return LOCERR_OK;
2838 // Now iterate trough associated target records and create datastores
2839 maxidx=fConfigP->fTargetsBinFile.getNumRecords();
2840 TBinfileDBSyncTarget target;
2841 for (recidx=0; recidx<maxidx; recidx++) {
2842 // - get record
2843 if (fConfigP->fTargetsBinFile.readRecord(recidx,&target)==BFE_OK0) {
2844 // check if this one of my targets
2845 if (target.remotepartyID == fRemotepartyID)
2846 {
2847 // get datastore config
2848 #ifdef HARDCODED_CONFIG
2849 // - traditional method by name for old monolythic builds (to make sure we don't break anything)
2850 TBinfileDSConfig *binfiledscfgP = static_cast<TBinfileDSConfig *>(
2851 getSessionConfig()->getLocalDS(target.dbname)
2852 );
2853 #else
2854 // - newer, engine based targets should use the DBtypeID instead, to allow change of DB name without loosing config
2855 TBinfileDSConfig *binfiledscfgP = static_cast<TBinfileDSConfig *>(
2856 getSessionConfig()->getLocalDS(NULL__null,target.localDBTypeID)
2857 );
2858 #endif
2859 // check if we have config and if this DS is available now (profile.dsAvailFlags, DSFLAGS_ALWAYS_AVAILABLE, evtl. license...)
2860 if (binfiledscfgP && binfiledscfgP->isAvailable(&fProfile)) {
2861 // check if this DB must be synced
2862 bool syncit=false;
2863 #ifdef AUTOSYNC_SUPPORT
2864 if (aAutoSyncSession) {
2865 // target enable status is not relevant, but autosync alert is
2866 syncit =
2867 binfiledscfgP->fAutosyncForced ||
2868 (binfiledscfgP->fAutosyncAlerted && target.enabled);
2869 }
2870 else {
2871 // normal session
2872 syncit = target.enabled && target.remoteDBpath[0]!=0; // and remote DB path specified
2873 binfiledscfgP->fAutosyncAlerted=false; // this is NOT an autosync session
2874 binfiledscfgP->fAutosyncForced=false;
2875 }
2876 #else
2877 syncit = target.enabled && target.remoteDBpath[0]!=0; // and remote DB path specified
2878 #endif
2879 if (syncit)
2880 {
2881 TBinfileImplDS *binfiledsP=NULL__null;
2882 if (binfiledscfgP) {
2883 // create datastore
2884 binfiledsP = static_cast<TBinfileImplDS *>(binfiledscfgP->newLocalDataStore(this));
2885 }
2886 if (binfiledsP) {
2887 // copy target info to datastore for later access during sync
2888 binfiledsP->fTargetIndex=recidx;
2889 binfiledsP->fTarget=target;
2890 // determine sync mode / flags to use
2891 TSyncModes myMode;
2892 bool mySlow;
2893 #ifdef AUTOSYNC_SUPPORT
2894 if (aAutoSyncSession && binfiledscfgP->fAutosyncAlertCode!=0) {
2895 // syncmode provided from auto sync alert (e.g. SAN)
2896 bool myIsSA;
2897 TLocalEngineDS::getSyncModeFromAlertCode(
2898 binfiledscfgP->fAutosyncAlertCode,
2899 myMode,
2900 mySlow,
2901 myIsSA
2902 );
2903 }
2904 else
2905 #endif
2906 {
2907 // take it from config
2908 myMode = target.syncmode;
2909 mySlow = target.forceSlowSync;
2910 }
2911 // clean change logs if...
2912 // ...we have separate changelog or this is the only profile
2913 // ...this is NOT a resumable session (resumable not necessarily means that it WILL be resumed)
2914 // ...we're about to slow sync
2915 if (mySlow && target.resumeAlertCode==0 && (fConfigP->fSeparateChangelogs || fConfigP->fProfileBinFile.getNumRecords()==1)) {
2916 fConfigP->cleanChangeLogForDBname(target.dbname,fProfile.profileID);
2917 }
2918 // set non-BinFile specific parameters (note that this call might
2919 // be to a derivate which uses additional info from fTarget to set sync params)
2920 binfiledsP->dsSetClientSyncParams(
2921 myMode,
2922 mySlow,
2923 target.remoteDBpath,
2924 NULL__null, // DB user
2925 NULL__null, // DB password
2926 NULL__null, // local path extension
2927 // %%% add filters here later!!!
2928 NULL__null, // filter query
2929 false // filter inclusive
2930 );
2931 // prepare local datastore (basic init can be done here) and check availability
2932 if (binfiledsP->localDatastorePrep()) {
2933 // add to datastores for this sync
2934 fLocalDataStores.push_back(binfiledsP);
2935 }
2936 else {
2937 // silently discard (do not sync it)
2938 PDEBUGPRINTFX(DBG_ERROR,("Local Database for datastore '%s' prepares not ok -> not synced",binfiledsP->getName())){ if (((0x00000002) & getDbgMask()) == (0x00000002)) getDbgLogger
()->setNextMask(0x00000002).DebugPrintfLastMask ("Local Database for datastore '%s' prepares not ok -> not synced"
,binfiledsP->getName()); }
;
2939 // show event (alerted for no database)
2940 SESSION_PROGRESS_EVENT(this->NotifySessionProgressEvent(pev_error,binfiledscfgP,LOCERR_LOCDBNOTRDY
,0,0)
2941 this,this->NotifySessionProgressEvent(pev_error,binfiledscfgP,LOCERR_LOCDBNOTRDY
,0,0)
2942 pev_error,this->NotifySessionProgressEvent(pev_error,binfiledscfgP,LOCERR_LOCDBNOTRDY
,0,0)
2943 binfiledscfgP,this->NotifySessionProgressEvent(pev_error,binfiledscfgP,LOCERR_LOCDBNOTRDY
,0,0)
2944 LOCERR_LOCDBNOTRDY,0,0this->NotifySessionProgressEvent(pev_error,binfiledscfgP,LOCERR_LOCDBNOTRDY
,0,0)
2945 )this->NotifySessionProgressEvent(pev_error,binfiledscfgP,LOCERR_LOCDBNOTRDY
,0,0)
;
2946 delete binfiledsP;
2947 }
2948 }
2949 } // if target DB enabled for sync
2950 } // if we have a datastore config for this target
2951 } // if target belongs to this profile
2952 } // if we can read the target record
2953 } // for all target records
2954 // ok if at least one datastore enabled;
2955 #ifdef ENGINE_LIBRARY1
2956 // For engine library, check for a non-empty URL makes no
2957 // sense any more, because the app on top of libsynthesis may know how
2958 // to contact the server without an URL (for example, via some transport
2959 // which doesn't need a parameter)
2960 return fLocalDataStores.size()>0 ? LOCERR_OK : LOCERR_NOCFG;
2961 #else
2962 // for classic synthesis builds (winmobile, palmos) the app relies on
2963 // the check for a non-empty URL, so we keep it for these legacy build cases
2964 return fLocalDataStores.size()>0 && fRemoteURI.size()>0 ? LOCERR_OK : LOCERR_NOCFG;
2965 #endif
2966 } // active
2967defaultprofile:
2968 return inherited::SelectProfile(aProfileSelector, aAutoSyncSession);
2969} // TBinfileImplClient::SelectProfile
2970
2971/* end of TBinfileImplClient implementation */
2972
2973} // namespace sysync
2974
2975
2976
2977
2978// eof