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