Bug Summary

File:libsynthesis/src/sysync/engineinterface.cpp
Warning:line 886, column 8
Access to field 'writable' results in a dereference of a null pointer (loaded from variable 'fldinfoP')

Annotated Source Code

1/**
2 * @File engineinterface.cpp
3 *
4 * @Author Lukas Zeller (luz@plan44.ch)
5 *
6 * @brief TEngineInterface - common interface to SySync engine for SDK
7 *
8 * Copyright (c) 2007-2011 by Synthesis AG + plan44.ch
9 *
10 */
11
12
13#include "prefix_file.h"
14
15#ifdef ENGINEINTERFACE_SUPPORT1
16
17#include "engineinterface.h"
18#include "syserial.h"
19#include "syncappbase.h"
20#include "SDK_util.h"
21
22namespace sysync {
23
24
25// TSettingsKeyImpl
26// ================
27
28
29TSettingsKeyImpl::TSettingsKeyImpl(
30 TEngineInterface *aEngineInterfaceP
31) :
32 fEngineInterfaceP(aEngineInterfaceP),
33 fImplicitParentKeyP(NULL__null)
34{
35 // init defaults from engine interface
36 fCharSet = fEngineInterfaceP->fCharSet;
37 fBigEndian = fEngineInterfaceP->fBigEndian;
38 fLineEndMode = fEngineInterfaceP->fLineEndMode;
39 // init hardcoded defaults
40 fTimeMode = TMODE_LINEARTIME+TMODE_FLAG_FLOATING; // linear time (as floating, which means UTC for engine timestamps)
41} // TSettingsKeyImpl::TSettingsKeyImpl
42
43
44TSettingsKeyImpl::~TSettingsKeyImpl()
45{
46 // deleting object means closing key
47 // - At this point (in baseclass), actual key implementation is closed
48 // already, so we can delete implicitly opened ancestors now recursively
49 if (fImplicitParentKeyP) {
50 delete fImplicitParentKeyP;
51 fImplicitParentKeyP=NULL__null;
52 }
53} // TSettingsKeyImpl::TSettingsKeyImpl
54
55
56// open subkey(chain) by path
57// - walks down through needed subkeys
58TSyError TSettingsKeyImpl::OpenKeyByPath(
59 TSettingsKeyImpl *&aSettingsKeyP, // might be set even if overall open fails - caller must delete object passed back in case of failure
60 cAppCharP aPath, uInt16 aMode,
61 bool aImplicit // if set, this means that THIS key was implicitly opened, and should be implicitly closed as well
62)
63{
64 TSyError sta;
65 TSettingsKeyImpl *subKeyP=NULL__null;
66
67 // as long as we haven't openend anything, make sure pointer returned is NULL
68 aSettingsKeyP=NULL__null;
69 // open by relative path, starting at myself
70 if (aPath==NULL__null) return LOCERR_WRONGUSAGE;
71 // strip leading separators
72 while (*aPath==SETTINGSKEY_PATH_SEPARATOR'/') aPath++;
73 // search end of string or next separator
74 cAppCharP e = aPath;
75 while (*e && *e!=SETTINGSKEY_PATH_SEPARATOR'/') e++;
76 // open the element we have found
77 sta = OpenSubKeyByName(aSettingsKeyP,aPath,e-aPath,aMode);
78 if (sta == LOCERR_OK) {
79 // immediate subkey opened successfully
80 // - if this is an implicit open, link back to myself as I must be deleted when subkey is deleted
81 if (aImplicit) {
82 aSettingsKeyP->fImplicitParentKeyP = this;
83 }
84 // new opened key inherits base key's value formatting settings
85 aSettingsKeyP->SetTextMode(fCharSet, fLineEndMode,fBigEndian);
86 aSettingsKeyP->SetTimeMode(fTimeMode);
87 // - check if chain continues
88 while (*e==SETTINGSKEY_PATH_SEPARATOR'/') e++; // strip leading separators
89 if (*e) {
90 // another path element follows, open it recursively
91 // - this is implicit in any case!
92 sta = aSettingsKeyP->OpenKeyByPath(subKeyP,e,aMode,true);
93 if (subKeyP != NULL__null) {
94 // more subkeys were opened, possibly not entire chain as requested. But in
95 // any case, we need to pass back the rightmost opened key in the path as this
96 // must be deleted by the caller (causing all implicitly related objects to delete as well)
97 aSettingsKeyP = subKeyP;
98 }
99 }
100 }
101 // return status
102 return sta;
103} // TSettingsKeyImpl::OpenKeyByPath
104
105
106const uInt16 engineCharSets[numCharSets] = {
107 CHS_UNKNOWN,
108 CHS_ASCII,
109 CHS_ANSI,
110 CHS_ISO_8859_1,
111 CHS_UTF8,
112 CHS_UTF16,
113 #ifdef CHINESE_SUPPORT
114 CHS_GB2312,
115 CHS_CP936
116 #endif
117};
118
119const uInt16 engineLineEndModes[numLineEndModes] = {
120 LEM_NONE,
121 LEM_UNIX,
122 LEM_MAC,
123 LEM_DOS,
124 LEM_CSTR,
125 LEM_FILEMAKER
126};
127
128
129// Set text format parameters
130TSyError TSettingsKeyImpl::SetTextMode(uInt16 aCharSet, uInt16 aLineEndMode, bool aBigEndian)
131{
132 // translate charset
133 uInt16 chs;
134 for (chs=0; chs<numCharSets; chs++) {
135 if (engineCharSets[chs]==aCharSet) break;
136 }
137 if (chs==numCharSets) return LOCERR_BADPARAM;
138 // translate lineendmode
139 uInt16 lem;
140 for (lem=0; lem<numLineEndModes; lem++) {
141 if (engineLineEndModes[lem]==aLineEndMode) break;
142 }
143 if (lem==numLineEndModes) return LOCERR_BADPARAM;
144 // assign them now they are checked ok
145 fCharSet = (TCharSets)chs;
146 fLineEndMode = (TLineEndModes)lem;
147 // big endian flag
148 fBigEndian = aBigEndian;
149 return LOCERR_OK;
150} // TSettingsKeyImpl::SetTextMode
151
152
153
154// Reads a named value in specified format into passed memory buffer
155TSyError TSettingsKeyImpl::GetValueByID(
156 sInt32 aID, sInt32 aArrayIndex, uInt16 aValType,
157 appPointer aBuffer, memSize aBufSize, memSize &aValSize
158)
159{
160 TSyError sta;
161 string valStr;
162 cAppCharP txt;
163 string convStr;
164 sInt64 tempInt=0;
165 lineartime_t tempTime;
166 timecontext_t tctx;
167
168 // get native type of value (and check validity of ID - invalid IDs must return VALTYPE_UNKNOWN)
169 uInt16 valType = GetValueType(aID);
170 if (valType==VALTYPE_UNKNOWN) return DB_NotFound;
171 // direct return in case requested type matches native type or raw data (VALTYPE_BUF) is requested
172 if (
173 (aValType == VALTYPE_BUF) || // we want raw buffer data
174 ((valType == aValType) &&
175 (valType != VALTYPE_TEXT || (fCharSet==chs_utf8 && fLineEndMode==lem_cstr)) &&
176 (valType != VALTYPE_TIME64 || ((fTimeMode & TMODE_MODEMASK)==TMODE_LINEARTIME)) )
177 ) {
178 // requested type&format matches native or we are requesting a buffer -> we can return native value directly
179 if (aValType == VALTYPE_TEXT) {
180 if (!aBuffer || aBufSize==0) {
181 // only measure size
182 return GetValueInternal(aID,aArrayIndex,NULL__null,0,aValSize);
183 }
184 else {
185 // low level text routines do not set terminators for simplicity, so make sure we have one here
186 // - request only max one char less than buf can hold, so we always have room for a terminator
187 sta = GetValueInternal(aID,aArrayIndex,aBuffer,aBufSize-1,aValSize);
188 // - make sure we have a NUL terminator at the very end of the buffer in all cases
189 ((appCharP)aBuffer)[aBufSize-1] = 0; // ultimate terminator
190 // - also make sure we have a terminator at the end of the actual string
191 if (sta==LOCERR_OK && aValSize<aBufSize)
192 ((appCharP)aBuffer)[aValSize] = 0;
193 // signal LOCERR_TRUNCATED if ok, but buffer is not large enough
194 if (sta==LOCERR_OK && aValSize>aBufSize-1) {
195 sta = LOCERR_TRUNCATED;
196 aValSize = aBufSize-1; // return actual size, not untruncated one
197 }
198 return sta;
199 }
200 }
201 else {
202 // non-text, simply return value
203 sta = GetValueInternal(aID,aArrayIndex,aBuffer,aBufSize,aValSize);
204 if (sta==LOCERR_OK && aBufSize && aBuffer && aValSize>aBufSize) {
205 // not only measuring size, check for truncation
206 if (aValType==VALTYPE_BUF) {
207 // in case of buffer, we call this "truncated" (we don't know if the result is usable or not, depends on data itself)
208 sta = LOCERR_TRUNCATED;
209 aValSize = aBufSize; // return actual size, not untruncated one
210 }
211 else {
212 // in other cases, too small buffer makes result unusable, so we don't call it "truncated"
213 // AND: we return the needed buffer size
214 sta = LOCERR_BUFTOOSMALL;
215 }
216 }
217 return sta;
218 }
219 }
220 // some kind of conversion needed
221 // - get native size of value first
222 memSize valSiz;
223 sta = GetValueInternal(aID,aArrayIndex,NULL__null,0,valSiz);
224 if (sta!=LOCERR_OK) return sta;
225 // - allocate matching buffer
226 memSize bufSiz = valSiz+1; // extra room for terminator
227 uInt8P bufP = (uInt8P) malloc(bufSiz);
228 bufP[valSiz]=0; // make sure we have a terminator
229 if (bufP==NULL__null) return LOCERR_OUTOFMEM;
230 // - get value in native type
231 sta = GetValueInternal(aID,aArrayIndex,bufP,bufSiz,valSiz);
232 if (sta==LOCERR_OK) {
233 // value conversion matrix
234 // - switch by native value type
235 switch (valType) {
236 // Timestamp native type (always VALTYPE_TIME64)
237 case VALTYPE_TIME64:
238 tempTime = *((lineartime_t *)bufP);
239 tctx = (fTimeMode & TMODE_FLAG_UTC)==0 ? TCTX_SYSTEM((timecontext_t) ((tctx_tz_system) | TCTX_SYMBOLIC_TZ)) : TCTX_UTC((timecontext_t) ((tctx_tz_UTC) | TCTX_SYMBOLIC_TZ));
240 // convert it from internal format (UTC), unless we request floating
241 if ((fTimeMode & TMODE_FLAG_FLOATING)==0)
242 TzConvertTimestamp(tempTime,TCTX_UTC((timecontext_t) ((tctx_tz_UTC) | TCTX_SYMBOLIC_TZ)),tctx,getEngineInterface()->getSyncAppBase()->getAppZones());
243 else
244 tctx = TCTX_UNKNOWN((timecontext_t) ((tctx_tz_unknown) | TCTX_SYMBOLIC_TZ)); // make sure that ISO8601 representation has no TZ info in floating mode
245 // now return
246 if (aValType==VALTYPE_TEXT) {
247 // return time as text
248 TimestampToISO8601Str(valStr, tempTime, tctx, false, false);
249 txt = valStr.c_str();
250 goto textConv;
251 }
252 // no time will return an error code
253 if (tempTime==noLinearTime) {
254 // no time
255 sta=DB_NoContent; // indicates NO value
256 break;
257 }
258 // return time as integer number
259 switch (fTimeMode & TMODE_MODEMASK) {
260 case TMODE_LINEARDATE:
261 tempInt = tempTime / linearDateToTimeFactor;
262 goto intConv;
263 case TMODE_UNIXTIME_MS:
264 tempInt = tempTime-UnixToLineartimeOffset; // lineartime_t (that is, milliseconds), but with unix epoch origin
265 goto intConv;
266 case TMODE_UNIXTIME:
267 tempInt = (tempTime-UnixToLineartimeOffset)/secondToLinearTimeFactor;
268 goto intConv;
269 default :
270 tempInt = tempTime;
271 goto intConv;
272 }
273 break;
274 // Integer native types
275 case VALTYPE_INT8:
276 tempInt = *((sInt8 *)bufP);
277 goto intConv;
278 case VALTYPE_INT16:
279 tempInt = *((sInt16 *)bufP);
280 goto intConv;
281 case VALTYPE_INT32:
282 tempInt = *((sInt32 *)bufP);
283 goto intConv;
284 case VALTYPE_INT64:
285 tempInt = *((sInt64 *)bufP);
286 intConv:
287 // convert integer into desired target type
288 switch (aValType) {
289 case VALTYPE_INT8:
290 case VALTYPE_ENUM:
291 aValSize=1;
292 if (aBufSize<aValSize) sta=LOCERR_BUFTOOSMALL;
293 else *((sInt8 *)aBuffer) = tempInt;
294 break;
295 case VALTYPE_INT16:
296 aValSize=2;
297 if (aBufSize<aValSize) sta=LOCERR_BUFTOOSMALL;
298 else *((sInt16 *)aBuffer) = tempInt;
299 break;
300 case VALTYPE_INT32:
301 case VALTYPE_TIME32:
302 aValSize=4;
303 if (aBufSize<aValSize) sta=LOCERR_BUFTOOSMALL;
304 else *((sInt32 *)aBuffer) = tempInt;
305 break;
306 case VALTYPE_INT64:
307 case VALTYPE_TIME64:
308 aValSize=8;
309 if (aBufSize<aValSize) sta=LOCERR_BUFTOOSMALL;
310 else *((sInt64 *)aBuffer) = tempInt;
311 break;
312 case VALTYPE_TEXT:
313 StringObjPrintf(valStr,PRINTF_LLD"%lld",PRINTF_LLD_ARG(tempInt)static_cast<long long>(tempInt));
314 txt = valStr.c_str();
315 goto textConv;
316 break;
317 }
318 break;
319 // Text native type
320 case VALTYPE_TEXT:
321 txt = (cAppCharP)bufP;
322 textConv:
323 // text can only be returned as text (implicit Int/time scanning makes no sense)
324 if (aValType!=VALTYPE_TEXT)
325 sta = LOCERR_WRONGUSAGE; // conversion not allowed
326 else {
327 // converted to requested charset/lineend
328 if (fCharSet==chs_utf16) {
329 if (!appendUTF8ToUTF16ByteString(
330 txt,
331 convStr,
332 fBigEndian,
333 fLineEndMode,
334 aBufSize>0 ? aBufSize-2 : 0 // max output size (but no limit if measuring actual size)
335 ))
336 sta = LOCERR_TRUNCATED;
337 // return (possibly truncated) size
338 aValSize=convStr.size();
339 // this will be added as part of the content, and gives a 16bit NUL terminator
340 convStr+=(char)0;
341 }
342 else {
343 // 8-bit character encoding
344 if (!appendUTF8ToString(
345 txt,
346 convStr,
347 fCharSet,
348 fLineEndMode,
349 qm_none,
350 aBufSize>0 ? aBufSize-1 : 0 // max output size (but no limit if measuring actual size)
351 ))
352 sta = LOCERR_TRUNCATED;
353 // return (possibly truncated) size
354 aValSize=convStr.size();
355 }
356 // if requested, return value into buffer
357 if (aBufSize>0) {
358 // copy including implicit NUL terminator BYTE (in case of UTF16, there is an extra explicit NUL char in the convStr itself to make a 16-bit NUL!)
359 memcpy(aBuffer,(appPointer)convStr.c_str(),convStr.size()+1>aBufSize ? aBufSize : convStr.size()+1);
360 }
361 else {
362 // measuring size always returns OK
363 sta = LOCERR_OK;
364 }
365 }
366 break;
367 } // switch by native type
368 } // if value returned
369
370 // - return temp buffer
371 free(bufP);
372 // - return status
373 return sta;
374} // TSettingsKeyImpl::GetValueByID
375
376
377// Writes a named value in specified format passed in memory buffer
378TSyError TSettingsKeyImpl::SetValueByID(
379 sInt32 aID, sInt32 aArrayIndex, uInt16 aValType,
380 cAppPointer aBuffer, memSize aValSize
381)
382{
383 TSyError sta = LOCERR_OK;
384 sInt64 tempInt;
385 lineartime_t tempTime;
386 timecontext_t tctx;
387 appPointer bP;
388 memSize siz;
389 string convStr;
390
391 // get native type of value (and check validity of ID - invalid IDs must return VALTYPE_UNKNOWN)
392 uInt16 valType = GetValueType(aID);
393 if (valType==VALTYPE_UNKNOWN) return DB_NotFound;
394 // measure value for strings
395 if (aValType == VALTYPE_TEXT && aValSize == memSize(-1)) {
396 if (fCharSet==chs_utf16)
397 return LOCERR_NOTIMP; // measuring UTF-16 not supported yet
398 //aValSize = wcslen((short *)aBuffer)/2;
399 else
400 aValSize = strlen((char *)aBuffer);
401 }
402 // we can set directly if input type matches native type
403 if (
404 (aValType == VALTYPE_BUF) ||
405 ((valType == aValType) &&
406 (valType != VALTYPE_TEXT || (fCharSet==chs_utf8 && fLineEndMode==lem_cstr)) &&
407 (valType != VALTYPE_TIME64 || ((fTimeMode & TMODE_MODEMASK)==TMODE_LINEARTIME)) )
408 ) {
409 // presented type&format matches native or we are setting bytes 1:1 anyway -> we can set native value directly
410 return SetValueInternal(aID,aArrayIndex,aBuffer,aValSize);
411 }
412 // some kind of conversion needed
413 // - switch by presented value type
414 switch (aValType) {
415 // Set "no value"
416 case VALTYPE_NULL:
417 sta = SetValueInternal(aID,aArrayIndex,NULL__null,0);
418 break;
419
420 // Text presented
421 case VALTYPE_TEXT:
422 // first convert into internal text format
423 if (fCharSet==chs_utf16) {
424 appendUTF16AsUTF8((uInt16 *)aBuffer,aValSize/2,fBigEndian,convStr, true, true);
425 }
426 else {
427 string s; s.assign((cAppCharP)aBuffer,aValSize);
428 appendStringAsUTF8(s.c_str(), convStr, fCharSet, lem_cstr, true);
429 }
430 // possibly convert text to native
431 switch (valType) {
432 case VALTYPE_TIME64:
433 // convert text to internal time format
434 ISO8601StrToTimestamp(convStr.c_str(), tempTime, tctx);
435 // if not floating, assume target timestamp is UTC, so ISO string w/o time zone is treated as system time for convenience
436 if ((fTimeMode & TMODE_FLAG_FLOATING)==0)
437 TzConvertTimestamp(tempTime, tctx, TCTX_UTC((timecontext_t) ((tctx_tz_UTC) | TCTX_SYMBOLIC_TZ)), getEngineInterface()->getSyncAppBase()->getAppZones(), TCTX_SYSTEM((timecontext_t) ((tctx_tz_system) | TCTX_SYMBOLIC_TZ)));
438 siz=8; bP = &tempTime;
439 break;
440 case VALTYPE_INT8:
441 case VALTYPE_INT16:
442 case VALTYPE_INT32:
443 case VALTYPE_INT64:
444 // convert text to integer
445 StrToLongLong(convStr.c_str(),tempInt);
446 goto intConv;
447 case VALTYPE_TEXT:
448 siz=convStr.size();
449 bP=(appPointer)convStr.c_str();
450 break;
451 default:
452 // cannot return as text
453 return LOCERR_WRONGUSAGE;
454 }
455 // set it
456 sta = SetValueInternal(aID,aArrayIndex,bP,siz);
457 break;
458
459 // Timestamp presented
460 case VALTYPE_TIME32:
461 if (aValSize<4) return LOCERR_BUFTOOSMALL;
462 tempTime = *((sInt32 *)aBuffer);
463 goto timeConv;
464 case VALTYPE_TIME64:
465 if (aValSize<8) return LOCERR_BUFTOOSMALL;
466 tempTime = *((sInt64 *)aBuffer);
467 timeConv:
468 switch (fTimeMode & TMODE_MODEMASK) {
469 case TMODE_LINEARDATE:
470 tempInt = tempTime * linearDateToTimeFactor;
471 break;
472 case TMODE_UNIXTIME_MS:
473 tempInt = tempTime+UnixToLineartimeOffset;
474 break;
475 case TMODE_UNIXTIME:
476 tempInt = secondToLinearTimeFactor*tempTime+UnixToLineartimeOffset;
477 break;
478 case TMODE_LINEARTIME:
479 default :
480 tempInt = tempTime;
481 break;
482 }
483 tctx = (fTimeMode & TMODE_FLAG_UTC)==0 ? TCTX_SYSTEM((timecontext_t) ((tctx_tz_system) | TCTX_SYMBOLIC_TZ)) : TCTX_UTC((timecontext_t) ((tctx_tz_UTC) | TCTX_SYMBOLIC_TZ));
484 // convert to UTC if needed
485 if ((fTimeMode & TMODE_FLAG_FLOATING)==0)
486 TzConvertTimestamp(tempInt,tctx,TCTX_UTC((timecontext_t) ((tctx_tz_UTC) | TCTX_SYMBOLIC_TZ)),getEngineInterface()->getSyncAppBase()->getAppZones());
487 goto intConv;
488
489 // Integer presented types
490 case VALTYPE_INT8:
491 case VALTYPE_ENUM:
492 if (aValSize<1) return LOCERR_BUFTOOSMALL;
493 tempInt = *((sInt8 *)aBuffer);
494 goto intConv;
495 case VALTYPE_INT16:
496 if (aValSize<2) return LOCERR_BUFTOOSMALL;
497 tempInt = *((sInt16 *)aBuffer);
498 goto intConv;
499 case VALTYPE_INT32:
500 if (aValSize<4) return LOCERR_BUFTOOSMALL;
501 tempInt = *((sInt32 *)aBuffer);
502 goto intConv;
503 case VALTYPE_INT64:
504 if (aValSize<8) return LOCERR_BUFTOOSMALL;
505 tempInt = *((sInt64 *)aBuffer);
506 intConv:
507 // convert integer into native type
508 union {
509 sInt64 buffer64;
510 sInt32 buffer32;
511 sInt16 buffer16;
512 sInt8 buffer8;
513 } buffer;
514 bP = &buffer;
515 switch (valType) {
516 case VALTYPE_INT8:
517 siz=1; buffer.buffer8 = tempInt;
518 break;
519 case VALTYPE_INT16:
520 siz=2; buffer.buffer16 = tempInt;
521 break;
522 case VALTYPE_INT32:
523 siz=4; buffer.buffer32 = tempInt;
524 break;
525 case VALTYPE_INT64:
526 case VALTYPE_TIME64: // native timestamp
527 siz=8; buffer.buffer64 = tempInt;
528 break;
529 default:
530 // other types (like text) cannot set as integer
531 return LOCERR_WRONGUSAGE; // conversion not allowed
532 break;
533 }
534 // now write int/time value
535 sta = SetValueInternal(aID,aArrayIndex,bP,siz);
536 break;
537
538 } // switch by presented type
539
540 return sta;
541} // TSettingsKeyImpl::SetValueByID
542
543
544
545#define VALID_IDXOFFS_VALTYPE0x100000 0x100000
546#define VALID_MASK_IDX0x00FFFF 0x00FFFF
547
548
549// helper for detecting generic field attribute access
550bool TSettingsKeyImpl::checkFieldAttrs(cAppCharP aName, size_t &aBaseNameSize, sInt32 &aFldID)
551{
552 aBaseNameSize = strlen(aName);
553 aFldID = 0; // basic
554 if (aBaseNameSize >= strlen(VALSUFF_TYPE".VALTYPE") &&
555 strucmp(aName+aBaseNameSize-strlen(VALSUFF_TYPE".VALTYPE"),VALSUFF_TYPE".VALTYPE")==0) {
556 // value type
557 aBaseNameSize-=strlen(VALSUFF_TYPE".VALTYPE");
558 aFldID += VALID_IDXOFFS_VALTYPE0x100000;
559 }
560 if (strucmp(aName,VALNAME_FLAG".FLAG",aBaseNameSize)==0)
561 return true; // asking for flag mask only
562 return false; // aFldID is only the flag mask, caller must add base index
563} // TSettingsKeyImpl::checkFieldAttrs
564
565
566
567// helper for returning generic field attribute type
568bool TSettingsKeyImpl::checkAttrValueType(sInt32 aID, uInt16 &aValType)
569{
570 if (aID>0 && (aID & VALID_IDXOFFS_VALTYPE0x100000)) {
571 aValType = VALTYPE_INT16; // valtype is always uInt16
572 return true;
573 }
574 return false;
575} // TSettingsKeyImpl::checkAttrValueType
576
577
578
579// helper for returning generic field attribute values
580bool TSettingsKeyImpl::checkAttrValue(
581 sInt32 aID, sInt32 aArrayIndex,
582 appPointer aBuffer, memSize aBufSize, memSize &aValSize
583)
584{
585 if (aID>0 && (aID & VALID_IDXOFFS_VALTYPE0x100000)) {
586 // return type, not value
587 aValSize = 2;
588 uInt16 valtype = GetValueType(aID & VALID_MASK_IDX0x00FFFF);
589 if (aBufSize>=aValSize) {
590 memcpy(aBuffer,&valtype,aValSize);
591 }
592 return true;
593 }
594 return false;
595} // TSettingsKeyImpl::checkAttrValue
596
597
598
599
600
601
602// TReadOnlyInfoKey
603// ================
604
605
606// get value's ID (e.g. internal index)
607sInt32 TReadOnlyInfoKey::GetValueID(cAppCharP aName)
608{
609 const TReadOnlyInfo *tblP = getInfoTable();
610
611 sInt32 idx=0;
612 size_t namsz;
613 sInt32 fldID;
614 if (checkFieldAttrs(aName,namsz,fldID))
615 return fldID;
616 while(tblP && idx<numInfos()) {
617 if (strucmp(aName,tblP[idx].valName,namsz)==0) {
618 return fldID+idx; // found
619 }
620 // next
621 idx++;
622 }
623 // now check for iterator commands
624 if (strucmp(aName,VALNAME_FIRST".FIRST")==0) {
625 fIterator=0;
626 if (fIterator<numInfos()) return fIterator;
627 }
628 else if (strucmp(aName,VALNAME_NEXT".NEXT")==0) {
629 if (fIterator<numInfos()) fIterator++;
630 if (fIterator<numInfos()) return fIterator;
631 }
632 // not found
633 return KEYVAL_ID_UNKNOWN; // unknown
634} // TReadOnlyInfoKey::GetValueID
635
636
637// get value's native type
638uInt16 TReadOnlyInfoKey::GetValueType(sInt32 aID)
639{
640 uInt16 valType;
641 if (checkAttrValueType(aID,valType))
642 return valType;
643 if (aID>=numInfos()) return VALTYPE_UNKNOWN;
644 return getInfoTable()[aID].valType;
645} // TReadOnlyInfoKey::GetValueType
646
647
648// get value
649TSyError TReadOnlyInfoKey::GetValueInternal(
650 sInt32 aID, sInt32 aArrayIndex,
651 appPointer aBuffer, memSize aBufSize, memSize &aValSize
652)
653{
654 if (checkAttrValue(aID,aArrayIndex,aBuffer,aBufSize,aValSize))
655 return LOCERR_OK;
656 const TReadOnlyInfo *infoP = &(getInfoTable()[aID]);
657 memSize siz = infoP->valSiz;
658 if (siz==0 && infoP->valType==VALTYPE_TEXT)
659 siz = strlen((cAppCharP)(infoP->valPtr));
660 // return actual size
661 aValSize = siz;
662 // return requested amount of data or all we have, whatever is smaller
663 if (siz>aBufSize)
664 siz=aBufSize; // limit to buffer size (aBufSiz is compensated for NUL terminator already, so we can use memcpy for strings as well)
665 memcpy(aBuffer,infoP->valPtr,siz);
666 return LOCERR_OK;
667} // TReadOnlyInfoKey::GetValueInternal
668
669
670
671// TConfigVarKey
672// =============
673
674
675// get value's ID (config vars do NOT have a real ID!)
676sInt32 TConfigVarKey::GetValueID(cAppCharP aName)
677{
678 size_t namsz;
679 sInt32 fldID;
680 checkFieldAttrs(aName,namsz,fldID);
681 if (fldID!=0)
682 return fldID; // is an attribute
683 // value itself cannot be accessed by ID - so cache name for next call to getValueInternal
684 fVarName = aName; // cache name
685 return KEYVAL_NO_ID;
686};
687
688
689// get value's native type (all config vars are text)
690uInt16 TConfigVarKey::GetValueType(sInt32 aID)
691{
692 uInt16 valType;
693 if (checkAttrValueType(aID,valType))
694 return valType;
695 // value itself is always text
696 return VALTYPE_TEXT;
697} // TConfigVarKey::GetValueType
698
699
700// get value
701TSyError TConfigVarKey::GetValueInternal(
702 sInt32 aID, sInt32 aArrayIndex,
703 appPointer aBuffer, memSize aBufSize, memSize &aValSize
704) {
705 if (checkAttrValue(aID,aArrayIndex,aBuffer,aBufSize,aValSize))
706 return LOCERR_OK;
707 string s;
708 if (!fEngineInterfaceP->getSyncAppBase()->getConfigVar(fVarName.c_str(),s))
709 return DB_NotFound;
710 // copy string into buffer
711 aValSize=s.size();
712 strncpy((appCharP)aBuffer,s.c_str(),aBufSize);
713 return LOCERR_OK;
714} // TConfigVarKey::GetValueInternal
715
716
717// set value
718TSyError TConfigVarKey::SetValueInternal(
719 sInt32 aID, sInt32 aArrayIndex,
720 cAppPointer aBuffer, memSize aValSize
721) {
722 if (!aBuffer) {
723 // writing NULL means undefining variable
724 fEngineInterfaceP->getSyncAppBase()->unsetConfigVar(fVarName.c_str());
725 return LOCERR_OK;
726 }
727 string v; v.assign((cAppCharP)aBuffer,(size_t)aValSize); // copy because input could be unterminated string
728 if (!fEngineInterfaceP->getSyncAppBase()->setConfigVar(fVarName.c_str(),v.c_str()))
729 return DB_NotFound;
730 return LOCERR_OK;
731} // TConfigVarKey::SetValueInternal
732
733
734
735
736// TStructFieldsKey
737// ================
738
739
740// static helper for procedural string readers
741TSyError TStructFieldsKey::returnString(cAppCharP aReturnString, appPointer aBuffer, memSize aBufSize, memSize &aValSize)
742{
743 aValSize=strlen(aReturnString);
744 if (aBufSize>=aValSize) {
745 // copy string
746 strncpy((appCharP)aBuffer,aReturnString,aValSize);
747 }
748 return LOCERR_OK;
749} // returnString
750
751
752// static helper for procedural int readers
753TSyError TStructFieldsKey::returnInt(sInt32 aInt, memSize aIntSize, appPointer aBuffer, memSize aBufSize, memSize &aValSize)
754{
755 aValSize=aIntSize;
756 if (aBufSize==0) return LOCERR_OK; // measuring size
757 if (aBufSize<aIntSize) return LOCERR_BUFTOOSMALL;
758 if (aValSize>=4)
759 *((sInt32 *)aBuffer) = (sInt32)aInt;
760 else if (aValSize>=2)
761 *((sInt16 *)aBuffer) = (sInt16)aInt;
762 else
763 *((sInt8 *)aBuffer) = (sInt8)aInt;
764 return LOCERR_OK;
765} // returnInt
766
767
768TSyError TStructFieldsKey::returnLineartime(lineartime_t aTime, appPointer aBuffer, memSize aBufSize, memSize &aValSize)
769{
770 aValSize=sizeof(lineartime_t);
771 if (aBufSize==0) return LOCERR_OK; // measuring size
772 if (aBufSize<aValSize) return LOCERR_BUFTOOSMALL;
773 *((lineartime_t *)aBuffer) = aTime;
774 return LOCERR_OK;
775}
776
777
778
779
780// get value's ID (e.g. internal index)
781sInt32 TStructFieldsKey::GetValueID(cAppCharP aName)
782{
783 const TStructFieldInfo *tblP = getFieldsTable();
784
785 sInt32 idx=0;
786 size_t namsz;
787 sInt32 fldID;
788 if (checkFieldAttrs(aName,namsz,fldID))
789 return fldID;
790 while(tblP && idx<numFields()) {
791 if (strucmp(aName,tblP[idx].valName,namsz)==0) {
792 return fldID+idx; // found
793 }
794 // next
795 idx++;
796 }
797 // now check for iterator commands
798 if (strucmp(aName,VALNAME_FIRST".FIRST")==0) {
799 fIterator=0;
800 if (fIterator<numFields()) return fIterator;
801 }
802 else if (strucmp(aName,VALNAME_NEXT".NEXT")==0) {
803 if (fIterator<numFields()) fIterator++;
804 if (fIterator<numFields()) return fIterator;
805 }
806 // not found
807 return KEYVAL_ID_UNKNOWN; // unknown
808} // TStructFieldsKey::GetValueID
809
810
811// get value's native type
812uInt16 TStructFieldsKey::GetValueType(sInt32 aID)
813{
814 uInt16 valType;
815 if (checkAttrValueType(aID,valType))
816 return valType;
817 if (aID>=numFields()) return VALTYPE_UNKNOWN;
818 const TStructFieldInfo *fldinfoP = &(getFieldsTable()[aID]);
819 valType = fldinfoP->valType;
820 if (valType == VALTYPE_ENUM) {
821 // VALTYPE_ENUM: determine integer type from actual size of variable
822 switch (fldinfoP->valSiz) {
823 default : return VALTYPE_INT8; // smallest causes least harm: use as default
824 case 2 : return VALTYPE_INT16;
825 case 4 : return VALTYPE_INT32;
826 case 8 : return VALTYPE_INT64;
827 }
828 }
829 else if (valType == VALTYPE_TEXT_OBFUS)
830 return VALTYPE_TEXT; // obfuscated fields are text for SDK user
831 else
832 return valType; // just return specified type
833} // TStructFieldsKey::GetValueType
834
835
836// get value
837TSyError TStructFieldsKey::GetValueInternal(
838 sInt32 aID, sInt32 aArrayIndex,
839 appPointer aBuffer, memSize aBufSize, memSize &aValSize
840)
841{
842 if (checkAttrValue(aID,aArrayIndex,aBuffer,aBufSize,aValSize))
843 return LOCERR_OK;
844 const TStructFieldInfo *fldinfoP = &(getFieldsTable()[aID]);
845 // check for programmatic access to value
846 if (fldinfoP->getValueProc) {
847 // get value programmatically
848 return fldinfoP->getValueProc(this,fldinfoP,aBuffer,aBufSize,aValSize);
849 }
850 // fetch value from structure
851 memSize siz = fldinfoP->valSiz; // get (max) size
852 if (siz==0) return DB_Forbidden; // read access not allowed
853 uInt8P valPtr = getStructAddr()+fldinfoP->fieldOffs;
854 // for text fields, measure actual size
855 if (fldinfoP->valType==VALTYPE_TEXT)
856 siz = strlen((cAppCharP)valPtr);
857 // return actual size
858 aValSize = siz;
859 // return requested amount of data or all we have, whatever is smaller
860 if (siz>aBufSize)
861 siz=aBufSize; // limit to buffer size (aBufSiz is compensated for NUL terminator already, so we can use memcpy for strings as well)
862 // for obfuscated fields, use special routine
863 if (fldinfoP->valType==VALTYPE_TEXT_OBFUS && siz>0) {
864 getUnmangledAsBuf((appCharP)aBuffer, siz, (cAppCharP)valPtr);
865 // measure decoded
866 aValSize = strlen((cAppCharP)aBuffer);
867 }
868 else
869 memcpy(aBuffer,valPtr,siz);
870 return LOCERR_OK;
871} // TStructFieldsKey::GetValueInternal
872
873
874// set value
875TSyError TStructFieldsKey::SetValueInternal(
876 sInt32 aID, sInt32 aArrayIndex,
877 cAppPointer aBuffer, memSize aValSize
878)
879{
880 if (!aBuffer) return LOCERR_WRONGUSAGE; // cannot handle NULL values
1
Assuming 'aBuffer' is non-null
2
Taking false branch
881 if (aID & VALID_IDXOFFS_VALTYPE0x100000)
3
Assuming the condition is false
4
Taking false branch
882 return DB_Forbidden; // can't write type
883 TSyError sta = LOCERR_OK;
884 const TStructFieldInfo *fldinfoP = &(getFieldsTable()[aID]);
5
'fldinfoP' initialized to a null pointer value
885 // refuse writing to read-only fields
886 if (!fldinfoP->writable) return DB_Forbidden;
6
Access to field 'writable' results in a dereference of a null pointer (loaded from variable 'fldinfoP')
887 // check for programmatic access to value
888 if (fldinfoP->setValueProc) {
889 // set value programmatically
890 return fldinfoP->setValueProc(this,fldinfoP,aBuffer,aValSize);
891 }
892 // write value to structure
893 memSize siz = fldinfoP->valSiz; // get (max) size (for strings: buffer including NUL)
894 if (siz==0) return DB_Forbidden; // write access not allowed
895 uInt8P valPtr = getStructAddr()+fldinfoP->fieldOffs;
896 // adjust usable size for strings
897 if (fldinfoP->valType == VALTYPE_TEXT)
898 siz--; // reserve one for terminator
899 // check and signal truncation
900 if (aValSize>siz)
901 sta=LOCERR_TRUNCATED;
902 else
903 siz=aValSize;
904 // copy data into struct
905 if (fldinfoP->valType==VALTYPE_TEXT_OBFUS) {
906 string v; v.assign((cAppCharP)aBuffer,aValSize);
907 assignMangledToCString((appCharP)valPtr, v.c_str(), fldinfoP->valSiz, true); // always use entire buffer and fill it with garbage beyond end of actual data
908 }
909 else
910 memcpy(valPtr,aBuffer,siz);
911 // - struct modified, signal that (for derivates that might want to save the record on close)
912 fDirty=true;
913 // append terminator in case of text
914 if (fldinfoP->valType == VALTYPE_TEXT)
915 *(valPtr+siz)=0;
916 // done
917 return sta;
918} // TStructFieldsKey::SetValueInternal
919
920
921
922#ifdef SYSER_REGISTRATION
923
924// Licensing key
925// -------------
926
927// Accessors for license text and code
928
929// - read license text
930static TSyError readLicenseText(
931 TStructFieldsKey *aStructFieldsKeyP, const TStructFieldInfo *aFldInfoP,
932 appPointer aBuffer, memSize aBufSize, memSize &aValSize
933)
934{
935 // copy from config
936 aValSize=aStructFieldsKeyP->getEngineInterface()->getSyncAppBase()->getRootConfig()->fLicenseName.size();
937 if (aBufSize>0)
938 strncpy((char *)aBuffer,aStructFieldsKeyP->getEngineInterface()->getSyncAppBase()->getRootConfig()->fLicenseName.c_str(),aBufSize);
939 return LOCERR_OK;
940} // readLicenseText
941
942
943// - write license text
944static TSyError writeLicenseText(
945 TStructFieldsKey *aStructFieldsKeyP, const TStructFieldInfo *aFldInfoP,
946 cAppPointer aBuffer, memSize aValSize
947)
948{
949 // assign to config
950 aStructFieldsKeyP->getEngineInterface()->getSyncAppBase()->getRootConfig()->fLicenseName.assign((cAppCharP)aBuffer,aValSize);
951 /* DO NOT recalculate, only when setting code
952 // recalculate app enabled status
953 fEngineInterfaceP->getSyncAppBase()->isRegistered();
954 */
955 return LOCERR_OK;
956} // writeLicenseText
957
958
959// - write license code
960static TSyError writeLicenseCode(
961 TStructFieldsKey *aStructFieldsKeyP, const TStructFieldInfo *aFldInfoP,
962 cAppPointer aBuffer, memSize aValSize
963)
964{
965 // assign to config
966 aStructFieldsKeyP->getEngineInterface()->getSyncAppBase()->getRootConfig()->fLicenseCode.assign((cAppCharP)aBuffer,aValSize);
967 // recalculate all license dependent variables
968 aStructFieldsKeyP->getEngineInterface()->getSyncAppBase()->isRegistered();
969 // always ok
970 return LOCERR_OK;
971} // writeLicenseCode
972
973
974// - read (and recalculate) registration status code
975// (i.e. status of currently installed license. Note that even if this returns non-ok, the app
976// might still be able to sync, e.g. due to a free demo period)
977static TSyError readRegStatus(
978 TStructFieldsKey *aStructFieldsKeyP, const TStructFieldInfo *aFldInfoP,
979 appPointer aBuffer, memSize aBufSize, memSize &aValSize
980)
981{
982 aValSize=2;
983 if (aBufSize>=aValSize) {
984 // recalculate all license dependent variables
985 localstatus sta = aStructFieldsKeyP->getEngineInterface()->getSyncAppBase()->isRegistered();
986 // copy from config
987 *((uInt16*)aBuffer)=sta;
988 }
989 return LOCERR_OK;
990} // readRegStatus
991
992
993// - read (and recalculate) application enable status code
994// (i.e. if app can sync now. Note that this does not necessarily mean that a valid license is installed,
995// read "regStatus" for that).
996static TSyError readEnabledStatus(
997 TStructFieldsKey *aStructFieldsKeyP, const TStructFieldInfo *aFldInfoP,
998 appPointer aBuffer, memSize aBufSize, memSize &aValSize
999)
1000{
1001 aValSize=2;
1002 if (aBufSize>=aValSize) {
1003 // recalculate all license dependent variables and current enabled status
1004 // Note: includes checking for daysleft
1005 localstatus sta = aStructFieldsKeyP->getEngineInterface()->getSyncAppBase()->appEnableStatus();
1006 // copy from config
1007 *((uInt16*)aBuffer)=sta;
1008 }
1009 return LOCERR_OK;
1010} // readEnabledStatus
1011
1012
1013#if defined(EXPIRES_AFTER_DAYS) && defined(ENGINEINTERFACE_SUPPORT1)
1014
1015// - write first use version number
1016static TSyError writeFuv(
1017 TStructFieldsKey *aStructFieldsKeyP, const TStructFieldInfo *aFldInfoP,
1018 cAppPointer aBuffer, memSize aValSize
1019)
1020{
1021 uInt32 fuv = *((uInt32 *)aBuffer);
1022 if (fuv==0x53595359) {
1023 // start eval
1024 aStructFieldsKeyP->getEngineInterface()->getSyncAppBase()->updateFirstUseInfo(
1025 aStructFieldsKeyP->getEngineInterface()->getSyncAppBase()->fFirstUseDate,
1026 aStructFieldsKeyP->getEngineInterface()->getSyncAppBase()->fFirstUseVers
1027 );
1028 }
1029 else {
1030 // simply assign (usually values read from here in an earlier session and stored persistently outside)
1031 aStructFieldsKeyP->getEngineInterface()->getSyncAppBase()->fFirstUseVers = fuv;
1032 }
1033 // always ok
1034 return LOCERR_OK;
1035} // writeFuv
1036
1037#endif // EXPIRES_AFTER_DAYS+ENGINEINTERFACE_SUPPORT
1038
1039
1040
1041// macro simplifying typing in the table below
1042#define OFFS_SZ_AB(n) (offsetof(TSyncAppBase,n)__builtin_offsetof(TSyncAppBase, n)), sizeof(dP_ab->n)
1043// dummy pointer needed for sizeof
1044static const TSyncAppBase *dP_ab=NULL__null;
1045
1046// accessor table for licensing info
1047static const TStructFieldInfo LicensingFieldInfos[] =
1048{
1049 // valName, valType, writable, fieldOffs, valSiz
1050 // - license text and code (writable)
1051 { "licensetext", VALTYPE_TEXT, true, 0, 0, &readLicenseText, &writeLicenseText },
1052 { "licensecode", VALTYPE_TEXT, true, 0, 0, NULL__null, &writeLicenseCode },
1053 #if defined(EXPIRES_AFTER_DAYS) && defined(ENGINEINTERFACE_SUPPORT1)
1054 // - read/write for eval
1055 { "fud", VALTYPE_INT32, true, OFFS_SZ_AB(fFirstUseDate) }, // first use date
1056 { "fuv", VALTYPE_INT32, true, OFFS_SZ_AB(fFirstUseVers), NULL__null, &writeFuv }, // first use version
1057 #endif
1058 // - read-only info about licensing status from syncappbase
1059 { "regStatus", VALTYPE_INT16, false, 0, 0, &readRegStatus, NULL__null },
1060 { "enabledStatus", VALTYPE_INT16, false, 0, 0, &readEnabledStatus, NULL__null },
1061 { "regOK", VALTYPE_ENUM, false, OFFS_SZ_AB(fRegOK) },
1062 { "productCode", VALTYPE_ENUM, false, OFFS_SZ_AB(fRegProductCode) },
1063 { "productFlags", VALTYPE_ENUM, false, OFFS_SZ_AB(fRegProductFlags) },
1064 { "quantity", VALTYPE_ENUM, false, OFFS_SZ_AB(fRegQuantity) },
1065 { "licenseType", VALTYPE_ENUM, false, OFFS_SZ_AB(fRegLicenseType) },
1066 { "daysleft", VALTYPE_ENUM, false, OFFS_SZ_AB(fDaysLeft) },
1067};
1068
1069
1070// get table describing the fields in the struct
1071const TStructFieldInfo *TLicensingKey::getFieldsTable(void)
1072{
1073 return LicensingFieldInfos;
1074} // TLicensingKey::getFieldsTable
1075
1076sInt32 TLicensingKey::numFields(void)
1077{
1078 return sizeof(LicensingFieldInfos)/sizeof(TStructFieldInfo);
1079} // TLicensingKey::numFields
1080
1081
1082
1083// get actual struct base address
1084uInt8P TLicensingKey::getStructAddr(void)
1085{
1086 return (uInt8P)fEngineInterfaceP->getSyncAppBase(); // we are accessing SyncAppBase fields
1087} // TLicensingKey::getStructAddr
1088
1089
1090#endif // SYSER_REGISTRATION
1091
1092
1093// TEngineInterface
1094// ================
1095
1096// constructor
1097TEngineInterface::TEngineInterface() :
1098 fAppBaseP(NULL__null)
1099{
1100 // init string modes to default
1101 fCharSet = chs_utf8;
1102 fLineEndMode = lem_cstr;
1103 fBigEndian = false; // default to Intel order
1104} // TEngineInterface
1105
1106
1107// constructor
1108TSyError TEngineInterface::Init()
1109{
1110 #ifdef DIRECT_APPBASE_GLOBALACCESS
1111 // global anchor only exists in old-style targets; pure engines do not have it any more
1112 sysync_glob_setanchor(this);
1113 #endif
1114 // create the appropriate SyncAppBase object
1115 fAppBaseP = newSyncAppBase();
1116 if (fAppBaseP==NULL__null)
1117 return LOCERR_UNDEFINED;
1118 // set myself as the Master
1119 fAppBaseP->fEngineInterfaceP = this;
1120 // connect the debug routines to the appbase logger
1121 #ifdef SYDEBUG2
1122 if (fCI) {
1123 fCI->callbackRef = fAppBaseP;
1124 fCI->DB_DebugPuts = AppBaseLogDebugPuts;
1125 fCI->DB_DebugBlock = AppBaseLogDebugBlock;
1126 fCI->DB_DebugEndBlock = AppBaseLogDebugEndBlock;
1127 fCI->DB_DebugEndThread = AppBaseLogDebugEndThread;
1128 fCI->DB_DebugExotic = AppBaseLogDebugExotic;
1129 }
1130 #endif
1131 // we have an appbase now
1132 return LOCERR_OK;
1133} // TEngineInterface::Init
1134
1135
1136TSyError TEngineInterface::Term()
1137{ // empty for the moment
1138 return LOCERR_OK;
1139} // TEnigneInterface::Term
1140
1141
1142// destructor
1143TEngineInterface::~TEngineInterface()
1144{
1145 // delete the SyncAppBase
1146 if (fAppBaseP) {
1147 delete fAppBaseP;
1148 fAppBaseP=NULL__null;
1149 }
1150 #ifdef DIRECT_APPBASE_GLOBALACCESS
1151 // global anchor only exists in old-style targets; pure engines do not have it any more
1152 sysync_glob_setanchor(NULL__null);
1153 #endif
1154} // ~TEngineInterface
1155
1156
1157// Set text format parameters
1158TSyError TEngineInterface::SetStringMode(uInt16 aCharSet, uInt16 aLineEndMode, bool aBigEndian)
1159{
1160 // translate charset
1161 uInt16 chs;
1162 for (chs=0; chs<numCharSets; chs++) {
1163 if (engineCharSets[chs]==aCharSet) break;
1164 }
1165 if (chs==numCharSets) return LOCERR_BADPARAM;
1166 // translate lineendmode
1167 uInt16 lem;
1168 for (lem=0; lem<numLineEndModes; lem++) {
1169 if (engineLineEndModes[lem]==aLineEndMode) break;
1170 }
1171 if (lem==numLineEndModes) return LOCERR_BADPARAM;
1172 // assign them now they are checked ok
1173 fCharSet = (TCharSets)chs;
1174 fLineEndMode = (TLineEndModes)lem;
1175 // big endian flag
1176 fBigEndian = aBigEndian;
1177 return LOCERR_OK;
1178} // TEngineInterface::SetStringMode
1179
1180
1181
1182// conversion helper
1183// - converts byte stream (which can be an 8-bit char set or unicode in intel or motorola order)
1184// to internal UTF-8, according to text mode set with SetStringMode()
1185cAppCharP TEngineInterface::makeAppString(cAppCharP aTextP, string &aString)
1186{
1187 // return as-is if input is UTF-8 already
1188 if (fCharSet==chs_utf8)
1189 return cAppCharP(aTextP);
1190 // convert into passed string
1191 if (fCharSet==chs_utf16) {
1192 appendUTF16AsUTF8((uInt16 *)aTextP,0x7FFFFFFF,fBigEndian,aString, true, true);
1193 }
1194 else {
1195 appendStringAsUTF8((cAppCharP)aTextP, aString, fCharSet, fLineEndMode, true);
1196 }
1197 // return pointer to just converted string
1198 return aString.c_str();
1199} // TEngineInterface::makeAppString
1200
1201
1202
1203/// @brief init object, optionally passing XML config text in memory
1204/// @param aConfigXML[in] NULL if no external config needed, config text otherwise
1205/// @return LOCERR_OK on success, SyncML or LOCERR_xxx error code on failure
1206TSyError TEngineInterface::InitEngineXML(cAppCharP aConfigXML)
1207{
1208 #ifndef CONSTANTXML_CONFIG1
1209 return LOCERR_NOTIMP;
1210 #else
1211 // get the global context for pooling ressources like Java VM
1212 fAppBaseP->fApiInterModuleContext = fCI->gContext;
1213 // make sure we have string as UTF-8
1214 string tempStr;
1215 aConfigXML = makeAppString(aConfigXML, tempStr);
1216 // feed config string directly into engine
1217 return getSyncAppBase()->readXMLConfigConstant(aConfigXML);
1218 #endif
1219} // TEngineInterface::InitEngineXML
1220
1221
1222/// @brief init object, optionally passing a open FILE for reading config
1223/// @param aCfgFile[in] open file containing XML config
1224/// @return LOCERR_OK on success, SyncML or LOCERR_xxx error code on failure
1225TSyError TEngineInterface::InitEngineFile(cAppCharP aConfigFilePath)
1226{
1227 // make sure we have string as UTF-8
1228 string tempStr;
1229 aConfigFilePath = makeAppString(aConfigFilePath, tempStr);
1230 // get the global context for pooling ressources like Java VM
1231 fAppBaseP->fApiInterModuleContext = fCI->gContext;
1232 // read config from a file
1233 string pathStr = aConfigFilePath;
1234 getSyncAppBase()->expandConfigVars(pathStr,2);
1235 // now parse config
1236 return getSyncAppBase()->readXMLConfigFile(pathStr.c_str());
1237} // TEngineInterface::InitEngineFile
1238
1239
1240/// @brief init object, optionally passing a callback for reading config
1241/// @param aReaderFunc[in] callback function which can deliver next chunk of XML config data
1242/// @param aContext[in] free context pointer passed back with callback
1243/// @return LOCERR_OK on success, SyncML or LOCERR_xxx error code on failure
1244TSyError TEngineInterface::InitEngineCB(TXMLConfigReadFunc aReaderFunc, void *aContext)
1245{
1246 // get the global context for pooling ressources like Java VM
1247 fAppBaseP->fApiInterModuleContext = fCI->gContext;
1248 // now parse config
1249 return getSyncAppBase()->readXMLConfigStream(aReaderFunc, aContext);
1250} // TEngineInterface::InitEngineCB
1251
1252
1253/// @brief Open a session
1254/// @param aNewSessionH[out] receives session handle for all session execution calls
1255/// @param aSelector[in] selector, depending on session type. For multi-profile clients: profile ID to use
1256/// @param aSessionName[in] a text name/id to identify a session, useage depending on session type.
1257/// @return LOCERR_OK on success, SyncML or LOCERR_xxx error code on failure
1258TSyError TEngineInterface::OpenSession(SessionH &aNewSessionH, uInt32 aSelector, cAppCharP aSessionName)
1259{
1260 // safety check - app must be enabled (initialized with config and ok license before we can open a session)
1261 localstatus sta=getSyncAppBase()->appEnableStatus();
1262 if (sta!=LOCERR_OK) return sta; // app not enabled (and maybe not initialized properly) - prevent any session opening
1263 // make sure we have string as UTF-8
1264 string tempStr;
1265 aSessionName = makeAppString(aSessionName, tempStr);
1266
1267 return OpenSessionInternal(aNewSessionH, aSelector, aSessionName);
1268} // TEngineInterface::OpenSession
1269
1270/// @brief internal implementation, derived in actual clients or servers
1271TSyError TEngineInterface::OpenSessionInternal(SessionH &aNewSessionH, uInt32 aSelector, cAppCharP aSessionName)
1272{
1273 // must be implemented in derived class
1274 return LOCERR_NOTIMP;
1275} // TEngineInterface::OpenSessionInternal
1276
1277
1278/// @brief open session specific runtime parameter/settings key
1279/// @note key handle obtained with this call must be closed BEFORE SESSION IS CLOSED!
1280/// @param aNewKeyH[out] receives the opened key's handle on success
1281/// @param aSessionH[in] session handle obtained with OpenSession
1282/// @param aMode[in] the open mode
1283/// @return LOCERR_OK on success, SyncML or LOCERR_xxx error code on failure
1284TSyError TEngineInterface::OpenSessionKey(SessionH aSessionH, KeyH &aNewKeyH, uInt16 aMode)
1285{
1286 // no session key available in base class
1287 return DB_NotFound;
1288} // TEngineInterface::OpenSessionKey
1289
1290
1291
1292/// @brief Close a session
1293/// @note It depends on session type if this also destroys the session or if it may persist and can be re-opened.
1294/// @param aSessionH[in] session handle obtained with OpenSession
1295/// @return LOCERR_OK on success, SyncML or LOCERR_xxx error code on failure
1296TSyError TEngineInterface::CloseSession(SessionH aSessionH)
1297{
1298 // must be implemented in derived class
1299 return LOCERR_NOTIMP;
1300} // TEngineInterface::CloseSession
1301
1302
1303/// @brief Executes next step of the session
1304/// @param aSessionH[in] session handle obtained with OpenSession
1305/// @param aStepCmd[in/out] step command (STEPCMD_xxx):
1306/// - tells caller to send or receive data or end the session etc.
1307/// - instructs engine to suspend or abort the session etc.
1308/// @param aInfoP[in] pointer to a TEngineProgressInfo structure, NULL if no progress info needed
1309/// @return LOCERR_OK on success, SyncML or LOCERR_xxx error code on failure
1310TSyError TEngineInterface::SessionStep (SessionH aSessionH, uInt16 &aStepCmd, TEngineProgressInfo *aInfoP)
1311{
1312 // must be implemented in derived class
1313 return LOCERR_NOTIMP;
1314} // TEngineInterface::SessionStep
1315
1316
1317/// @brief Get access to SyncML message buffer
1318/// @param aSessionH[in] session handle obtained with OpenSession
1319/// @param aForSend[in] send mode (true) / receive mode (false)
1320/// @param aBuffer[out] receives pointer to buffer (empty for receive, full for send)
1321/// @param aBufSize[out] receives size of empty or full buffer
1322/// @return LOCERR_OK on success, SyncML or LOCERR_xxx error code on failure
1323TSyError TEngineInterface::GetSyncMLBuffer(SessionH aSessionH, bool aForSend, appPointer &aBuffer, memSize &aBufSize)
1324{
1325 Ret_t rc;
1326 MemSize_t bufSz; // Note: this is SML_TK definition of memsize!
1327 // get SML instance for this session (note that "session" could be a SAN checker as well)
1328 InstanceID_t myInstance = getSmlInstanceOfSession(aSessionH);
1329 if (myInstance==0)
1330 return LOCERR_WRONGUSAGE; // no instance, usage must be wrong
1331 // provide access to the buffer
1332 if (aForSend) {
1333 // we want to read the SyncML buffer
1334 rc=smlLockReadBuffer(
1335 myInstance,
1336 (unsigned char **)&aBuffer, // receives address of buffer containing SyncML to send
1337 &bufSz // receives size of SyncML to send
1338 );
1339 aBufSize = bufSz;
1340 }
1341 else {
1342 // we want to write the SyncML buffer
1343 rc=smlLockWriteBuffer(
1344 myInstance,
1345 (unsigned char **)&aBuffer, // receives address of buffer where received SyncML can be put
1346 &bufSz // capacity of the buffer
1347 );
1348 aBufSize = bufSz;
1349 }
1350 // check error
1351 if (rc!=SML_ERR_OK0x00)
1352 return LOCERR_SMLFATAL; // problem with SML toolkit
1353 // done
1354 return LOCERR_OK;
1355} // TEngineInterface::GetSyncMLBuffer
1356
1357
1358
1359/// @brief Return SyncML message buffer to engine
1360/// @param aSessionH[in] session handle obtained with OpenSession
1361/// @param aForSend[in] send mode (true) / receive mode (false)
1362/// @param aProcessed[in] number of bytes put into or read from the buffer
1363/// @return LOCERR_OK on success, SyncML or LOCERR_xxx error code on failure
1364TSyError TEngineInterface::RetSyncMLBuffer(SessionH aSessionH, bool aForSend, memSize aProcessed)
1365{
1366 Ret_t rc;
1367
1368 // get SML instance for this session (note that "session" could be a SAN checker as well)
1369 InstanceID_t myInstance = getSmlInstanceOfSession(aSessionH);
1370 if (myInstance==0)
1371 return LOCERR_WRONGUSAGE; // no instance, usage must be wrong
1372 // return buffer
1373 if (aForSend) {
1374 // we have read the SyncML from the buffer (and usually sent to the remote)
1375 rc=smlUnlockReadBuffer(
1376 myInstance,
1377 aProcessed // number of bytes read from the buffer (and sent to the remote, hopefully...)
1378 );
1379 }
1380 else {
1381 // we have written some data (usually received from the remote) into the SyncML buffer
1382 rc=smlUnlockWriteBuffer(
1383 myInstance,
1384 aProcessed // number of SyncML bytes put into the buffer (coming from the remote, usually...)
1385 );
1386 }
1387 // check error
1388 if (rc!=SML_ERR_OK0x00)
1389 return LOCERR_SMLFATAL; // problem with SML toolkit
1390 // done
1391 return LOCERR_OK;
1392} // TEngineInterface::RetSyncMLBuffer
1393
1394
1395/// @brief Read data from SyncML message buffer
1396/// @param aSessionH[in] session handle obtained with OpenSession
1397/// @param aBuffer[in] pointer to buffer
1398/// @param aBufSize[in] size of buffer, maximum to be read
1399/// @param aMsgSize[out] size of data available in the buffer for read INCLUDING just returned data.
1400/// @note If the aBufSize is too small to return all available data LOCERR_TRUNCATED will be returned, and the
1401/// caller can repeat calls to ReadSyncMLBuffer to get the next chunk.
1402/// @return LOCERR_OK on success, SyncML or LOCERR_xxx error code on failure
1403TSyError TEngineInterface::ReadSyncMLBuffer(SessionH aSessionH, appPointer aBuffer, memSize aBufSize, memSize &aMsgSize)
1404{
1405 TSyError sta;
1406 appPointer bufP;
1407 memSize msgsiz;
1408
1409 // get buffer for read
1410 sta = GetSyncMLBuffer(aSessionH,true,bufP,msgsiz);
1411 if (sta!=LOCERR_OK) return sta;
1412 // anyway: pass size of data in the buffer
1413 aMsgSize = msgsiz;
1414 // check if buffer passed is large enough
1415 if (aBufSize<msgsiz) {
1416 sta = LOCERR_TRUNCATED;
1417 // adjust number of bytes to copy
1418 msgsiz=aBufSize;
1419 }
1420 if (msgsiz>0) {
1421 // copy data
1422 memcpy(aBuffer,bufP,msgsiz);
1423 }
1424 // return SyncML buffer to engine
1425 RetSyncMLBuffer(aSessionH,true,msgsiz);
1426 // return status
1427 return sta;
1428} // TEngineInterface::ReadSyncMLBuffer
1429
1430
1431/// @brief Write data to SyncML message buffer
1432/// @param aSessionH[in] session handle obtained with OpenSession
1433/// @param aBuffer[in] pointer to buffer
1434/// @param aMsgSize[in] size of message to write to the buffer
1435/// @return LOCERR_OK on success, SyncML or LOCERR_xxx error code on failure
1436TSyError TEngineInterface::WriteSyncMLBuffer(SessionH aSessionH, appPointer aBuffer, memSize aMsgSize)
1437{
1438 TSyError sta;
1439 appPointer bufP;
1440 memSize bufsiz;
1441
1442 // get buffer for write
1443 sta = GetSyncMLBuffer(aSessionH,false,bufP,bufsiz);
1444 if (sta!=LOCERR_OK) return sta;
1445 // check if buffer large enough to write data
1446 if (aMsgSize>bufsiz) {
1447 // can't write data - message too large
1448 sta = LOCERR_BUFTOOSMALL;
1449 aMsgSize=0; // don't write anything
1450 }
1451 else {
1452 if (aMsgSize>0) {
1453 // copy data
1454 memcpy(bufP,aBuffer,aMsgSize);
1455 }
1456 }
1457 // return SyncML buffer to engine
1458 RetSyncMLBuffer(aSessionH,false,aMsgSize);
1459 // return status
1460 return sta;
1461} // TEngineInterface::WriteSyncMLBuffer
1462
1463
1464
1465
1466
1467/// @brief open Settings key by path specification
1468/// @param aNewKeyH[out] receives the opened key's handle on success
1469/// @param aParentKeyH[in] NULL if path is absolute from root, handle to an open key for relative access
1470/// @param aPath[in] the path specification as null terminated string
1471/// @param aMode[in] the open mode
1472/// @return LOCERR_OK on success, SyncML or LOCERR_xxx error code on failure
1473TSyError TEngineInterface::OpenKeyByPath (
1474 KeyH &aNewKeyH,
1475 KeyH aParentKeyH,
1476 cAppCharP aPath, uInt16 aMode
1477) {
1478 TSettingsKeyImpl *aBaseKeyP = NULL__null;
1479 TSettingsKeyImpl *aKeyP = NULL__null;
1480 bool implicit = false;
1481 TSyError sta;
1482
1483 // make sure we have string as UTF-8
1484 string tempStr;
1485 aPath = makeAppString(aPath, tempStr);
1486
1487 // determine base key
1488 if (aParentKeyH) {
1489 // already opened base key passed
1490 aBaseKeyP = reinterpret_cast<TSettingsKeyImpl *>(aParentKeyH);
1491 implicit = false; // we have the parent already, do not delete it implicitly
1492 }
1493 else {
1494 // we need to implicitly create the root key
1495 aBaseKeyP = newSettingsRootKey();
1496 implicit = true; // the root key is implicitly created and must be deleted implicitly as well
1497 }
1498 // open key
1499 if (implicit && (aPath==NULL__null || *aPath==0 || (*aPath==SETTINGSKEY_PATH_SEPARATOR'/' && *(aPath+1)==0))) {
1500 // opening root requested
1501 aKeyP = aBaseKeyP;
1502 sta = LOCERR_OK;
1503 }
1504 else {
1505 // open subkey of current key
1506 sta = aBaseKeyP->OpenKeyByPath(aKeyP,aPath,aMode,implicit);
1507 }
1508 if (sta!=LOCERR_OK) {
1509 if (aKeyP) {
1510 // make sure all implicitly opened elements of the chain are deleted
1511 // (includes the TSettingsRootKey, if one was created above)
1512 delete aKeyP;
1513 }
1514 }
1515 else {
1516 // pass back pointer to opened key
1517 aNewKeyH = (KeyH)aKeyP;
1518 }
1519 return sta;
1520} // TEngineInterface::OpenKeyByPath
1521
1522
1523
1524/// @brief open Settings subkey key by ID or iterating over all subkeys
1525/// @param aNewKeyH[out] receives the opened key's handle on success
1526/// @param aParentKeyH[in] handle to the parent key
1527/// @param aID[in] the ID of the subkey to open,
1528/// or KEYVAL_ID_FIRST/KEYVAL_ID_NEXT to iterate over existing subkeys
1529/// or KEYVAL_ID_NEW to create a new subkey
1530/// @param aMode[in] the open mode
1531/// @return LOCERR_OK on success, DB_NoContent when no more subkeys are found with
1532/// KEYVAL_ID_FIRST/KEYVAL_ID_NEXT
1533/// or any other SyncML or LOCERR_xxx error code on failure
1534TSyError TEngineInterface::OpenSubkey(
1535 KeyH &aNewKeyH,
1536 KeyH aParentKeyH,
1537 sInt32 aID, uInt16 aMode
1538) {
1539 TSettingsKeyImpl *baseKeyP = NULL__null;
1540 TSettingsKeyImpl *keyP = NULL__null;
1541 TSyError sta;
1542
1543 // We need a parent key
1544 if (!aParentKeyH) return LOCERR_WRONGUSAGE;
1545 // Get key
1546 baseKeyP = reinterpret_cast<TSettingsKeyImpl *>(aParentKeyH);
1547 // now open subkey
1548 sta = baseKeyP->OpenSubkey(keyP,aID,aMode);
1549 if (sta == LOCERR_OK) {
1550 // return key handle
1551 aNewKeyH = (KeyH)keyP;
1552 }
1553 return sta;
1554} // TEngineInterface::OpenSubkey
1555
1556
1557/// @brief delete Settings subkey key by ID
1558/// @param aID[in] the ID of the subkey to delete
1559/// @param aParentKeyH[in] handle to the parent key
1560/// @return LOCERR_OK on success
1561/// or any other SyncML or LOCERR_xxx error code on failure
1562TSyError TEngineInterface::DeleteSubkey(KeyH aParentKeyH, sInt32 aID)
1563{
1564 // We need a parent key
1565 if (!aParentKeyH) return LOCERR_WRONGUSAGE;
1566 // Get key
1567 return reinterpret_cast<TSettingsKeyImpl *>(aParentKeyH)->DeleteSubkey(aID);
1568} // TEngineInterface::DeleteSubkey
1569
1570
1571/// @brief Get key ID of currently open key. Note that the Key ID is only locally unique within
1572/// the parent key.
1573/// @param aKeyH[in] an open key handle
1574/// @param aID[out] receives the ID of the open key, which can be used to re-access the
1575/// key within its parent using OpenSubkey()
1576/// @return LOCERR_OK on success, SyncML or LOCERR_xxx error code on failure
1577TSyError TEngineInterface::GetKeyID(KeyH aKeyH, sInt32 &aID)
1578{
1579 if (!aKeyH) return LOCERR_WRONGUSAGE;
1580 return reinterpret_cast<TSettingsKeyImpl *>(aKeyH)->GetKeyID(aID);
1581} // TEngineInterface::GetKeyID
1582
1583
1584
1585
1586/// @brief Set text format parameters
1587/// @param aKeyH[in] an open key handle
1588/// @param aCharSet[in] charset (default is UTF-8 when SetTextMode() is not used)
1589/// @param aLineEndMode[in] line end mode (default is C-lineends of the platform (almost always LF) when SetTextMode() is not used)
1590/// @param aBigEndian[in] determines endianness of UTF16 text (defaults to little endian = intel order)
1591/// @return LOCERR_OK on success, SyncML or LOCERR_xxx error code on failure
1592TSyError TEngineInterface::SetTextMode(KeyH aKeyH, uInt16 aCharSet, uInt16 aLineEndMode, bool aBigEndian)
1593{
1594 if (!aKeyH) return LOCERR_WRONGUSAGE;
1595 return reinterpret_cast<TSettingsKeyImpl *>(aKeyH)->SetTextMode(aCharSet,aLineEndMode,aBigEndian);
1596} // TEngineInterface::SetTextMode
1597
1598
1599
1600/// @brief Set time format parameters
1601/// @param aKeyH[in] an open key handle
1602/// @param aTimeMode[in] time mode, see TMODE_xxx (default is platform's lineratime_t when SetTimeMode() is not used)
1603/// @return LOCERR_OK on success, SyncML or LOCERR_xxx error code on failure
1604TSyError TEngineInterface::SetTimeMode(KeyH aKeyH, uInt16 aTimeMode)
1605{
1606 if (!aKeyH) return LOCERR_WRONGUSAGE;
1607 return reinterpret_cast<TSettingsKeyImpl *>(aKeyH)->SetTimeMode(aTimeMode);
1608} // TEngineInterface::SetTimeMode
1609
1610
1611
1612/// @brief Closes a key opened by OpenKeyByPath() or OpenSubKey()
1613/// @param aKeyH[in] an open key handle. Will be invalid when call returns with LOCERR_OK. Do not re-use!
1614/// @return LOCERR_OK on success, SyncML or LOCERR_xxx error code on failure
1615TSyError TEngineInterface::CloseKey(KeyH aKeyH)
1616{
1617 if (aKeyH) {
1618 // deleting key will close it (including all implicitly opened parents)
1619 delete reinterpret_cast<TSettingsKeyImpl *>(aKeyH);
1620 }
1621 return LOCERR_OK;
1622} // TEngineInterface::CloseKey
1623
1624
1625/// @brief get value's ID for use with Get/SetValueByID()
1626/// @return KEYVAL_ID_UNKNOWN when name is unknown,
1627/// KEYVAL_NO_ID when name is known, but no ID exists for it (ID access not possible)
1628/// ID of value otherwise
1629sInt32 TEngineInterface::GetValueID(KeyH aKeyH, cAppCharP aName)
1630{
1631 if (!aKeyH) return KEYVAL_ID_UNKNOWN;
1632
1633 // make sure we have string as UTF-8
1634 string tempStr;
1635 aName = makeAppString(aName, tempStr);
1636
1637 return reinterpret_cast<TSettingsKeyImpl *>(aKeyH)->GetValueID(aName);
1638} // TEngineInterface::GetValueID
1639
1640
1641/// @brief Reads a named value in specified format into passed memory buffer
1642/// @param aKeyH[in] an open key handle
1643/// @param aValueName[in] name of the value to read
1644/// @param aValType[in] desired return type, see VALTYPE_xxxx
1645/// @param aBuffer[in/out] buffer where to store the data
1646/// @param aBufSize[in] size of buffer in bytes (ALWAYS in bytes, even if value is Unicode string)
1647/// @param aValSize[out] actual size of value.
1648/// For VALTYPE_TEXT, size is string length (IN BYTES) excluding NULL terminator
1649/// Note that this will be set also when return value is LOCERR_BUFTOOSMALL, to indicate the required buffer size
1650/// @return LOCERR_OK on success, SyncML or LOCERR_xxx error code on failure
1651TSyError TEngineInterface::GetValue(
1652 KeyH aKeyH, cAppCharP aValueName,
1653 uInt16 aValType,
1654 appPointer aBuffer, memSize aBufSize, memSize &aValSize
1655)
1656{
1657 if (!aKeyH) return LOCERR_WRONGUSAGE;
1658
1659 // GetValueID will convert aValueName to app format if needed
1660 sInt32 valId = GetValueID(aKeyH,aValueName);
1661 if (valId==KEYVAL_ID_UNKNOWN) return DB_NotFound;
1662 // directly call settingsKeyImpl, for cases where value has no ID
1663 return reinterpret_cast<TSettingsKeyImpl *>(aKeyH)->GetValueByID(
1664 valId,0,aValType,aBuffer,aBufSize,aValSize
1665 );
1666} // GetValue
1667
1668
1669/// @brief Reads value by ID in specified format into passed memory buffer
1670/// @param aKeyH[in] an open key handle
1671/// @param aID[in] ID of the value to read
1672/// @param aArrayIndex[in] 0-based array element index for array values.
1673/// @param aValType[in] desired return type, see VALTYPE_xxxx
1674/// @param aBuffer[in/out] buffer where to store the data
1675/// @param aBufSize[in] size of buffer in bytes (ALWAYS in bytes, even if value is Unicode string)
1676/// @param aValSize[out] actual size of value.
1677/// For VALTYPE_TEXT, size is string length (IN BYTES) excluding NULL terminator
1678/// Note that this will be set also when return value is LOCERR_BUFTOOSMALL, to indicate the required buffer size
1679/// @return LOCERR_OK on success, LOCERR_OUTOFRANGE when array index is out of range
1680/// SyncML or LOCERR_xxx error code on other failure
1681TSyError TEngineInterface::GetValueByID(
1682 KeyH aKeyH, sInt32 aID, sInt32 aArrayIndex,
1683 uInt16 aValType,
1684 appPointer aBuffer, memSize aBufSize, memSize &aValSize
1685)
1686{
1687 if (!aKeyH) return LOCERR_WRONGUSAGE;
1688 if (aID==KEYVAL_NO_ID) return LOCERR_BADPARAM;
1689 return reinterpret_cast<TSettingsKeyImpl *>(aKeyH)->GetValueByID(
1690 aID,aArrayIndex,aValType,aBuffer,aBufSize,aValSize
1691 );
1692} // TEngineInterface::GetValueByID
1693
1694
1695
1696/// @brief Writes a named value in specified format passed in memory buffer
1697/// @param aKeyH[in] an open key handle
1698/// @param aValueName[in] name of the value to write
1699/// @param aValType[in] type of value passed in, see VALTYPE_xxxx
1700/// @param aBuffer[in] buffer containing the data
1701/// @param aValSize[in] size of value. For VALTYPE_TEXT, size can be passed as -1 if string is null terminated
1702/// @return LOCERR_OK on success, SyncML or LOCERR_xxx error code on failure
1703TSyError TEngineInterface::SetValue(
1704 KeyH aKeyH, cAppCharP aValueName,
1705 uInt16 aValType,
1706 cAppPointer aBuffer, memSize aValSize
1707) {
1708 if (!aKeyH) return LOCERR_WRONGUSAGE;
1709
1710 // GetValueID will convert aValueName to app format if needed
1711 sInt32 valId = GetValueID(aKeyH,aValueName);
1712 if (valId==KEYVAL_ID_UNKNOWN) return DB_NotFound;
1713 return reinterpret_cast<TSettingsKeyImpl *>(aKeyH)->SetValueByID(
1714 valId,0,aValType,aBuffer,aValSize
1715 );
1716} // TEngineInterface::SetValue
1717
1718
1719/// @brief Writes a named value in specified format passed in memory buffer
1720/// @param aKeyH[in] an open key handle
1721/// @param aID[in] ID of the value to read
1722/// @param aArrayIndex[in] 0-based array element index for array values.
1723/// @param aValType[in] type of value passed in, see VALTYPE_xxxx
1724/// @param aBuffer[in] buffer containing the data
1725/// @param aValSize[in] size of value. For VALTYPE_TEXT, size can be passed as -1 if string is null terminated
1726/// @return LOCERR_OK on success, SyncML or LOCERR_xxx error code on failure
1727TSyError TEngineInterface::SetValueByID(
1728 KeyH aKeyH, sInt32 aID, sInt32 aArrayIndex,
1729 uInt16 aValType,
1730 cAppPointer aBuffer, memSize aValSize
1731)
1732{
1733 if (!aKeyH) return LOCERR_WRONGUSAGE;
1734 if (aID==KEYVAL_NO_ID) return LOCERR_BADPARAM;
1735 return reinterpret_cast<TSettingsKeyImpl *>(aKeyH)->SetValueByID(
1736 aID,aArrayIndex,aValType,aBuffer,aValSize
1737 );
1738} // TEngineInterface::SetValueByID
1739
1740
1741
1742#ifdef DBAPI_TUNNEL_SUPPORT
1743
1744// DBApi-like access to datastores
1745// ===============================
1746
1747TSyError TEngineInterface::StartDataRead(SessionH aSessionH, cAppCharP lastToken, cAppCharP resumeToken)
1748{
1749 TLocalEngineDS *ds = reinterpret_cast<TSyncSession *>(aSessionH)->getTunnelDS();
1750 if (!ds) return LOCERR_WRONGUSAGE; // need properly opened tunnel session/datastore
1751 return ds->TunnelStartDataRead(lastToken,resumeToken);
1752} // StartDataRead
1753
1754
1755TSyError TEngineInterface::ReadNextItem(SessionH aSessionH, ItemID aID, appCharP *aItemData, sInt32 *aStatus, bool aFirst)
1756{
1757 TLocalEngineDS *ds = reinterpret_cast<TSyncSession *>(aSessionH)->getTunnelDS();
1758 if (!ds) return LOCERR_WRONGUSAGE; // need properly opened tunnel session/datastore
1759 return ds->TunnelReadNextItem(aID,aItemData,aStatus,aFirst);
1760} // ReadNextItem
1761
1762
1763TSyError TEngineInterface::ReadItem(SessionH aSessionH, cItemID aID, appCharP *aItemData)
1764{
1765 TLocalEngineDS *ds = reinterpret_cast<TSyncSession *>(aSessionH)->getTunnelDS();
1766 if (!ds) return LOCERR_WRONGUSAGE; // need properly opened tunnel session/datastore
1767 return ds->TunnelReadItem(aID,aItemData);
1768} // ReadItem
1769
1770
1771TSyError TEngineInterface::EndDataRead(SessionH aSessionH)
1772{
1773 TLocalEngineDS *ds = reinterpret_cast<TSyncSession *>(aSessionH)->getTunnelDS();
1774 if (!ds) return LOCERR_WRONGUSAGE; // need properly opened tunnel session/datastore
1775 return ds->TunnelEndDataRead();
1776} // EndDataRead
1777
1778
1779TSyError TEngineInterface::StartDataWrite(SessionH aSessionH)
1780{
1781 TLocalEngineDS *ds = reinterpret_cast<TSyncSession *>(aSessionH)->getTunnelDS();
1782 if (!ds) return LOCERR_WRONGUSAGE; // need properly opened tunnel session/datastore
1783 return ds->TunnelStartDataWrite();
1784} // StartDataWrite
1785
1786
1787TSyError TEngineInterface::InsertItem(SessionH aSessionH, cAppCharP aItemData, ItemID aID)
1788{
1789 TLocalEngineDS *ds = reinterpret_cast<TSyncSession *>(aSessionH)->getTunnelDS();
1790 if (!ds) return LOCERR_WRONGUSAGE; // need properly opened tunnel session/datastore
1791 return ds->TunnelInsertItem(aItemData,aID);
1792} // InsertItem
1793
1794
1795TSyError TEngineInterface::UpdateItem(SessionH aSessionH, cAppCharP aItemData, cItemID aID, ItemID updID )
1796{
1797 TLocalEngineDS *ds = reinterpret_cast<TSyncSession *>(aSessionH)->getTunnelDS();
1798 if (!ds) return LOCERR_WRONGUSAGE; // need properly opened tunnel session/datastore
1799 return ds->TunnelUpdateItem(aItemData,aID,updID);
1800} // UpdateItem
1801
1802
1803TSyError TEngineInterface::MoveItem(SessionH aSessionH, cItemID aID, cAppCharP newParID)
1804{
1805 TLocalEngineDS *ds = reinterpret_cast<TSyncSession *>(aSessionH)->getTunnelDS();
1806 if (!ds) return LOCERR_WRONGUSAGE; // need properly opened tunnel session/datastore
1807 return ds->TunnelMoveItem(aID,newParID);
1808} // MoveItem
1809
1810
1811TSyError TEngineInterface::DeleteItem(SessionH aSessionH, cItemID aID)
1812{
1813 TLocalEngineDS *ds = reinterpret_cast<TSyncSession *>(aSessionH)->getTunnelDS();
1814 if (!ds) return LOCERR_WRONGUSAGE; // need properly opened tunnel session/datastore
1815 return ds->TunnelDeleteItem(aID);
1816} // DeleteItem
1817
1818
1819TSyError TEngineInterface::EndDataWrite(SessionH aSessionH, bool success, appCharP *newToken)
1820{
1821 TLocalEngineDS *ds = reinterpret_cast<TSyncSession *>(aSessionH)->getTunnelDS();
1822 if (!ds) return LOCERR_WRONGUSAGE; // need properly opened tunnel session/datastore
1823 return ds->TunnelEndDataWrite(success,newToken);
1824} // EndDataWrite
1825
1826
1827void TEngineInterface::DisposeObj(SessionH aSessionH, void* memory)
1828{
1829 TLocalEngineDS *ds = reinterpret_cast<TSyncSession *>(aSessionH)->getTunnelDS();
1830 if (!ds) return; // need properly opened tunnel session/datastore
1831 return ds->TunnelDisposeObj(memory);
1832} // DisposeObj
1833
1834
1835// ---- asKey ----
1836TSyError TEngineInterface::ReadNextItemAsKey(SessionH aSessionH, ItemID aID, KeyH aItemKey, sInt32 *aStatus, bool aFirst)
1837{
1838 TLocalEngineDS *ds = reinterpret_cast<TSyncSession *>(aSessionH)->getTunnelDS();
1839 if (!ds) return LOCERR_WRONGUSAGE; // need properly opened tunnel session/datastore
1840 return ds->TunnelReadNextItemAsKey(aID,aItemKey,aStatus,aFirst);
1841} // ReadNextItemAsKey
1842
1843
1844TSyError TEngineInterface::ReadItemAsKey(SessionH aSessionH, cItemID aID, KeyH aItemKey)
1845{
1846 TLocalEngineDS *ds = reinterpret_cast<TSyncSession *>(aSessionH)->getTunnelDS();
1847 if (!ds) return LOCERR_WRONGUSAGE; // need properly opened tunnel session/datastore
1848 return ds->TunnelReadItemAsKey(aID,aItemKey);
1849} // ReadItemAsKey
1850
1851
1852TSyError TEngineInterface::InsertItemAsKey(SessionH aSessionH, KeyH aItemKey, ItemID aID)
1853{
1854 TLocalEngineDS *ds = reinterpret_cast<TSyncSession *>(aSessionH)->getTunnelDS();
1855 if (!ds) return LOCERR_WRONGUSAGE; // need properly opened tunnel session/datastore
1856 return ds->TunnelInsertItemAsKey(aItemKey,aID);
1857} // InsertItemAsKey
1858
1859
1860TSyError TEngineInterface::UpdateItemAsKey(SessionH aSessionH, KeyH aItemKey, cItemID aID, ItemID updID)
1861{
1862 TLocalEngineDS *ds = reinterpret_cast<TSyncSession *>(aSessionH)->getTunnelDS();
1863 if (!ds) return LOCERR_WRONGUSAGE; // need properly opened tunnel session/datastore
1864 return ds->TunnelUpdateItemAsKey(aItemKey,aID,updID);
1865} // UpdateItemAsKey
1866
1867#endif // DBAPI_TUNNEL_SUPPORT
1868
1869TSyError TEngineInterface::debugPuts(cAppCharP aFile, int aLine, cAppCharP aFunction,
1870 int aDbgLevel, cAppCharP aPrefix,
1871 cAppCharP aText)
1872{
1873 #if defined(SYDEBUG2)
1874 // Including the prefix as meta-data would be better, because it would
1875 // allow formatting it, for example in HTML. Instead of
1876 // dropping it entirely, at least mix into the normal text.
1877 if (aPrefix) {
1878 std::string body = aPrefix;
1879 if (aText) {
1880 body += ": ";
1881 body += aText;
1882 }
1883 getSyncAppBase()->getDbgLogger()->DebugPuts(TDBG_LOCATION_ARGS(aFunction, aFile, aLine /*, aPrefix */)
1884 aDbgLevel, body.c_str());
1885 } else {
1886 getSyncAppBase()->getDbgLogger()->DebugPuts(TDBG_LOCATION_ARGS(aFunction, aFile, aLine)
1887 aDbgLevel, aText);
1888 }
1889 return 0;
1890 #else
1891 return LOCERR_NOTIMP;
1892 #endif
1893} // debugPuts
1894
1895#ifdef ENGINE_LIBRARY1
1896#ifndef SIMPLE_LINKING
1897
1898// Callback "factory" function implementation
1899
1900static TSyError internal_ConnectEngine(
1901 bool aIsServer,
1902 UI_Call_In *aCIP,
1903 uInt16 aCallbackVersion, // if==0, engine creates new aCI
1904 CVersion *aEngVersionP,
1905 CVersion aPrgVersion,
1906 uInt16 aDebugFlags
1907)
1908{
1909 // create new engine
1910 TEngineModuleBase *engine = NULL__null;
1911 TSyError err = LOCERR_OK;
1912 if (aIsServer) {
1913 #ifdef SYSYNC_SERVER1
1914 engine = newServerEngine();
1915 #else
1916 err = LOCERR_WRONGUSAGE;
1917 #endif
1918 }
1919 else {
1920 #ifdef SYSYNC_CLIENT1
1921 engine = newClientEngine();
1922 #else
1923 err = LOCERR_WRONGUSAGE;
1924 #endif
1925 }
1926 if (err==LOCERR_OK) {
1927 // connect the engine
1928 if (aCallbackVersion!=0) {
1929 // valid aCIP passed in
1930 // - flag static
1931 engine->fCIisStatic= true;
1932 // - prepare callback and pass to engine
1933 (*aCIP)->callbackVersion = aCallbackVersion; // fill in the outside callback version
1934 engine->fCI = *aCIP; // engine uses the structure provided by the uiapp
1935 // - connect the engine
1936 err = engine->Connect("", aPrgVersion, aDebugFlags);
1937 }
1938 else {
1939 // no aCIP passed, let engine create one
1940 // - connect engine
1941 err = engine->Connect("", aPrgVersion, aDebugFlags);
1942 // - get CI from engine
1943 *aCIP = engine->fCI;
1944 }
1945 // - get the version
1946 if (aEngVersionP) *aEngVersionP = Plugin_Version(0);
1947 }
1948 return err;
1949} // internal_ConnectEngine
1950
1951
1952// Client engine main entry point
1953TSyError SYSYNC_EXTERNAL(ConnectEngine)SySync_ConnectEngine(
1954 UI_Call_In *aCI,
1955 CVersion *aEngVersion,
1956 CVersion aPrgVersion,
1957 uInt16 aDebugFlags
1958)
1959{
1960 return internal_ConnectEngine(false, aCI, 0, aEngVersion, aPrgVersion, aDebugFlags);
1961} // ConnectEngine
1962
1963
1964// The same, but coming in with a valid <aCI> */
1965TSyError SYSYNC_EXTERNAL(ConnectEngineS)SySync_ConnectEngineS(
1966 UI_Call_In aCI,
1967 uInt16 aCallbackVersion,
1968 CVersion *aEngVersion,
1969 CVersion aPrgVersion,
1970 uInt16 aDebugFlags
1971)
1972{
1973 return internal_ConnectEngine(false, &aCI, aCallbackVersion, aEngVersion, aPrgVersion, aDebugFlags);
1974} // ConnectEngineS
1975
1976
1977// Server engine main entry point
1978TSyError SYSYNC_EXTERNAL_SRV(ConnectEngine)SySync_srv_ConnectEngine(
1979 UI_Call_In *aCI,
1980 CVersion *aEngVersion,
1981 CVersion aPrgVersion,
1982 uInt16 aDebugFlags
1983)
1984{
1985 return internal_ConnectEngine(true, aCI, 0, aEngVersion, aPrgVersion, aDebugFlags);
1986} // ConnectEngine
1987
1988
1989// The same, but coming in with a valid <aCI> */
1990TSyError SYSYNC_EXTERNAL_SRV(ConnectEngineS)SySync_srv_ConnectEngineS(
1991 UI_Call_In aCI,
1992 uInt16 aCallbackVersion,
1993 CVersion *aEngVersion,
1994 CVersion aPrgVersion,
1995 uInt16 aDebugFlags
1996)
1997{
1998 return internal_ConnectEngine(true, &aCI, aCallbackVersion, aEngVersion, aPrgVersion, aDebugFlags);
1999} // ConnectEngineS
2000
2001
2002
2003
2004static TSyError internal_DisconnectEngine(UI_Call_In aCI)
2005{
2006 TSyError err= LOCERR_OK;
2007
2008 if (aCI && aCI->thisBase) { // structure must still exist
2009 // first get pointer to engine
2010 TEngineModuleBase *engine = static_cast<TEngineModuleBase *>(aCI->thisBase);
2011 err= engine->Disconnect();
2012 aCI->thisBase= NULL__null; // no longer valid
2013 // delete the engine (this also deletes the callback!)
2014 SYSYNC_TRYtry {
2015 delete engine;
2016 }
2017 SYSYNC_CATCH (...)catch(...) {
2018 err = LOCERR_EXCEPTION;
2019 SYSYNC_ENDCATCH}
2020 // done
2021 } // if
2022 return err;
2023} // internal_DisconnectEngine
2024
2025
2026/* Entry point to disconnect client engine */
2027TSyError SYSYNC_EXTERNAL(DisconnectEngine)SySync_DisconnectEngine(UI_Call_In aCI)
2028{
2029 return internal_DisconnectEngine(aCI);
2030}
2031
2032
2033/* Entry point to disconnect server engine */
2034TSyError SYSYNC_EXTERNAL_SRV(DisconnectEngine)SySync_srv_DisconnectEngine(UI_Call_In aCI)
2035{
2036 return internal_DisconnectEngine(aCI);
2037}
2038
2039
2040#endif // not SIMPLE_LINKING
2041#endif // ENGINE_LIBRARY
2042
2043
2044} // namespace sysync
2045
2046/* end of TEngineInterface implementation */
2047
2048#endif // ENGINEINTERFACE_SUPPORT
2049
2050// eof