2 * File: sysync_utils.cpp
4 * Author: Lukas Zeller (luz@synthesis.ch)
6 * Provides some helper functions interfacing between SyncML Toolkit
7 * and C++ plus other utilities
9 * Copyright (c) 2001-2009 by Synthesis AG (www.synthesis.ch)
11 * 2001-05-16 : luz : created
15 #ifndef SYSYNC_UTILS_H
16 #define SYSYNC_UTILS_H
18 #include "sysync_globs.h"
19 // include external utils in separate files
20 #include "sysync_b64.h"
21 #include "sysync_md5.h"
23 #include "stringutil.h"
25 #include "lineartime.h"
28 #ifndef FULLY_STANDALONE
33 #include "smldevinfdtd.h"
34 #include "smlmetinfdtd.h"
40 // convert between character sets
41 int charConv(int argc, const char *argv[]);
43 // parse RFC 2822 addr spec
44 int parse2822AddrSpec(int argc, const char *argv[]);
49 // max line size for MIME content (used while encoding and folding)
50 #define MIME_MAXLINESIZE 75
55 chs_unknown, // invalid
56 chs_ascii, // 7 bit ASCII-only, with nearest char conversion for umlauts etc.
61 #ifdef CHINESE_SUPPORT
67 // Note: Char set names are defined after this enum in other files,
68 // such as MimeDirItemType
71 // supported MIME encoding types
78 enc_base64, // b64 including terminating with CRLF at end
79 enc_b, // b64 without termination (as needed in RFC2047)
87 lem_none, // none specified
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
96 extern const char * const lineEndModeNames[numLineEndModes];
99 // literal quoting modes
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.)
108 extern const char * const quotingModeNames[numQuotingModes];
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.
137 extern const char * const encodingFmtNames[numFmtTypes];
138 extern const char * const encodingFmtSyncMLNames[numFmtTypes];
140 extern const char * const MIMEEncodingNames[numMIMEencodings];
141 extern const char * const MIMECharSetNames[numCharSets];
144 // field (property) data types
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
157 extern const char * const propDataTypeNames[numPropDataTypes];
160 // Authorization types
168 extern const char * const authTypeSyncMLNames[numAuthTypes];
169 //extern const char * const authFormatNames[numAuthTypes];
172 // char that is used for non-convertible chars
173 #define INCONVERTIBLE_PLACEHOLDER '_'
176 // encoding functions
178 // encode binary stream and append to string
180 const uInt8 *aBinary,
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"
191 // decode encoded data and append to string
192 const char *appendDecoded(
196 TEncodingTypes aEncoding
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,
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(
223 // append internal UTF8 string as RFC2047 style encoding
224 const char *appendUTF8AsRFC2047(
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
234 TLineEndModes aLEM=lem_none
239 // charset conversion functions
241 // generic bintree-based conversion functions
242 typedef uInt16 treeval_t;
247 treeval_t linksstart;
254 #ifdef BINTREE_GENERATOR
256 typedef struct TBinTreeNode {
258 struct TBinTreeNode *nextHigher;
259 struct TBinTreeNode *nextLowerOrEqual;
260 treeval_t value; // valid only if links are both NULL
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);
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);
272 // make a flat form representation of the bintree in a one-dimensional array
274 TBinTreeNode *aBinTree, TConvFlatTree &aFlatTree, size_t aArrSize,
275 treeval_t aMinKey, treeval_t aMaxKey, treeval_t aLinksStart, treeval_t aLinksEnd
279 // search flattened bintree for a specific key value
280 treeval_t searchFlatBintree(const TConvFlatTree &aFlatTree, treeval_t aKey, treeval_t aUndefValue);
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);
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,
292 TLineEndModes aLEM=lem_cstr,
293 bool aAllowFilemakerCR=false // if set, 0x0B is interpreted as line end as well
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,
303 TLineEndModes aLEM=lem_none,
304 TQuotingModes aQuotingMode=qm_none,
307 // same, but output string is cleared first
308 bool storeUTF8ToString(
309 cAppCharP aUTF8, string &aVal,
311 TLineEndModes aLEM=lem_none,
312 TQuotingModes aQuotingMode=qm_none,
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);
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);
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(
343 string &aUTF16ByteString,
345 TLineEndModes aLEM=lem_none,
349 // add UTF16 byte string as UTF8 to value
350 void appendUTF16AsUTF8(
351 const uInt16 *aUTF16,
352 uInt32 aNumUTF16Chars,
355 bool aConvertLineEnds=false,
356 bool aAllowFilemakerCR=false
360 // MD5 and B64 given string
361 void MD5B64(const char *aString, sInt32 aLen, string &aMD5B64);
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);
368 // add CGI to existing URL string
369 bool addCGItoString(string &aStringObj, cAppCharP aCGI, bool noduplicate=true);
372 int countbits(uInt32 aMask);
375 void StringUpper(string &aString);
377 void StringLower(string &aString);
379 // Substitute occurences of pattern with replacement in string
381 string &aString, const char *aPattern, const string &aReplacement,
383 TCharSets aCharSet, TLineEndModes aLEM,
384 TQuotingModes aQuotingMode
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
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);
395 i\=0\; *while\(\(i\=([^.]+)\.find\(\"([^"]+)\",i\)\)\!\=string::npos\) *\{ *[^.]+\.replace\(i,([0-9]+),(.+)\)\; i\+\=.*$
396 StringSubst(\1,"\2",\4,\3);
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)
404 // allocate memory via SyncML toolkit allocation function, but throw
405 // exception if it fails. Used by SML
406 void *_smlMalloc(MemSize_t size);
408 // copy PCdata contents into std::string object
409 void smlPCDataToStringObj(const SmlPcdataPtr_t aPcdataP, string &aStringObj);
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);
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);
418 // returns item string or empty string (NEVER NULL)
419 const char *smlItemDataToCharP(const SmlItemPtr_t aItemP);
421 // returns first item string or empty string (NEVER NULL)
422 const char *smlFirstItemDataToCharP(const SmlItemListPtr_t aItemListP);
424 // split Hostname into address and port parts
425 void splitHostname(const char *aHost,string *aAddr,string *aPort);
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);
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);
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);
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);
443 // returns pointer to source or target LocURI
444 const char *smlSrcTargLocURIToCharP(const SmlTargetPtr_t aSrcTargP);
446 // returns pointer to source or target LocName
447 const char *smlSrcTargLocNameToCharP(const SmlTargetPtr_t aSrcTargP);
449 // returns DevInf pointer if any in specified PCData, NULL otherwise
450 SmlDevInfDevInfPtr_t smlPCDataToDevInfP(const SmlPcdataPtr_t aPCDataP);
452 // returns MetInf pointer if any in specified PCData, NULL otherwise
453 SmlMetInfMetInfPtr_t smlPCDataToMetInfP(const SmlPcdataPtr_t aPCDataP);
455 // returns true on successful conversion of PCData string to format
456 bool smlPCDataToFormat(const SmlPcdataPtr_t aPCDataP, TFmtTypes &aFmt);
459 // returns type from meta
460 const char *smlMetaTypeToCharP(SmlMetInfMetInfPtr_t aMetaP);
462 // returns Next Anchor from meta
463 const char *smlMetaNextAnchorToCharP(SmlMetInfMetInfPtr_t aMetaP);
465 // returns Last Anchor from meta
466 const char *smlMetaLastAnchorToCharP(SmlMetInfMetInfPtr_t aMetaP);
470 SmlPcdataPtr_t newMetaAnchor(const char *aNextAnchor, const char *aLastAnchor=NULL);
473 SmlPcdataPtr_t newMetaType(const char *aMetaType);
476 SmlPcdataPtr_t newMeta(void);
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);
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
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
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
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
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
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
520 // create new optional location (source or target)
521 SmlSourcePtr_t newOptLocation(
523 const char *aLocName=NULL
526 // create new location (source or target)
527 SmlSourcePtr_t newLocation(
529 const char *aLocName=NULL
532 // create new empty Item
533 SmlItemPtr_t newItem(void);
535 // create new Item with string-type data
536 SmlItemPtr_t newStringDataItem(
541 // create format PCData
542 SmlPcdataPtr_t newPCDataFormat(
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)
556 // create new string-type PCData, if NULL is passed for aString, NULL is returned (optional info not there)
557 SmlPcdataPtr_t newPCDataOptString(
559 sInt32 aLength=-1 // length of string, if<0 then length is calculated
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(
567 sInt32 aLength=-1 // length of string, if<0 then length is calculated
570 // create new string-type PCData, if NULL is passed for aString, an empty string is created
571 SmlPcdataPtr_t newPCDataString(
573 sInt32 aLength=-1 // length of string, if<0 then length is calculate
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
584 // create new string-type PCData from C++ string
585 SmlPcdataPtr_t newPCDataString(const string &aString);
587 // create new decimal string representation of long as PCData
588 SmlPcdataPtr_t newPCDataLong(sInt32 aLong);
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);
595 // create challenge of requested type
596 SmlChalPtr_t newChallenge(TAuthTypes aAuthType, const string &aNextNonce, bool aBinaryAllowed);
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);
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);
604 // frees prototype element and sets calling pointer to NULL
605 void FreeProtoElement(void * &aVoidP);
606 // macro to overcome pointer reference conversion constraints
608 #define FREEPROTOELEMENT(p) FreeProtoElement((void *&)p)
610 template <class T> void FREEPROTOELEMENT(T *&p)
612 smlFreeProtoElement(static_cast<void *>(p));
617 } // namespace sysync