Bug Summary

File:libsynthesis/src/sysync_SDK/Sources/san.cpp
Warning:line 574, column 7
Access to field 'serverURI_len' results in a dereference of a null pointer (loaded from variable 'tb')

Annotated Source Code

1/*
2 * File: san.cpp
3 *
4 * Author: Beat Forster (bfo@synthesis.ch)
5 *
6 * Server Alerted Notification
7 * for OMA DS 1.2
8 *
9 * Copyright (c) 2005-2011 by Synthesis AG + plan44.ch
10 *
11 *
12 */
13
14/*
15 128 bit 64 bit + n char
16 +------------+--------------------+--------------------+
17 | | | |
18 | digest | notification-hdr | notification-body |
19 | | | |
20 +------------+--------------------+--------------------+
21 / \ \
22 / \ --------- \
23 / \ \ \
24 -------------------- ------ \ \
25 / \ \ \
26 / \ \ \
27+---------+---------+-----------+--------+---------+--------+--------+ +----------+
28| version | ui-mode | initiator | future | session | server | server | | usage |
29| | | | use | id | ident | ident | | specific |
30| | | | | | length | | | |
31+---------+---------+-----------+--------+---------+--------+--------+ +----------+
32 10 bit 2 bit 1 bit 27 bit 16 bit 8 bit n char
33
34
35H = MD5 hashing function
36B64 = Base64 encoding
37digest= H(B64(H(server-identifier:password)):nonce:B64(H(notification)))
38
39
40
41 notification body:
42 +-------+--------+--------+--------+----------+
43 | num | future | sync 1 | sync N | vendor |
44 | syncs | use | | | specific |
45 | | | | | |
46 +-------+--------+--------+--------+----------+
47 4 bit 4 bit / \ n char
48 / \
49 ---------- -------
50 / \
51 / \
52+------+--------+---------+--------+--------+
53| sync | future | content | server | server |
54| type | use | type | URI | URI |
55| | | | length | |
56+------+--------+---------+--------+--------+
57 4 bit 4 bit 24 bit 8 bit n char
58
59*/
60
61
62#ifdef HAVE_CONFIG_H1
63# include <config.h>
64#endif
65
66#include "prefix_file.h"
67#include "sync_include.h"
68#include "san.h"
69#include "sysync_md5.h"
70#include "sysync_b64.h"
71
72#ifndef WITHOUT_SAN_1_1
73#include "sysync_utils.h"
74#endif
75
76
77const uInt16 SyncML12 = 12; // currently supported SyncML version
78const uInt16 SyncML11 = 11; // currently supported SyncML version
79const uInt16 SyncML10 = 10; // currently supported SyncML version
80
81#pragma options align= packed // allow direct mapping of the structure
82
83
84using namespace sysync;
85
86namespace sysync {
87
88// ---- structure definition ---------------------------------------------
89#define BpB8 8 // bits per byte
90#define NBits7 7 // bytes of the notification-hdr bits
91#define BBits4 4 // bytes of the notification-body bits
92
93#define DB_Full420 420 // memory full error
94#define DB_Error510 510 // general DB error
95
96struct TPackage {
97 TDigestField digest;
98
99 uInt8 bitField[ NBits7 ]; // version, ui-mode, initiator, future use, sesion id
100 uInt8 serverID_len;
101}; // TPackage
102
103
104struct TBody {
105 uInt8 bitField[ BBits4 ]; // sync type, future use, content type
106 uInt8 serverURI_len;
107}; // TBody
108
109
110
111// ---- defined locally for the moment to avoid dependencies ----
112//
113// MD5 and B64 given string
114static void MD5B64_Local(const char *aString, sInt32 aLen, string &aMD5B64)
115{
116 // determine input length
117 if (aLen<=0) aLen=strlen(aString);
118 // calc MD5
119 md5::SYSYNC_MD5_CTX context;
120 uInt8 digest[16];
121 md5::Init (&context);
122 md5::Update (&context, (const uInt8 *)aString,aLen);
123 md5::Final (digest, &context);
124 // b64 encode the MD5 digest
125 uInt32 b64md5len;
126 char *b64md5=b64::encode(digest,16,&b64md5len);
127 // assign result
128 aMD5B64.assign(b64md5,b64md5len);
129 // done
130 b64::free(b64md5); // return buffer allocated by b64::encode
131} // MD5B64_Local
132
133
134
135// ---- constructor/destructor -------------------------------------------
136SanPackage::SanPackage() // constructor
137{
138 fBody= NULL__null;
139 CreateEmptyNotificationBody();
140
141 memset( &fDigest, 0, DigestSize16 );
142 fProtocolVersion= 0;
143 fUI_Mode = UI_not_specified;
144 fInitiator = Initiator_Server;
145 fSessionID = 0;
146
147 fSan = NULL__null;
148 fSanSize = 0;
149} // constructor
150
151
152SanPackage::~SanPackage() // destructor
153{
154 ReleasePackage();
155 ReleaseNotificationBody();
156} // destructor
157
158
159
160// ---- digest creation --------------------------------------------------
161TDigestField SanPackage::H( string s )
162{
163 TDigestField df;
164
165 // calc MD5
166 md5::SYSYNC_MD5_CTX context;
167 md5::Init ( &context );
168 md5::Update ( &context, (const uInt8 *)s.c_str(), s.length() );
169 md5::Final( df.b, &context );
170 return df;
171} // DigestField
172
173
174string SanPackage::B64_H( string s1, string s2 )
175{
176 if (!s2.empty()) s1+= ":" + s2;
177 MD5B64_Local( s1.c_str(), s1.size(), s1 );
178 return s1;
179} // B64_H
180
181
182string SanPackage::B64_H_Notification( void* san, size_t sanSize )
183{
184 string s;
185 const char* v= (const char*)san + DigestSize16;
186 size_t nfySize= sanSize - DigestSize16;
187 MD5B64_Local( v, nfySize, s );
188 return s;
189} // B64_H
190
191
192
193/*! Prepare the SAN record */
194void SanPackage::PreparePackage( string aB64_H_srvID_pwd,
195 string aNonce,
196 uInt16 aProtocolVersion,
197 UI_Mode aUI_Mode,
198 Initiator aInitiator,
199 uInt16 aSessionID,
200 string aSrvID )
201{
202 fB64_H_srvID_pwd= aB64_H_srvID_pwd;
203 fNonce = aNonce;
204 fProtocolVersion= aProtocolVersion;
205 fUI_Mode = aUI_Mode;
206 fInitiator = aInitiator;
207 fSessionID = aSessionID;
208 fServerID = aSrvID;
209} // PreparePackage
210
211
212// if only hashes are available
213TSyError SanPackage::CreateDigest( const char* b64_h_serverID_password,
214 const char* aNonce,
215 void* san, size_t sanSize )
216{
217 string s= b64_h_serverID_password;
218 if ( s.empty()) {
219 for (int i= 0; i<DigestSize16; i++) { // special case for empty digest
220 fDigest.b[ i ]= 0x00;
221 } // for
222 }
223 else { s+= ":";
224 s+= aNonce; s+= ":";
225 s+= B64_H_Notification( san,sanSize );
226 fDigest= H( s );
227 } // if
228
229 return LOCERR_OK;
230} // CreateDigest
231
232
233TSyError SanPackage::CreateDigest( const char* aServerID,
234 const char* aPassword,
235 const char* aNonce,
236 void* san, size_t sanSize )
237{
238 return CreateDigest( B64_H( aServerID,aPassword ).c_str(),
239 aNonce,
240 san,sanSize );
241} // CreateDigest
242
243
244
245bool SanPackage::DigestOK( void* san )
246{
247 TDigestField* sanD= (TDigestField*)san;
248
249 for (int i= 0; i<DigestSize16; i++) {
250 if (fDigest.b[ i ]!=sanD->b[ i ]) return false;
251 } // for
252
253 return true;
254} // DigestOK
255
256
257
258// ---- bit operations ---------------------------------------------------
259void SanPackage::AddBits( void* ptr, int pos, int n, uInt32 value )
260{
261 byte* b= (byte*)ptr;
262 int lim= pos+n;
263 if (lim>BpB8*NBits7) return; // check if within the field
264 while (lim>BpB8) { b++; lim-= BpB8; }
265
266 int i;
267 for (i=0; i<n; i++) {
268 uInt8 db= 1<<(BpB8-lim);
269
270 if ((value % 2)==1) *b|= db; // add bit
271 else *b&= ~db; // remove bit
272 value= value / 2;
273
274 lim--;
275 if (lim==0) { lim= BpB8; b--; }
276 } // for
277} // AddBits
278
279
280uInt32 SanPackage::GetBits( void* ptr, int pos, int n )
281{
282 uInt32 value= 0;
283
284 byte* b= (byte*)ptr;
285 int lim= pos+n;
286 if (lim>BpB8*NBits7) return 0; // check if within the field
287 while (lim>BpB8) { b++; lim-= BpB8; }
288
289 int i;
290 for (i=0; i<n; i++) {
291 uInt8 db= 1<<(BpB8-lim);
292
293 if ((*b & db)!=0) value|= (1<<n); // check bit and add it to <value>
294 value= value / 2;
295
296 lim--;
297 if (lim==0) { lim= BpB8; b--; }
298 } // for
299
300 return value;
301} // GetBits
302
303
304
305// ---- notification body generation -------------------------------------
306void SanPackage::CreateEmptyNotificationBody()
307{
308 ReleaseNotificationBody();
309
310 fEmpty= 0x00; // no sync fields = ALL data stores concerned
311 fBody= &fEmpty;
312 fBodySize= sizeof(fEmpty);
313 fNSync= 0;
314} // CreateEmptyNotificationBody
315
316
317
318TSyError SanPackage::AddSync( int syncType, uInt32 contentType,
319 const char* serverURI )
320{
321 int len= strlen(serverURI);
322 int nLen= BBits4 + 1 + len; // length of the new part
323 int newLen= fBodySize + nLen; // total length of the new block
324
325 void* fb= malloc( newLen ); // allocate it
326 memcpy( fb, fBody,fBodySize ); // copy existing structure to beginning
327
328 byte* b = (byte*)fb;
329 b+= fBodySize; // get a pointer to the new part
330
331 ReleaseNotificationBody(); // release the old structure
332 fNSync++; // adapt number of available parts
333 fBody = fb; // now the new bigger structure is assigned
334 fBodySize= newLen;
335
336 // fill in new counter value
337 AddBits( fBody, 0, 4, fNSync ); // number of sync datastores
338 AddBits( fBody, 4, 4, 0 ); // future use
339
340 // fill in contents of the nth structure
341 TBody* tb= (TBody*)b;
342 AddBits( tb->bitField, 0, 4, syncType-200 ); // the sync type 206..210
343 AddBits( tb->bitField, 4, 4, 0 ); // future use
344 AddBits( tb->bitField, 8,24, contentType ); // the content tye
345 tb->serverURI_len= len;
346
347 byte* pp= (byte*)(tb+1); // = right after TBody
348 memcpy( (void*) pp, (void*)serverURI, len );
349 return LOCERR_OK;
350} // AddSync
351
352
353
354void SanPackage::ReleaseNotificationBody()
355{
356 if (fBody!=NULL__null &&
357 fBody!=&fEmpty) { free( fBody ); fBody= NULL__null; }
358} // ReleaseNotificationBody
359
360
361#ifndef WITHOUT_SAN_1_1
362// general callback entry for all others
363static Ret_t univ( ... )
364{
365//printf( "callback\n" );
366 return 0;
367} // univ
368
369
370static Ret_t startM( InstanceID_t id, VoidPtr_t userData, SmlSyncHdrPtr_t pContent )
371{
372 cAppCharP Sy= "SyncML/";
373 size_t n = strlen(Sy);
374
375 SanPackage* a= (SanPackage*)userData;
376 string mup = "";
377 string nonce= "";
378
379 uInt16 major=0,minor=0;
380
381 cAppCharP verP = smlPCDataToCharP(pContent->proto);
382 if (strucmp(verP,Sy,n)==0) {
383 n+=StrToUShort(verP+n,major);
384 if (verP[n]=='.') {
385 n++;
386 StrToUShort(verP+n,minor);
387 }
388 }
389
390 sInt32 sessionID;
391 smlPCDataToLong( pContent->sessionID, sessionID );
392
393 string srvID= smlSrcTargLocURIToCharP(pContent->source);
394
395 a->PreparePackage( mup, nonce, 10*major+minor, UI_not_specified, Initiator_Server, sessionID, srvID );
396 a->CreateEmptyNotificationBody();
397 return 0;
398} // startM
399
400
401static Ret_t alertM( InstanceID_t id, VoidPtr_t userData, SmlAlertPtr_t pContent )
402{
403 SanPackage* a= (SanPackage*)userData;
404
405 sInt32 syncType;
406 smlPCDataToLong( pContent->data, syncType );
407 uInt32 contentType= 0; // always 0
408
409 SmlItemListPtr_t el= pContent->itemList;
410
411 while (true) { // can be a chained list of elements
412 string locURI= smlSrcTargLocURIToCharP(el->item->source);
413 a->AddSync( syncType, contentType, locURI.c_str() ); // for each element add one
414
415 if (el->next==NULL__null) break;
416 el= el->next;
417 } // while
418
419//printf( "alert\n" );
420 return 0;
421} // alert
422
423
424static Ret_t endM( InstanceID_t id, VoidPtr_t userData, Boolean_t final )
425{
426//printf( "end\n" );
427 return 0;
428} // endM
429
430
431// Callback record, most of the routines are not used
432static const SmlCallbacks_t mySmlCallbacks = {
433 /* message callbacks */
434 startM, // smlStartMessageCallback,
435 endM, // smlEndMessageCallback,
436 /* grouping commands */
437 (smlStartSyncFunc) univ, // smlStartSyncCallback,
438 (smlEndSyncFunc) univ, // smlEndSyncCallback,
439 #ifdef ATOMIC_RECEIVE /* these callbacks are NOT included in the Toolkit lite version */
440 univ, // smlStartAtomicCallback,
441 univ, // smlEndAtomicCallback,
442 #endif
443 #ifdef SEQUENCE_RECEIVE
444 univ, // smlStartSequenceCallback,
445 univ, // smlEndSequenceCallback,
446 #endif
447 /* Sync Commands */
448 (smlAddCmdFunc) univ, // smlAddCmdCallback,
449 alertM, // smlAlertCmdCallback,
450 (smlDeleteCmdFunc)univ, // smlDeleteCmdCallback,
451 (smlGetCmdFunc) univ, // smlGetCmdCallback,
452 (smlPutCmdFunc) univ, // smlPutCmdCallback,
453 #ifdef MAP_RECEIVE
454 (smlMapCmdFunc) univ, // smlMapCmdCallback,
455 #endif
456 #ifdef RESULT_RECEIVE
457 (smlResultsCmdFunc)univ, // smlResultsCmdCallback,
458 #endif
459 (smlStatusCmdFunc) univ, // smlStatusCmdCallback,
460 (smlReplaceCmdFunc)univ, // smlReplaceCmdCallback,
461 /* other commands */
462 #ifdef COPY_RECEIVE /* these callbacks are NOT included in the Toolkit lite version */
463 univ, // smlCopyCmdCallback,
464 #endif
465 #ifdef EXEC_RECEIVE
466 univ, // smlExecCmdCallback,
467 #endif
468 #ifdef SEARCH_RECEIVE
469 univ, // smlSearchCmdCallback,
470 #endif
471 smlMoveCmdFunc(univ), // smlMoveCmdCallback,
472 /* Other Callbacks */
473 smlHandleErrorFunc (univ), // smlHandleErrorCallback,
474 smlTransmitChunkFunc(univ) // smlTransmitChunkCallback
475}; /* sml_callbacks struct */
476
477
478
479// Try to convert a 1.1 message
480// - if successful, fill in values into 1.2 fields
481// - if not successful, interpret it as 1.2 structure
482TSyError SanPackage::Check_11( void* san, size_t sanSize )
483{
484 TSyError err;
485 SmlCallbacks_t scb= mySmlCallbacks;
486 SmlInstanceOptions_t sIOpts;
487 InstanceID_t id;
488 Ret_t cer;
489 MemPtr_t wPos;
490 MemSize_t freeSize;
491
492 // struct assignment / 1k buffer
493 sIOpts.encoding = SML_WBXML; // it is always WBXML
494 sIOpts.workspaceSize = 1024*30; // should be always sufficient
495 sIOpts.maxOutgoingSize= 0; // disabled for now
496
497 err= smlInitInstance( &scb, &sIOpts, this, &id ); if (err) return err;
498
499 do {
500 err= smlLockWriteBuffer ( id, &wPos, &freeSize ); if (err) break;
501
502 memcpy( wPos, san,sanSize ); // now we have a new internal copy
503 err= smlUnlockWriteBuffer( id, sanSize ); if (err) break;
504 err= smlProcessData ( id, SML_ALL_COMMANDS ); if (err) break;
505 } while (false);
506
507 cer= smlTerminateInstance( id ); if (!err) err= cer;
508
509 return err;
510} // Check_11
511#endif // WITHOUT_SAN_1_1
512
513
514TSyError SanPackage::PassSan( void* san, size_t sanSize, int mode)
515{
516 TSyError err = LOCERR_OK;
517 bool use_as_12= true;
518
519 ReleasePackage();
520//printf( "here we will have the potential 1.1 -> 1.2 conversion\n" );
521
522 #ifndef WITHOUT_SAN_1_1
523 if (mode == 0 || mode == 1) {
524 err= Check_11 ( san,sanSize );
525 if (!err) err= GetPackage( san,sanSize );
526 //use_as_12= err==SML_ERR_XLT_INCOMP_WBXML_VERS;
527 use_as_12= err!=0;
528 //printf( "err=%d\n", err );
529 }
530#endif
531
532 if (use_as_12 && mode !=1) {
533 err= DB_Full420;
534
535 fSan= malloc( sanSize );
536 if (fSan) {
537 fSanSize= sanSize;
538 memcpy( fSan, san,sanSize ); // now we have a new internal copy
539 err= LOCERR_OK;
540 } // if
541 } // if
542
543 return err;
544} // PassSan
545
546
547TSyError SanPackage::GetSanSize( void* san, size_t &sanSize )
548{
549 TPackage* tp= (TPackage*)san;
550 TBody* tb = NULL__null;
1
'tb' initialized to a null pointer value
551
552 byte* b= (byte*)(tp+1);
553 byte* v;
554
555 b+= tp->serverID_len;
556
557 int nth= GetBits( b, 0,4 ); // first not valid = the end
558
559 b++; // start of 1st element
560 int n= nth;
561 while (n>0) {
2
Assuming 'n' is <= 0
3
Loop condition is false. Execution continues on line 574
562 n--;
563 tb= (TBody*)b;
564 b = (byte*)(tb+1);
565
566 if (b > (byte*)san+sanSize && sanSize>0) return DB_Forbidden;
567 v= b + tb->serverURI_len;
568 if (b > (byte*)san+sanSize && sanSize>0) return DB_Forbidden;
569
570 if (n==0) break;
571 b= v;
572 } // while
573
574 b+= tb->serverURI_len; // finally the serverURI length
4
Access to field 'serverURI_len' results in a dereference of a null pointer (loaded from variable 'tb')
575
576 size_t rslt= b - (byte*)san;
577 if (sanSize>0 && sanSize<rslt) return DB_Forbidden;
578
579 sanSize= rslt;
580 return LOCERR_OK;
581} // GetSanSize
582
583
584// ---- notification body parsing ----------------------------------------
585TSyError SanPackage::GetNthSync( int nth,
586 int &syncType,
587 uInt32 &contentType,
588 string &serverURI )
589{
590 syncType = 0; // set default values
591 contentType= 0;
592 serverURI = "";
593
594 TPackage* tp= (TPackage*)fSan;
595 TBody* tb;
596
597 fDigest = tp->digest;
598 fProtocolVersion= GetBits( tp->bitField, 0,10 );
599 fUI_Mode = (UI_Mode)GetBits( tp->bitField, 10, 2 );
600 fInitiator = (Initiator)GetBits( tp->bitField, 12, 1 );
601 fSessionID = GetBits( tp->bitField, 40,16 );
602
603 /*If the version does not match, this should be an invalid SAN message*/
604 if (fProtocolVersion!=SyncML12 &&
605 fProtocolVersion!=SyncML11 &&
606 fProtocolVersion!=SyncML10) return DB_Forbidden;
607
608 byte* b= (byte*)(tp+1);
609 byte* v;
610
611 fServerID.assign( (const char*)b,(unsigned int)tp->serverID_len );
612 b+= tp->serverID_len;
613
614 fNSync= GetBits( b, 0,4 );
615
616 if (nth==0) return LOCERR_OK;
617 if (nth<1 || nth>fNSync ) return DB_NotFound;
618
619 b++; // start of 1st element
620 int n= nth;
621 while (n>0) {
622 n--;
623 tb= (TBody*)b;
624 b = (byte*)(tb+1);
625
626 if (b > (byte*)fSan+fSanSize) return DB_Forbidden; // no access behind the message
627 v= b + tb->serverURI_len;
628 if (v > (byte*)fSan+fSanSize) return DB_Forbidden; // no access behind the message
629
630 if (n==0) break;
631 b= v;
632 } // while
633
634 syncType = 200 + GetBits( tb->bitField, 0, 4 );
635 contentType= GetBits( tb->bitField, 8,24 );
636
637 serverURI.assign( (const char*)b,(unsigned int)tb->serverURI_len );
638
639 return LOCERR_OK;
640} // GetNthSync
641
642
643TSyError SanPackage::GetHeader()
644{
645 int syncType; // these 3 variables are not really used
646 uInt32 contentType;
647 string serverURI;
648
649 return GetNthSync( 0, syncType,contentType,serverURI );
650} // GetHeader
651
652
653
654// ---- package generation -----------------------------------------------
655TSyError SanPackage::GetPackage( void* &san, size_t &sanSize,
656 void* vendorSpecific,
657 size_t vendorSpecificSize )
658{
659 ReleasePackage(); // remove a previous one
660
661 byte len = (byte)fServerID.length(); // calulate the full size
662 sanSize= sizeof(TPackage) + len + fBodySize + vendorSpecificSize;
663 //size_t nfySize= sanSize - DigestSize;
664 fSan = malloc( sanSize );
665 san = fSan;
666 TPackage* tp= (TPackage*)fSan;
667
668 // -------------------
669 AddBits( tp->bitField, 0,10, fProtocolVersion );
670 AddBits( tp->bitField, 10, 2, fUI_Mode );
671 AddBits( tp->bitField, 12, 1, fInitiator );
672 AddBits( tp->bitField, 13,27, 0 ); // future use, must be "0"
673 AddBits( tp->bitField, 40,16, fSessionID );
674 tp->serverID_len= len;
675
676 // copy <fServerID> string at the end of TPackage struct
677 byte* pp= (byte*)(tp+1); // = right after TPackage
678 memcpy( (void*) pp, (void*)fServerID.c_str(), len );
679 memcpy( (void*)(pp+len), fBody, fBodySize );
680
681 if (vendorSpecific!=NULL__null &&
682 vendorSpecificSize>0)
683 memcpy( (void*)(pp+len+fBodySize), vendorSpecific,vendorSpecificSize );
684
685 CreateDigest( fB64_H_srvID_pwd.c_str(), fNonce.c_str(), san,sanSize );
686 tp->digest= fDigest;
687
688 fSanSize= sanSize;
689 return LOCERR_OK;
690} // GetPackage
691
692
693void SanPackage::ReleasePackage() {
694 if (fSan!=NULL__null) { free( fSan ); fSan= NULL__null; }
695} // ReleasePackage
696
697#ifndef WITHOUT_SAN_1_1
698
699const char * const SyncMLVerProtoNames[] =
700{
701 "undefined",
702 "SyncML/1.0",
703 "SyncML/1.1",
704 "SyncML/1.2"
705};
706
707const char *const SyncMLVerDTDNames[] =
708{
709 "???",
710 "1.0",
711 "1.1",
712 "1.2"
713};
714
715const SmlVersion_t SmlVersionCodes[] =
716{
717 SML_VERS_UNDEF,
718 SML_VERS_1_0,
719 SML_VERS_1_1,
720 SML_VERS_1_1
721};
722
723TSyError SanPackage::GetPackageLegacy( void* &san,
724 size_t &sanSize,
725 const vector<pair <string, string> >& sources,
726 int alertCode,
727 bool wbxml)
728{
729 ReleasePackage(); // remove a previous one
730 TSyError err;
731 SmlCallbacks_t scb= mySmlCallbacks;
732 SmlInstanceOptions_t sIOpts;
733 InstanceID_t id;
734
735
736 // struct assignment / 1k buffer
737 sIOpts.encoding = wbxml ? SML_WBXML : SML_XML;
738 sIOpts.workspaceSize = 1024; // should be always sufficient
739 sIOpts.maxOutgoingSize= 0; // disabled for now
740
741 err= smlInitInstance( &scb, &sIOpts, this, &id ); if (err) return err;
742
743 SmlSyncHdrPtr_t headerP = NULL__null;
744 SmlAlertPtr_t alertP = NULL__null;
745
746 do {
747 SYSYNC_TRYtry{
748 //create SyncHdr
749 headerP = SML_NEW (SmlSyncHdr_t)((SmlSyncHdr_t*) _smlMalloc(sizeof(SmlSyncHdr_t)));
750 headerP->elementType = SML_PE_HEADER;
751 if (fProtocolVersion != 10 && fProtocolVersion != 11){
752 //wrong version!
753 err = DB_Error510;
754 break;
755 }
756 int version = fProtocolVersion - 10 + 1;
757 headerP->version = newPCDataString (SyncMLVerDTDNames[version]);
758 headerP->proto = newPCDataString (SyncMLVerProtoNames[version]);
759 headerP->sessionID = newPCDataLong (fSessionID);
760 headerP->msgID = newPCDataString ("1");
761 headerP->target = newLocation ("/", "");
762 headerP->source = newLocation (fServerID.c_str(), "");
763 headerP->respURI = NULL__null;
764 headerP->meta = NULL__null;
765 headerP->flags = 0;
766 //TODO generate the cred element for authentication
767 headerP->cred = NULL__null;
768
769 //create SyncMessage
770 err = smlStartMessageExt (id, headerP, SmlVersionCodes[version]); if (err) break;
771 //create Alert Commands
772 //internal Alert element
773 alertP = SML_NEW (SmlAlert_t)((SmlAlert_t*) _smlMalloc(sizeof(SmlAlert_t)));
774 alertP->elementType = SML_PE_ALERT;
775 alertP->cmdID = newPCDataLong(1);
776 alertP->flags = 0;
777 alertP->data = newPCDataLong (alertCode);
778 alertP->cred = NULL__null;
779 alertP->itemList = NULL__null;
780 alertP->flags = 0;
781
782 //for each source, add a item
783 for (unsigned int num =0; num < sources.size(); num++) {
784 SmlItemPtr_t alertItemP = newItem();
785 alertItemP->source = newOptLocation (sources[num].second.c_str());
786 alertItemP->meta = newMetaType (sources[num].first.c_str());
787 addItemToList (alertItemP, &alertP->itemList);
788 }
789
790 err = smlAlertCmd (id, alertP); if (err) break;
791 err = smlEndMessage (id, true); if (err) break;
792
793 MemPtr_t buf = NULL__null;
794 err = smlLockReadBuffer (id, (MemPtr_t *) &buf, (MemSize_t *)&sanSize); if (err) break;
795 fSan = malloc( sanSize ); if (!fSan) {err = DB_Full420; break;}
796 san = fSan;
797 memcpy (san, buf, sanSize);
798 err = smlUnlockReadBuffer (id, sanSize); if (err) break;
799 } SYSYNC_CATCH (...)catch(...) {
800 if (headerP) {
801 smlFreeProtoElement (headerP);
802 headerP = NULL__null;
803 }
804 if (alertP) {
805 smlFreeProtoElement (alertP);
806 alertP = NULL__null;
807 }
808 err = DB_Full420;
809 SYSYNC_ENDCATCH}
810 } while (false);
811 if (headerP) {
812 smlFreeProtoElement (headerP);
813 }
814 if (alertP) {
815 smlFreeProtoElement (alertP);
816 }
817 if (err) return err;
818
819 err = smlTerminateInstance( id );
820 return err;
821}
822#endif
823
824} // namespace sysync
825
826// eof