Imported Upstream version 1.0beta3
[platform/upstream/syncevolution.git] / src / synthesis / src / sysync_SDK / Sources / sysync_utils.h
1 /*
2  *  File:         sysync_utils.cpp
3  *
4  *  Author:       Lukas Zeller (luz@synthesis.ch)
5  *
6  *  Provides some helper functions interfacing between SyncML Toolkit
7  *  and C++ plus other utilities
8  *
9  *  Copyright (c) 2001-2009 by Synthesis AG (www.synthesis.ch)
10  *
11  *  2001-05-16 : luz : created
12  *
13  */
14
15 #ifndef SYSYNC_UTILS_H
16 #define SYSYNC_UTILS_H
17
18 #include "sysync_globs.h"
19 // include external utils in separate files
20 #include "sysync_b64.h"
21 #include "sysync_md5.h"
22 #ifndef SYSYNC_ENGINE
23 #include "stringutil.h"
24 #endif
25 #include "lineartime.h"
26 #include "iso8601.h"
27
28 #ifndef FULLY_STANDALONE
29 #include "sysync.h"
30 #endif
31
32 #include "sml.h"
33 #include "smldevinfdtd.h"
34 #include "smlmetinfdtd.h"
35
36 namespace sysync {
37
38 #ifdef SYSYNC_TOOL
39
40 // convert between character sets
41 int charConv(int argc, const char *argv[]);
42
43 // parse RFC 2822 addr spec
44 int parse2822AddrSpec(int argc, const char *argv[]);
45
46 #endif
47
48
49 // max line size for MIME content (used while encoding and folding)
50 #define MIME_MAXLINESIZE 75
51
52
53 // supported charsets
54 typedef enum {
55   chs_unknown, // invalid
56   chs_ascii, // 7 bit ASCII-only, with nearest char conversion for umlauts etc.
57   chs_ansi,
58   chs_iso_8859_1,
59   chs_utf8,
60   chs_utf16,
61   #ifdef CHINESE_SUPPORT
62   chs_gb2312,
63   chs_cp936,
64   #endif
65   numCharSets
66 } TCharSets;
67 // Note: Char set names are defined after this enum in other files,
68 // such as MimeDirItemType
69
70
71 // supported MIME encoding types
72 typedef enum {
73   enc_none,
74   enc_7bit,
75   enc_8bit,
76   enc_binary,
77   enc_quoted_printable,
78   enc_base64, // b64 including terminating with CRLF at end
79   enc_b, // b64 without termination (as needed in RFC2047)
80   numMIMEencodings
81 } TEncodingTypes;
82
83
84
85 // line end modes
86 typedef enum {
87   lem_none, // none specified
88   lem_unix, // 0x0A
89   lem_mac,  // 0x0D
90   lem_dos,  // 0x0D 0x0A
91   lem_cstr, // as in C strings, '\n' which is 0x0A normally (but might be 0x0D on some platforms)
92   lem_filemaker, // 0x0B (filemaker tab-separated text format, CR is shown as 0x0B within fields
93   numLineEndModes
94 } TLineEndModes;
95
96 extern const char * const lineEndModeNames[numLineEndModes];
97
98
99 // literal quoting modes
100 typedef enum {
101   qm_none, // none specified
102   qm_duplsingle, // single quote must be duplicated
103   qm_dupldouble, // double quote must be duplicated
104   qm_backslash, // C-string-style escapes of CR,LF,TAB,BS,\," and ' (but no full c-string escape with \xXX etc.)
105   numQuotingModes
106 } TQuotingModes;
107
108 extern const char * const quotingModeNames[numQuotingModes];
109
110
111
112 /*
113 The value of this element SHOULD BE one of bin, bool, b64, chr, int,
114 node, null or xml. If the element type is missing, the default value is chr. If the value is
115 bin, then the format of the content is binary data. If the value is bool, then the format of
116 the content is either true or false. If the value is b64, then the format of the content
117 information is binary data that has been character encoded using the Base64 transfer
118 encoding defined by [RFC2045]. If the value is chr, then the format of the content
119 information is clear-text in the character set specified on either the transport protocol, the
120 MIME content type header or the XML prolog. If the value is int, then the format of the
121 content information is numeric text representing an unsigned integer between zero and
122 2**32-1. If the value is node, then the content represents an interior object in the
123 management tree. If the value is null, then there is no content information. This value is
124 used by some synchronization data models to delete the content, but not the presence of
125 the property. If the value is xml, then the format of the content information is XML
126 structured mark-up data.
127 */
128
129 // format types
130 typedef enum {
131   fmt_chr, // default
132   fmt_bin,
133   fmt_b64,
134   numFmtTypes
135 } TFmtTypes;
136
137 extern const char * const encodingFmtNames[numFmtTypes];
138 extern const char * const encodingFmtSyncMLNames[numFmtTypes];
139
140 extern const char * const MIMEEncodingNames[numMIMEencodings];
141 extern const char * const MIMECharSetNames[numCharSets];
142
143
144 // field (property) data types
145 typedef enum {
146   proptype_chr, // Character
147   proptype_int, // Integer
148   proptype_bool, // Boolean
149   proptype_bin, // Binary
150   proptype_datetime, // Date and time of day
151   proptype_phonenum, // Phone number
152   proptype_text, // plain text
153   proptype_unknown, // unknown
154   numPropDataTypes
155 } TPropDataTypes;
156
157 extern const char * const propDataTypeNames[numPropDataTypes];
158
159
160 // Authorization types
161 typedef enum {
162   auth_none,
163   auth_basic,
164   auth_md5,
165   numAuthTypes
166 } TAuthTypes;
167
168 extern const char * const authTypeSyncMLNames[numAuthTypes];
169 //extern const char * const authFormatNames[numAuthTypes];
170
171
172 // char that is used for non-convertible chars
173 #define INCONVERTIBLE_PLACEHOLDER '_'
174
175
176 // encoding functions
177
178 // encode binary stream and append to string
179 void appendEncoded(
180   const uInt8 *aBinary,
181   size_t aSize,
182   string &aString,
183   TEncodingTypes aEncoding,
184   sInt16 aMaxLineSize=76,
185   sInt32 aCurrLineSize=0,     // how may chars are on the first line
186   bool aSoftBreaksAsCR=false, // if set, soft breaks are not added as CRLF, but only indicated as CR
187   bool aEncodeBinary=false    // quoted printable: binary coding: both CR and LF will be
188                               // always replaced by "=0D" and "=0A"
189 );
190
191 // decode encoded data and append to string
192 const char *appendDecoded(
193   const char *aText,
194   size_t aSize,
195   string &aBinString,
196   TEncodingTypes aEncoding
197 );
198
199
200
201 // generate RFC2822-style address specificiation
202 // - Common Name will be quoted
203 // - recipient will be put in angle brackets
204 void makeRFC2822AddrSpec(
205   cAppCharP aCommonName,
206   cAppCharP aRecipient,
207   string &aRFCAddr
208 );
209
210
211 // Parse RFC2822-style address specificiation
212 // - aName will receive name and all (possible) comments
213 // - aRecipient will receive the (first, in case of a group) email address
214 cAppCharP parseRFC2822AddrSpec(
215   cAppCharP aText,
216   string &aName,
217   string &aRecipient
218 );
219
220
221 // RFC2047 encoding
222
223 // append internal UTF8 string as RFC2047 style encoding
224 const char *appendUTF8AsRFC2047(
225   const char *aText,
226   string &aString
227 );
228
229 // parse character string from RFC2047 style encoding to UTF8 internal string
230 const char *appendRFC2047AsUTF8(
231   const char *aRFC2047,
232   stringSize aSize, // max number of chars to look at
233   string &aString,
234   TLineEndModes aLEM=lem_none
235 );
236
237
238
239 // charset conversion functions
240
241 // generic bintree-based conversion functions
242 typedef uInt16 treeval_t;
243
244 typedef struct {
245   treeval_t minkey;
246   treeval_t maxkey;
247   treeval_t linksstart;
248   treeval_t linksend;
249   size_t numelems;
250   treeval_t *elements;
251 } TConvFlatTree;
252
253
254 #ifdef BINTREE_GENERATOR
255
256 typedef struct TBinTreeNode {
257   treeval_t key;
258   struct TBinTreeNode *nextHigher;
259   struct TBinTreeNode *nextLowerOrEqual;
260   treeval_t value; // valid only if links are both NULL
261 } TBinTreeNode;
262
263
264 // add a key/value pair to the binary tree
265 void addToBinTree(TBinTreeNode *&aBinTree, treeval_t aMinKey, treeval_t aMaxKey, treeval_t aKey, treeval_t aValue);
266 // dispose a bintree
267 void disposeBinTree(TBinTreeNode *&aBinTree);
268 // search directly in bintree
269 treeval_t searchBintree(TBinTreeNode *aBinTree, treeval_t aKey, treeval_t aUndefValue, treeval_t aMinKey, treeval_t aMaxKey);
270
271
272 // make a flat form representation of the bintree in a one-dimensional array
273 bool flatBinTree(
274   TBinTreeNode *aBinTree, TConvFlatTree &aFlatTree, size_t aArrSize,
275   treeval_t aMinKey, treeval_t aMaxKey, treeval_t aLinksStart, treeval_t aLinksEnd
276 );
277 #endif
278
279 // search flattened bintree for a specific key value
280 treeval_t searchFlatBintree(const TConvFlatTree &aFlatTree, treeval_t aKey, treeval_t aUndefValue);
281
282 // add byte char as UTF8 to string value and apply charset translation if needed
283 //void appendCharAsUTF8(char c, string &aVal, TCharSets aCharSet);
284 uInt16 appendCharsAsUTF8(const char *aChars, string &aVal, TCharSets aCharSet, uInt16 aNumChars=1);
285
286 // add string as UTF8 to value and apply charset translation if needed
287 // - if aLineEndChar is specified, occurrence of this will be replaced
288 //   by '\n', occurrence of non matching LF/CR will be ignored
289 void appendStringAsUTF8(
290   const char *s, string &aVal,
291   TCharSets aCharSet,
292   TLineEndModes aLEM=lem_cstr,
293   bool aAllowFilemakerCR=false // if set, 0x0B is interpreted as line end as well
294 );
295 // add UTF8 string to value in custom charset
296 // - aLEM specifies line ends to be used
297 // - aQuotingMode specifies what quoting (for ODBC literals for example) should be used
298 // - output is clipped after aMaxBytes bytes (if not 0)
299 // - returns true if all input could be converted, false if output is clipped
300 bool appendUTF8ToString(
301   cAppCharP aUTF8, string &aVal,
302   TCharSets aCharSet,
303   TLineEndModes aLEM=lem_none,
304   TQuotingModes aQuotingMode=qm_none,
305   size_t aMaxBytes=0
306 );
307 // same, but output string is cleared first
308 bool storeUTF8ToString(
309   cAppCharP aUTF8, string &aVal,
310   TCharSets aCharSet,
311   TLineEndModes aLEM=lem_none,
312   TQuotingModes aQuotingMode=qm_none,
313   size_t aMaxBytes=0
314 );
315
316
317 // convert UTF8 to UCS4
318 // - returns pointer to next char
319 // - returns UCS4=0 on error (no char, bad sequence, sequence not complete)
320 const char *UTF8toUCS4(const char *aUTF8, uInt32 &aUCS4);
321 // convert UCS4 to UTF8 (0 char is not allowed and will be ignored!)
322 void UCS4toUTF8(uInt32 aUCS4, string &aUTF8);
323
324
325 // convert UTF-16 to UCS4
326 // - returns pointer to next char
327 // - returns UCS4=0 on error (no char, bad sequence, sequence not complete)
328 const uInt16 *UTF16toUCS4(const uInt16 *aUTF16P, uInt32 &aUCS4);
329 // convert UCS4 to UTF-16
330 // - returns 0 for UNICODE range UCS4 and first word of UTF-16 for non UNICODE
331 uInt16 UCS4toUTF16(uInt32 aUCS4, uInt16 &aUTF16);
332
333
334
335 // add UTF8 string as UTF-16 byte stream to 8-bit string
336 // - if aLEM is not lem_none, occurrence of any type of Linefeeds
337 //   (LF,CR,CRLF and even CRCRLF) in input string will be
338 //   replaced by the specified line end type
339 // - output is clipped after ByteString reaches aMaxBytes size (if not 0), = approx half as many Unicode chars
340 // - returns true if all input could be converted, false if output is clipped
341 bool appendUTF8ToUTF16ByteString(
342   cAppCharP aUTF8,
343   string &aUTF16ByteString,
344   bool aBigEndian,
345   TLineEndModes aLEM=lem_none,
346   uInt32 aMaxBytes=0
347 );
348
349 // add UTF16 byte string as UTF8 to value
350 void appendUTF16AsUTF8(
351   const uInt16 *aUTF16,
352   uInt32 aNumUTF16Chars,
353   bool aBigEndian,
354   string &aVal,
355   bool aConvertLineEnds=false,
356   bool aAllowFilemakerCR=false
357 );
358
359
360 // MD5 and B64 given string
361 void MD5B64(const char *aString, sInt32 aLen, string &aMD5B64);
362
363 // format as Timestamp text, usually for logfiles
364 void StringObjTimestamp(string &aStringObj, lineartime_t aTimer);
365 // format as hex byte string
366 void StringObjHexString(string &aStringObj, const uInt8 *aBinary, uInt32 aBinSz);
367
368 // add CGI to existing URL string
369 bool addCGItoString(string &aStringObj, cAppCharP aCGI, bool noduplicate=true);
370
371 // Count bits
372 int countbits(uInt32 aMask);
373
374 // make uppercase
375 void StringUpper(string &aString);
376 // make lowercase
377 void StringLower(string &aString);
378
379 // Substitute occurences of pattern with replacement in string
380 void StringSubst(
381   string &aString, const char *aPattern, const string &aReplacement,
382   sInt32 aPatternLen,
383   TCharSets aCharSet, TLineEndModes aLEM,
384   TQuotingModes aQuotingMode
385 );
386 void StringSubst(
387   string &aString, const char *aPattern, const char *aReplacement,
388   sInt32 aPatternLen, sInt32 aReplacementLen,
389   TCharSets aCharSet=chs_unknown, TLineEndModes aLEM=lem_none,
390   TQuotingModes aQuotingMode=qm_none
391 );
392 void StringSubst(string &aString, const char *aPattern, const string &aReplacement, sInt32 aPatternLen=-1);
393 void StringSubst(string &aString, const char *aPattern, sInt32 aNumber, sInt32 aPatternLen=-1);
394 /* subst regexp
395 i\=0\; *while\(\(i\=([^.]+)\.find\(\"([^"]+)\",i\)\)\!\=string::npos\) *\{ *[^.]+\.replace\(i,([0-9]+),(.+)\)\; i\+\=.*$
396 StringSubst(\1,"\2",\4,\3);
397 */
398
399
400 // helper macro for allocation of SyncML Toolkit structures from C++ code
401 #define SML_NEW(ty) ((ty*) _smlMalloc(sizeof(ty)))
402 #define SML_FREE(m) smlLibFree(m)
403
404 // allocate memory via SyncML toolkit allocation function, but throw
405 // exception if it fails. Used by SML
406 void *_smlMalloc(MemSize_t size);
407
408 // copy PCdata contents into std::string object
409 void smlPCDataToStringObj(const SmlPcdataPtr_t aPcdataP, string &aStringObj);
410
411 // returns pointer to PCdata contents or null string. If aSizeP!=NULL, length will be stored in *aSize
412 const char *smlPCDataToCharP(const SmlPcdataPtr_t aPcdata, stringSize *aSizeP=NULL);
413
414 // returns pointer to PCdata contents if existing, NULL otherwise.
415 // If aSizeP!=NULL, length will be stored in *aSize
416 const char *smlPCDataOptToCharP(const SmlPcdataPtr_t aPcdataP, stringSize *aSizeP=NULL);
417
418 // returns item string or empty string (NEVER NULL)
419 const char *smlItemDataToCharP(const SmlItemPtr_t aItemP);
420
421 // returns first item string or empty string (NEVER NULL)
422 const char *smlFirstItemDataToCharP(const SmlItemListPtr_t aItemListP);
423
424 // split Hostname into address and port parts
425 void splitHostname(const char *aHost,string *aAddr,string *aPort);
426
427 // split URL into protocol, hostname, document name and auth-info (user, password)
428 void splitURL(const char *aURI,string *aProtocol,string *aHost,string *aDoc,string *aUser, string *aPasswd);
429
430 // returns error code made ready for SyncML sending (that is, remove offset
431 // of 10000 if present, and make generic error 500 for non-SyncML errors,
432 // and return LOCERR_OK as 200)
433 localstatus syncmlError(localstatus aErr);
434
435 // returns error code made local (that is, offset by 10000 in case aErr is a
436 // SyncML status code <10000, and convert 200 into LOCERR_OK)
437 localstatus localError(localstatus aErr);
438
439 // returns pure relative URI, if specified relative or absolute to
440 // optionally given server URI
441 const char *relativeURI(const char *aURI,const char *aServerURI=NULL);
442
443 // returns pointer to source or target LocURI
444 const char *smlSrcTargLocURIToCharP(const SmlTargetPtr_t aSrcTargP);
445
446 // returns pointer to source or target LocName
447 const char *smlSrcTargLocNameToCharP(const SmlTargetPtr_t aSrcTargP);
448
449 // returns DevInf pointer if any in specified PCData, NULL otherwise
450 SmlDevInfDevInfPtr_t smlPCDataToDevInfP(const SmlPcdataPtr_t aPCDataP);
451
452 // returns MetInf pointer if any in specified PCData, NULL otherwise
453 SmlMetInfMetInfPtr_t smlPCDataToMetInfP(const SmlPcdataPtr_t aPCDataP);
454
455 // returns true on successful conversion of PCData string to format
456 bool smlPCDataToFormat(const SmlPcdataPtr_t aPCDataP, TFmtTypes &aFmt);
457
458
459 // returns type from meta
460 const char *smlMetaTypeToCharP(SmlMetInfMetInfPtr_t aMetaP);
461
462 // returns Next Anchor from meta
463 const char *smlMetaNextAnchorToCharP(SmlMetInfMetInfPtr_t aMetaP);
464
465 // returns Last Anchor from meta
466 const char *smlMetaLastAnchorToCharP(SmlMetInfMetInfPtr_t aMetaP);
467
468
469 // build Meta anchor
470 SmlPcdataPtr_t newMetaAnchor(const char *aNextAnchor, const char *aLastAnchor=NULL);
471
472 // build Meta type
473 SmlPcdataPtr_t newMetaType(const char *aMetaType);
474
475 // build empty Meta
476 SmlPcdataPtr_t newMeta(void);
477
478 // copy meta from existing meta (for data items only
479 // anchor, mem, emi, maxobjsize, nonce are not copied!)
480 SmlPcdataPtr_t copyMeta(SmlPcdataPtr_t aOldMetaP);
481
482
483 // add an item to an item list
484 SmlItemListPtr_t *addItemToList(
485   SmlItemPtr_t aItemP, // existing item data structure, ownership is passed to list
486   SmlItemListPtr_t *aItemListPP // adress of pointer to existing item list or NULL
487 );
488
489 // add a CTData item to a CTDataList
490 SmlDevInfCTDataListPtr_t *addCTDataToList(
491   SmlDevInfCTDataPtr_t aCTDataP, // existing CTData item data structure, ownership is passed to list
492   SmlDevInfCTDataListPtr_t *aCTDataListPP // adress of pointer to existing item list or NULL
493 );
494
495 // add a CTDataProp item to a CTDataPropList
496 SmlDevInfCTDataPropListPtr_t *addCTDataPropToList(
497   SmlDevInfCTDataPropPtr_t aCTDataPropP, // existing CTDataProp item data structure, ownership is passed to list
498   SmlDevInfCTDataPropListPtr_t *aCTDataPropListPP // adress of pointer to existing item list or NULL
499 );
500
501 // add a CTData describing a property (as returned by newDevInfCTData())
502 // as a new property without parameters to a CTDataPropList
503 SmlDevInfCTDataPropListPtr_t *addNewPropToList(
504   SmlDevInfCTDataPtr_t aPropCTData, // CTData describing property
505   SmlDevInfCTDataPropListPtr_t *aCTDataPropListPP // adress of pointer to existing item list or NULL
506 );
507
508 // add PCData element to a PCData list
509 SmlPcdataListPtr_t *addPCDataToList(
510   SmlPcdataPtr_t aPCDataP, // Existing PCData element to be added, ownership is passed to list
511   SmlPcdataListPtr_t *aPCDataListPP // adress of pointer to existing PCData list or NULL
512 );
513
514 // add PCData string to a PCData list
515 SmlPcdataListPtr_t *addPCDataStringToList(
516   const char *aString, // String to be added
517   SmlPcdataListPtr_t *aPCDataListPP // adress of pointer to existing PCData list or NULL
518 );
519
520 // create new optional location (source or target)
521 SmlSourcePtr_t newOptLocation(
522   const char *aLocURI,
523   const char *aLocName=NULL
524 );
525
526 // create new location (source or target)
527 SmlSourcePtr_t newLocation(
528   const char *aLocURI,
529   const char *aLocName=NULL
530 );
531
532 // create new empty Item
533 SmlItemPtr_t newItem(void);
534
535 // create new Item with string-type data
536 SmlItemPtr_t newStringDataItem(
537   const char *aString
538 );
539
540
541 // create format PCData
542 SmlPcdataPtr_t newPCDataFormat(
543   TFmtTypes aFmtType,
544   bool aShowDefault
545 );
546
547 // create new string-type PCData, if NULL or empty string is passed for aData,
548 // NULL is returned (optional info not there)
549 SmlPcdataPtr_t newPCDataFormatted(
550   const uInt8 *aData,    // data
551   sInt32 aLength,         // length of data, if<0 then string length is calculated
552   TFmtTypes aEncType,   // encoding
553   bool aNeedsOpaque   // set opaque needed (string that could confuse XML parsing or even binary)
554 );
555
556 // create new string-type PCData, if NULL is passed for aString, NULL is returned (optional info not there)
557 SmlPcdataPtr_t newPCDataOptString(
558   const char *aString,
559   sInt32 aLength=-1 // length of string, if<0 then length is calculated
560 );
561
562 // create new string-type PCData, if NULL is passed for aString,
563 // NULL is returned (optional info not there)
564 // if empty string is passed, PCData with empty contents will be created
565 SmlPcdataPtr_t newPCDataOptEmptyString(
566   const char *aString,
567   sInt32 aLength=-1 // length of string, if<0 then length is calculated
568 );
569
570 // create new string-type PCData, if NULL is passed for aString, an empty string is created
571 SmlPcdataPtr_t newPCDataString(
572   const char *aString,
573   sInt32 aLength=-1 // length of string, if<0 then length is calculate
574 );
575
576 // create new PCData, aOpaque can be used to generate non-string data
577 SmlPcdataPtr_t newPCDataStringX(
578   const uInt8 *aString,
579   bool aOpaque=false, // if set, an opaque method (OPAQUE or CDATA) is used
580   sInt32 aLength=-1 // length of string, if<0 then length is calculate
581 );
582
583
584 // create new string-type PCData from C++ string
585 SmlPcdataPtr_t newPCDataString(const string &aString);
586
587 // create new decimal string representation of long as PCData
588 SmlPcdataPtr_t newPCDataLong(sInt32 aLong);
589
590 // returns true on successful conversion of PCData string to long
591 bool smlPCDataToLong(const SmlPcdataPtr_t aPCDataP, sInt32 &aLong);
592 bool smlPCDataToULong(const SmlPcdataPtr_t aPCDataP, uInt32 &aLong);
593
594
595 // create challenge of requested type
596 SmlChalPtr_t newChallenge(TAuthTypes aAuthType, const string &aNextNonce, bool aBinaryAllowed);
597
598 // Nonce generator allowing last-session nonce to be correctly re-generated in next session
599 void generateNonce(string &aNonce, const char *aDevStaticString, sInt32 aSessionStaticID);
600
601 // create new property or param descriptor for CTCap
602 SmlDevInfCTDataPtr_t newDevInfCTData(cAppCharP aName,uInt32 aSize=0, bool aNoTruncate=false, uInt32 aMaxOccur=0, cAppCharP aDataType=NULL);
603
604 // frees prototype element and sets calling pointer to NULL
605 void FreeProtoElement(void * &aVoidP);
606 // macro to overcome pointer reference conversion constraints
607 #ifdef PREFER_MACROS
608 #define FREEPROTOELEMENT(p) FreeProtoElement((void *&)p)
609 #else
610 template <class T> void FREEPROTOELEMENT(T *&p)
611 {
612   smlFreeProtoElement(static_cast<void *>(p));
613   p = NULL;
614 }
615 #endif
616
617 } // namespace sysync
618
619 #endif
620 // eof