SOAPUtils.cpp 70 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373
  1. /*
  2. * Copyright 2005 - 2016 Zarafa and its licensors
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU Affero General Public License, version 3,
  6. * as published by the Free Software Foundation.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU Affero General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU Affero General Public License
  14. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. *
  16. */
  17. #include <kopano/platform.h>
  18. #include <cstring>
  19. #include <mapidefs.h>
  20. #include <mapitags.h>
  21. #include <edkmdb.h>
  22. #include <kopano/ECGuid.h>
  23. #include "kcore.hpp"
  24. #include "SOAPUtils.h"
  25. #include "SOAPAlloc.h"
  26. #include <kopano/stringutil.h>
  27. #include <kopano/ustringutil.h>
  28. using namespace std;
  29. namespace KC {
  30. /* See m4lcommon/Util.cpp for twcmp */
  31. template<typename T> static int twcmp(T a, T b)
  32. {
  33. return (a < b) ? -1 : (a == b) ? 0 : 1;
  34. }
  35. class MVPropProxy {
  36. public:
  37. MVPropProxy(struct propVal *lpMVProp): m_lpMVProp(lpMVProp)
  38. { }
  39. unsigned int size() const {
  40. if (m_lpMVProp == NULL || (PROP_TYPE(m_lpMVProp->ulPropTag) & MV_FLAG) == 0)
  41. return 0;
  42. switch (PROP_TYPE(m_lpMVProp->ulPropTag)) {
  43. case PT_MV_I2: return m_lpMVProp->Value.mvi.__size;
  44. case PT_MV_LONG: return m_lpMVProp->Value.mvl.__size;
  45. case PT_MV_R4: return m_lpMVProp->Value.mvflt.__size;
  46. case PT_MV_DOUBLE:
  47. case PT_MV_APPTIME: return m_lpMVProp->Value.mvdbl.__size;
  48. case PT_MV_I8: return m_lpMVProp->Value.mvl.__size;
  49. case PT_MV_SYSTIME:
  50. case PT_MV_CURRENCY: return m_lpMVProp->Value.mvhilo.__size;
  51. case PT_MV_CLSID:
  52. case PT_MV_BINARY: return m_lpMVProp->Value.mvbin.__size;
  53. case PT_MV_STRING8:
  54. case PT_MV_UNICODE: return m_lpMVProp->Value.mvszA.__size;
  55. default: return 0;
  56. }
  57. }
  58. ECRESULT compare(unsigned int ulIndex, const struct propVal *lpProp, const ECLocale &locale, int *lpnCompareResult)
  59. {
  60. int nCompareResult = 0;
  61. if (m_lpMVProp == NULL ||
  62. (PROP_TYPE(m_lpMVProp->ulPropTag) & MV_FLAG) == 0 ||
  63. (PROP_TYPE(m_lpMVProp->ulPropTag) & ~MV_FLAG) != PROP_TYPE(lpProp->ulPropTag) ||
  64. ulIndex >= size())
  65. return KCERR_INVALID_PARAMETER;
  66. switch (PROP_TYPE(m_lpMVProp->ulPropTag)) {
  67. case PT_MV_I2:
  68. nCompareResult = twcmp(m_lpMVProp->Value.mvi.__ptr[ulIndex], lpProp->Value.i);
  69. break;
  70. case PT_MV_LONG:
  71. nCompareResult = twcmp(m_lpMVProp->Value.mvl.__ptr[ulIndex], lpProp->Value.ul);
  72. break;
  73. case PT_MV_R4:
  74. nCompareResult = twcmp(m_lpMVProp->Value.mvflt.__ptr[ulIndex], lpProp->Value.flt);
  75. break;
  76. case PT_MV_DOUBLE:
  77. case PT_MV_APPTIME:
  78. nCompareResult = twcmp(m_lpMVProp->Value.mvdbl.__ptr[ulIndex], lpProp->Value.dbl);
  79. break;
  80. case PT_MV_I8:
  81. /* promote LHS from unsigned int to int64_t */
  82. nCompareResult = twcmp(static_cast<int64_t>(m_lpMVProp->Value.mvl.__ptr[ulIndex]), lpProp->Value.li);
  83. break;
  84. case PT_MV_SYSTIME:
  85. case PT_MV_CURRENCY:
  86. if (m_lpMVProp->Value.mvhilo.__ptr[ulIndex].hi == lpProp->Value.hilo->hi)
  87. nCompareResult = twcmp(m_lpMVProp->Value.mvhilo.__ptr[ulIndex].lo, lpProp->Value.hilo->lo);
  88. else
  89. nCompareResult = twcmp(m_lpMVProp->Value.mvhilo.__ptr[ulIndex].hi, lpProp->Value.hilo->hi);
  90. break;
  91. case PT_MV_CLSID:
  92. case PT_MV_BINARY:
  93. nCompareResult = twcmp(m_lpMVProp->Value.mvbin.__ptr[ulIndex].__size, lpProp->Value.bin->__size);
  94. if (nCompareResult == 0)
  95. nCompareResult = memcmp(m_lpMVProp->Value.mvbin.__ptr[ulIndex].__ptr, lpProp->Value.bin->__ptr, lpProp->Value.bin->__size);
  96. break;
  97. case PT_MV_STRING8:
  98. case PT_MV_UNICODE:
  99. if (m_lpMVProp->Value.mvszA.__ptr[ulIndex] == NULL && lpProp->Value.lpszA != NULL)
  100. nCompareResult = 1;
  101. else if (m_lpMVProp->Value.mvszA.__ptr[ulIndex] != NULL && lpProp->Value.lpszA == NULL)
  102. nCompareResult = -1;
  103. else
  104. nCompareResult = u8_icompare(m_lpMVProp->Value.mvszA.__ptr[ulIndex], lpProp->Value.lpszA, locale);
  105. break;
  106. default:
  107. return KCERR_INVALID_PARAMETER;
  108. }
  109. *lpnCompareResult = nCompareResult;
  110. return erSuccess;
  111. }
  112. private:
  113. struct propVal *m_lpMVProp;
  114. };
  115. void FreeSortOrderArray(struct sortOrderArray *lpsSortOrder)
  116. {
  117. if(lpsSortOrder == NULL)
  118. return;
  119. s_free(nullptr, lpsSortOrder->__ptr);
  120. s_free(nullptr, lpsSortOrder);
  121. }
  122. int CompareSortOrderArray(const struct sortOrderArray *lpsSortOrder1,
  123. const struct sortOrderArray *lpsSortOrder2)
  124. {
  125. if(lpsSortOrder1 == NULL && lpsSortOrder2 == NULL)
  126. return 0; // both NULL
  127. if(lpsSortOrder1 == NULL || lpsSortOrder2 == NULL)
  128. return -1; // not equal due to one of them being NULL
  129. if(lpsSortOrder1->__size != lpsSortOrder2->__size)
  130. return twcmp(lpsSortOrder1->__size, lpsSortOrder2->__size);
  131. for (gsoap_size_t i = 0; i < lpsSortOrder1->__size; ++i) {
  132. if(lpsSortOrder1->__ptr[i].ulPropTag != lpsSortOrder2->__ptr[i].ulPropTag)
  133. return -1;
  134. if(lpsSortOrder1->__ptr[i].ulOrder != lpsSortOrder2->__ptr[i].ulOrder)
  135. return -1;
  136. }
  137. // Exact match
  138. return 0;
  139. }
  140. ECRESULT CopyPropTagArray(struct soap *soap,
  141. const struct propTagArray *lpPTsSrc, struct propTagArray **lppsPTsDst)
  142. {
  143. struct propTagArray* lpPTsDst = NULL;
  144. if (lppsPTsDst == NULL || lpPTsSrc == NULL)
  145. return KCERR_INVALID_PARAMETER;
  146. lpPTsDst = s_alloc<struct propTagArray>(soap);
  147. lpPTsDst->__size = lpPTsSrc->__size;
  148. if(lpPTsSrc->__size > 0) {
  149. lpPTsDst->__ptr = s_alloc<unsigned int>(soap, lpPTsSrc->__size );
  150. memcpy(lpPTsDst->__ptr, lpPTsSrc->__ptr, sizeof(unsigned int) * lpPTsSrc->__size);
  151. } else {
  152. lpPTsDst->__ptr = NULL;
  153. }
  154. *lppsPTsDst = lpPTsDst;
  155. return erSuccess;
  156. }
  157. void FreePropTagArray(struct propTagArray *lpsPropTags, bool bFreeBase)
  158. {
  159. if(lpsPropTags == NULL)
  160. return;
  161. s_free(nullptr, lpsPropTags->__ptr);
  162. if(bFreeBase)
  163. s_free(nullptr, lpsPropTags);
  164. }
  165. /**
  166. * Finds a specific property tag in a soap propValArray.
  167. *
  168. * @param[in] lpPropValArray SOAP propValArray
  169. * @param[in] ulPropTagq Property to search for in array, type may also be PT_UNSPECIFIED to find the first match on the PROP_ID
  170. * @return propVal* Direct pointer into the propValArray where the found property is, or NULL if not found.
  171. */
  172. struct propVal *FindProp(const struct propValArray *lpPropValArray,
  173. unsigned int ulPropTag)
  174. {
  175. if (lpPropValArray == NULL)
  176. return NULL;
  177. for (gsoap_size_t i = 0; i < lpPropValArray->__size; ++i) {
  178. if (lpPropValArray->__ptr[i].ulPropTag == ulPropTag ||
  179. (PROP_TYPE(ulPropTag) == PT_UNSPECIFIED && PROP_ID(lpPropValArray->__ptr[i].ulPropTag) == PROP_ID(ulPropTag)))
  180. return &lpPropValArray->__ptr[i];
  181. }
  182. return NULL;
  183. }
  184. /*
  185. this function check if the right proptag with the value and is't null
  186. */
  187. static ECRESULT PropCheck(const struct propVal *lpProp)
  188. {
  189. ECRESULT er = erSuccess;
  190. if(lpProp == NULL)
  191. return KCERR_INVALID_PARAMETER;
  192. switch(PROP_TYPE(lpProp->ulPropTag))
  193. {
  194. case PT_I2:
  195. if(lpProp->__union != SOAP_UNION_propValData_i)
  196. er = KCERR_INVALID_PARAMETER;
  197. break;
  198. case PT_LONG:
  199. if(lpProp->__union != SOAP_UNION_propValData_ul)
  200. er = KCERR_INVALID_PARAMETER;
  201. break;
  202. case PT_R4:
  203. if(lpProp->__union != SOAP_UNION_propValData_flt)
  204. er = KCERR_INVALID_PARAMETER;
  205. break;
  206. case PT_BOOLEAN:
  207. if(lpProp->__union != SOAP_UNION_propValData_b)
  208. er = KCERR_INVALID_PARAMETER;
  209. break;
  210. case PT_DOUBLE:
  211. if(lpProp->__union != SOAP_UNION_propValData_dbl)
  212. er = KCERR_INVALID_PARAMETER;
  213. break;
  214. case PT_APPTIME:
  215. if(lpProp->__union != SOAP_UNION_propValData_dbl)
  216. er = KCERR_INVALID_PARAMETER;
  217. break;
  218. case PT_I8:
  219. if(lpProp->__union != SOAP_UNION_propValData_li)
  220. er = KCERR_INVALID_PARAMETER;
  221. break;
  222. case PT_SYSTIME:
  223. if(lpProp->__union != SOAP_UNION_propValData_hilo)
  224. er = KCERR_INVALID_PARAMETER;
  225. break;
  226. case PT_CURRENCY:
  227. if(lpProp->__union != SOAP_UNION_propValData_hilo)
  228. er = KCERR_INVALID_PARAMETER;
  229. break;
  230. case PT_UNICODE:
  231. if(lpProp->__union != SOAP_UNION_propValData_lpszA)
  232. er = KCERR_INVALID_PARAMETER;
  233. break;
  234. case PT_STRING8:
  235. if(lpProp->__union != SOAP_UNION_propValData_lpszA)
  236. er = KCERR_INVALID_PARAMETER;
  237. else {
  238. if(lpProp->Value.lpszA == NULL)
  239. er = KCERR_INVALID_PARAMETER;
  240. else
  241. er = erSuccess;
  242. }
  243. break;
  244. case PT_BINARY:
  245. if(lpProp->__union != SOAP_UNION_propValData_bin)
  246. er = KCERR_INVALID_PARAMETER;
  247. else {
  248. if(lpProp->Value.bin->__size > 0)
  249. {
  250. if(lpProp->Value.bin->__ptr == NULL)
  251. er = KCERR_INVALID_PARAMETER;
  252. }
  253. }
  254. break;
  255. case PT_CLSID:
  256. if(lpProp->__union != SOAP_UNION_propValData_bin)
  257. er = KCERR_INVALID_PARAMETER;
  258. else {
  259. if(lpProp->Value.bin->__size > 0)
  260. {
  261. if(lpProp->Value.bin->__ptr == NULL || (lpProp->Value.bin->__size%sizeof(GUID)) != 0)
  262. er = KCERR_INVALID_PARAMETER;
  263. }
  264. }
  265. break;
  266. // TODO: check __ptr pointers?
  267. case PT_MV_DOUBLE:
  268. case PT_MV_APPTIME:
  269. if(lpProp->__union != SOAP_UNION_propValData_mvdbl)
  270. er = KCERR_INVALID_PARAMETER;
  271. break;
  272. case PT_MV_CLSID:
  273. case PT_MV_BINARY:
  274. if(lpProp->__union != SOAP_UNION_propValData_mvbin)
  275. er = KCERR_INVALID_PARAMETER;
  276. break;
  277. case PT_MV_SYSTIME:
  278. case PT_MV_CURRENCY:
  279. if(lpProp->__union != SOAP_UNION_propValData_mvhilo)
  280. er = KCERR_INVALID_PARAMETER;
  281. break;
  282. case PT_MV_FLOAT:
  283. if(lpProp->__union != SOAP_UNION_propValData_mvflt)
  284. er = KCERR_INVALID_PARAMETER;
  285. break;
  286. case PT_MV_I2:
  287. if(lpProp->__union != SOAP_UNION_propValData_mvi)
  288. er = KCERR_INVALID_PARAMETER;
  289. break;
  290. case PT_MV_I8:
  291. if(lpProp->__union != SOAP_UNION_propValData_mvli)
  292. er = KCERR_INVALID_PARAMETER;
  293. break;
  294. case PT_MV_LONG:
  295. if(lpProp->__union != SOAP_UNION_propValData_mvl)
  296. er = KCERR_INVALID_PARAMETER;
  297. break;
  298. case PT_MV_UNICODE:
  299. case PT_MV_STRING8:
  300. if(lpProp->__union != SOAP_UNION_propValData_mvszA)
  301. er = KCERR_INVALID_PARAMETER;
  302. break;
  303. case PT_ACTIONS:
  304. if(lpProp->__union != SOAP_UNION_propValData_actions)
  305. er = KCERR_INVALID_PARAMETER;
  306. break;
  307. case PT_SRESTRICTION:
  308. if(lpProp->__union != SOAP_UNION_propValData_res)
  309. er = KCERR_INVALID_PARAMETER;
  310. break;
  311. default:
  312. er = erSuccess;
  313. break;
  314. }
  315. return er;
  316. }
  317. static ECRESULT CompareABEID(const struct propVal *lpProp1,
  318. const struct propVal *lpProp2, int *lpCompareResult)
  319. {
  320. ECRESULT er = erSuccess;
  321. int iResult = 0;
  322. assert(lpProp1 != NULL && PROP_TYPE(lpProp1->ulPropTag) == PT_BINARY);
  323. assert(lpProp2 != NULL && PROP_TYPE(lpProp2->ulPropTag) == PT_BINARY);
  324. assert(lpCompareResult != NULL);
  325. auto peid1 = reinterpret_cast<const ABEID *>(lpProp1->Value.bin->__ptr);
  326. auto peid2 = reinterpret_cast<const ABEID *>(lpProp2->Value.bin->__ptr);
  327. if (memcmp(&peid1->guid, &MUIDECSAB, sizeof(GUID)) || memcmp(&peid2->guid, &MUIDECSAB, sizeof(GUID))) {
  328. er = KCERR_INVALID_PARAMETER;
  329. goto exit;
  330. }
  331. if (peid1->ulVersion == peid2->ulVersion) {
  332. if (lpProp1->Value.bin->__size != lpProp2->Value.bin->__size)
  333. iResult = twcmp(lpProp1->Value.bin->__size, lpProp2->Value.bin->__size);
  334. else if (peid1->ulVersion == 0)
  335. iResult = twcmp(peid1->ulId, peid2->ulId);
  336. else
  337. iResult = strcmp((const char *)peid1->szExId, (const char *)peid2->szExId);
  338. } else {
  339. /**
  340. * Different ABEID version, so check on the legacy ulId field. This implies that
  341. * when a V0 ABEID is stored somewhere in the database, and the server was upgraded and
  342. * an additional server was added, that the comparison will yield invalid results as
  343. * we're not allowed to compare the legacy field cross server.
  344. **/
  345. iResult = (int)(peid1->ulId - peid2->ulId);
  346. }
  347. if (iResult == 0)
  348. iResult = (int)(peid1->ulType - peid2->ulType);
  349. exit:
  350. *lpCompareResult = iResult;
  351. return er;
  352. }
  353. ECRESULT CompareProp(const struct propVal *lpProp1,
  354. const struct propVal *lpProp2, const ECLocale &locale,
  355. int *lpCompareResult)
  356. {
  357. ECRESULT er = erSuccess;
  358. int nCompareResult = 0;
  359. unsigned int ulPropTag1;
  360. unsigned int ulPropTag2;
  361. // List of prperties that get special treatment
  362. static const struct {
  363. ULONG ulPropTag;
  364. ECRESULT (*lpfnComparer)(const struct propVal *, const struct propVal *, int *);
  365. } sSpecials[] = {
  366. {PR_ADDRESS_BOOK_ENTRYID, &CompareABEID},
  367. };
  368. if (lpProp1 == NULL || lpProp2 == NULL || lpCompareResult == NULL)
  369. return KCERR_INVALID_PARAMETER;
  370. ulPropTag1 = NormalizePropTag(lpProp1->ulPropTag);
  371. ulPropTag2 = NormalizePropTag(lpProp2->ulPropTag);
  372. if (PROP_TYPE(ulPropTag1) != PROP_TYPE(ulPropTag2))
  373. // Treat this as equal
  374. return KCERR_INVALID_PARAMETER;
  375. // check soap union types and null pointers
  376. if (PropCheck(lpProp1) != erSuccess || PropCheck(lpProp2) != erSuccess)
  377. return KCERR_INVALID_PARAMETER;
  378. // First check if the any of the properties is in the sSpecials list
  379. for (size_t x = 0; x < ARRAY_SIZE(sSpecials); ++x) {
  380. bool special = lpProp1->ulPropTag == sSpecials[x].ulPropTag && PROP_TYPE(lpProp2->ulPropTag) == PROP_TYPE(sSpecials[x].ulPropTag);
  381. special |= PROP_TYPE(lpProp1->ulPropTag) == PROP_TYPE(sSpecials[x].ulPropTag) && lpProp2->ulPropTag == sSpecials[x].ulPropTag;
  382. if (!special)
  383. continue;
  384. er = sSpecials[x].lpfnComparer(lpProp1, lpProp2, &nCompareResult);
  385. if (er == erSuccess)
  386. goto skip_check;
  387. er = erSuccess;
  388. break;
  389. }
  390. // Perform a regular comparison
  391. switch(PROP_TYPE(lpProp1->ulPropTag)) {
  392. case PT_I2:
  393. nCompareResult = twcmp(lpProp1->Value.i, lpProp2->Value.i);
  394. break;
  395. case PT_LONG:
  396. if(lpProp1->Value.ul == lpProp2->Value.ul)
  397. nCompareResult = 0;
  398. else if(lpProp1->Value.ul < lpProp2->Value.ul)
  399. nCompareResult = -1;
  400. else
  401. nCompareResult = 1;
  402. break;
  403. case PT_R4:
  404. if(lpProp1->Value.flt == lpProp2->Value.flt)
  405. nCompareResult = 0;
  406. else if(lpProp1->Value.flt < lpProp2->Value.flt)
  407. nCompareResult = -1;
  408. else
  409. nCompareResult = 1;
  410. break;
  411. case PT_BOOLEAN:
  412. nCompareResult = twcmp(lpProp1->Value.b, lpProp2->Value.b);
  413. break;
  414. case PT_DOUBLE:
  415. case PT_APPTIME:
  416. if(lpProp1->Value.dbl == lpProp2->Value.dbl)
  417. nCompareResult = 0;
  418. else if(lpProp1->Value.dbl < lpProp2->Value.dbl)
  419. nCompareResult = -1;
  420. else
  421. nCompareResult = 1;
  422. break;
  423. case PT_I8:
  424. if(lpProp1->Value.li == lpProp2->Value.li)
  425. nCompareResult = 0;
  426. else if(lpProp1->Value.li < lpProp2->Value.li)
  427. nCompareResult = -1;
  428. else
  429. nCompareResult = 1;
  430. break;
  431. case PT_UNICODE:
  432. case PT_STRING8:
  433. if (lpProp1->Value.lpszA && lpProp2->Value.lpszA)
  434. if(PROP_ID(lpProp2->ulPropTag) == PROP_ID(PR_ANR))
  435. nCompareResult = u8_istartswith(lpProp1->Value.lpszA, lpProp2->Value.lpszA, locale);
  436. else
  437. nCompareResult = u8_icompare(lpProp1->Value.lpszA, lpProp2->Value.lpszA, locale);
  438. else
  439. nCompareResult = lpProp1->Value.lpszA != lpProp2->Value.lpszA;
  440. break;
  441. case PT_SYSTIME:
  442. case PT_CURRENCY:
  443. if(lpProp1->Value.hilo->hi == lpProp2->Value.hilo->hi && lpProp1->Value.hilo->lo < lpProp2->Value.hilo->lo)
  444. nCompareResult = -1;
  445. else if(lpProp1->Value.hilo->hi == lpProp2->Value.hilo->hi && lpProp1->Value.hilo->lo > lpProp2->Value.hilo->lo)
  446. nCompareResult = 1;
  447. else
  448. nCompareResult = twcmp(lpProp1->Value.hilo->hi, lpProp2->Value.hilo->hi);
  449. break;
  450. case PT_BINARY:
  451. case PT_CLSID:
  452. if (lpProp1->Value.bin->__ptr && lpProp2->Value.bin->__ptr &&
  453. lpProp1->Value.bin->__size && lpProp2->Value.bin->__size &&
  454. lpProp1->Value.bin->__size == lpProp2->Value.bin->__size)
  455. nCompareResult = memcmp(lpProp1->Value.bin->__ptr, lpProp2->Value.bin->__ptr, lpProp1->Value.bin->__size);
  456. else
  457. nCompareResult = twcmp(lpProp1->Value.bin->__size, lpProp2->Value.bin->__size);
  458. break;
  459. case PT_MV_I2:
  460. if (lpProp1->Value.mvi.__size == lpProp2->Value.mvi.__size) {
  461. for (gsoap_size_t i = 0; i < lpProp1->Value.mvi.__size; ++i) {
  462. nCompareResult = twcmp(lpProp1->Value.mvi.__ptr[i], lpProp2->Value.mvi.__ptr[i]);
  463. if(nCompareResult != 0)
  464. break;
  465. }
  466. } else
  467. nCompareResult = twcmp(lpProp1->Value.mvi.__size, lpProp2->Value.mvi.__size);
  468. break;
  469. case PT_MV_LONG:
  470. if (lpProp1->Value.mvl.__size == lpProp2->Value.mvl.__size) {
  471. for (gsoap_size_t i = 0; i < lpProp1->Value.mvl.__size; ++i) {
  472. if(lpProp1->Value.mvl.__ptr[i] == lpProp2->Value.mvl.__ptr[i])
  473. nCompareResult = 0;
  474. else if(lpProp1->Value.mvl.__ptr[i] < lpProp2->Value.mvl.__ptr[i])
  475. nCompareResult = -1;
  476. else
  477. nCompareResult = 1;
  478. if(nCompareResult != 0)
  479. break;
  480. }
  481. } else
  482. nCompareResult = twcmp(lpProp1->Value.mvl.__size, lpProp2->Value.mvl.__size);
  483. break;
  484. case PT_MV_R4:
  485. if (lpProp1->Value.mvflt.__size == lpProp2->Value.mvflt.__size) {
  486. for (gsoap_size_t i = 0; i < lpProp1->Value.mvflt.__size; ++i) {
  487. if(lpProp1->Value.mvflt.__ptr[i] == lpProp2->Value.mvflt.__ptr[i])
  488. nCompareResult = 0;
  489. else if(lpProp1->Value.mvflt.__ptr[i] < lpProp2->Value.mvflt.__ptr[i])
  490. nCompareResult = -1;
  491. else
  492. nCompareResult = 1;
  493. if(nCompareResult != 0)
  494. break;
  495. }
  496. } else
  497. nCompareResult = twcmp(lpProp1->Value.mvflt.__size, lpProp2->Value.mvflt.__size);
  498. break;
  499. case PT_MV_DOUBLE:
  500. case PT_MV_APPTIME:
  501. if (lpProp1->Value.mvdbl.__size == lpProp2->Value.mvdbl.__size) {
  502. for (gsoap_size_t i = 0; i < lpProp1->Value.mvdbl.__size; ++i) {
  503. if(lpProp1->Value.mvdbl.__ptr[i] == lpProp2->Value.mvdbl.__ptr[i])
  504. nCompareResult = 0;
  505. else if(lpProp1->Value.mvdbl.__ptr[i] < lpProp2->Value.mvdbl.__ptr[i])
  506. nCompareResult = -1;
  507. else
  508. nCompareResult = 1;
  509. if(nCompareResult != 0)
  510. break;
  511. }
  512. } else
  513. nCompareResult = twcmp(lpProp1->Value.mvdbl.__size, lpProp2->Value.mvdbl.__size);
  514. break;
  515. case PT_MV_I8:
  516. if (lpProp1->Value.mvli.__size == lpProp2->Value.mvli.__size) {
  517. for (gsoap_size_t i = 0; i < lpProp1->Value.mvli.__size; ++i) {
  518. if(lpProp1->Value.mvli.__ptr[i] == lpProp2->Value.mvli.__ptr[i])
  519. nCompareResult = 0;
  520. else if(lpProp1->Value.mvli.__ptr[i] < lpProp2->Value.mvli.__ptr[i])
  521. nCompareResult = -1;
  522. else
  523. nCompareResult = 1;
  524. if(nCompareResult != 0)
  525. break;
  526. }
  527. } else
  528. nCompareResult = twcmp(lpProp1->Value.mvli.__size, lpProp2->Value.mvli.__size);
  529. break;
  530. case PT_MV_SYSTIME:
  531. case PT_MV_CURRENCY:
  532. if (lpProp1->Value.mvhilo.__size == lpProp2->Value.mvhilo.__size) {
  533. for (gsoap_size_t i = 0; i < lpProp1->Value.mvhilo.__size; ++i) {
  534. if(lpProp1->Value.mvhilo.__ptr[i].hi == lpProp2->Value.mvhilo.__ptr[i].hi && lpProp1->Value.mvhilo.__ptr[i].lo < lpProp2->Value.mvhilo.__ptr[i].lo)
  535. nCompareResult = -1;
  536. else if(lpProp1->Value.mvhilo.__ptr[i].hi == lpProp2->Value.mvhilo.__ptr[i].hi && lpProp1->Value.mvhilo.__ptr[i].lo > lpProp2->Value.mvhilo.__ptr[i].lo)
  537. nCompareResult = 1;
  538. else
  539. nCompareResult = twcmp(lpProp1->Value.mvhilo.__ptr[i].hi, lpProp2->Value.mvhilo.__ptr[i].hi);
  540. if(nCompareResult != 0)
  541. break;
  542. }
  543. } else
  544. nCompareResult = lpProp1->Value.mvhilo.__size == lpProp2->Value.mvhilo.__size;
  545. break;
  546. case PT_MV_CLSID:
  547. case PT_MV_BINARY:
  548. if (lpProp1->Value.mvbin.__size == lpProp2->Value.mvbin.__size) {
  549. for (gsoap_size_t i = 0; i < lpProp1->Value.mvbin.__size; ++i) {
  550. if(lpProp1->Value.mvbin.__ptr[i].__ptr && lpProp2->Value.mvbin.__ptr[i].__ptr &&
  551. lpProp1->Value.mvbin.__ptr[i].__size && lpProp2->Value.mvbin.__ptr[i].__size &&
  552. lpProp1->Value.mvbin.__ptr[i].__size == lpProp2->Value.mvbin.__ptr[i].__size)
  553. nCompareResult = memcmp(lpProp1->Value.mvbin.__ptr[i].__ptr, lpProp2->Value.mvbin.__ptr[i].__ptr, lpProp1->Value.mvbin.__ptr[i].__size);
  554. else
  555. nCompareResult = twcmp(lpProp1->Value.mvbin.__ptr[i].__size, lpProp2->Value.mvbin.__ptr[i].__size);
  556. if(nCompareResult != 0)
  557. break;
  558. }
  559. } else
  560. nCompareResult = twcmp(lpProp1->Value.mvbin.__size, lpProp2->Value.mvbin.__size);
  561. break;
  562. case PT_MV_STRING8:
  563. case PT_MV_UNICODE:
  564. if (lpProp1->Value.mvszA.__size == lpProp2->Value.mvszA.__size) {
  565. for (gsoap_size_t i = 0; i < lpProp1->Value.mvszA.__size; ++i) {
  566. if (lpProp1->Value.mvszA.__ptr[i] && lpProp2->Value.mvszA.__ptr[i])
  567. nCompareResult =u8_icompare(lpProp1->Value.mvszA.__ptr[i], lpProp2->Value.mvszA.__ptr[i], locale);
  568. else
  569. nCompareResult = lpProp1->Value.mvszA.__ptr[i] != lpProp2->Value.mvszA.__ptr[i];
  570. if(nCompareResult != 0)
  571. break;
  572. }
  573. } else
  574. nCompareResult = twcmp(lpProp1->Value.mvszA.__size, lpProp2->Value.mvszA.__size);
  575. break;
  576. default:
  577. return KCERR_INVALID_PARAMETER;
  578. }
  579. skip_check:
  580. *lpCompareResult = nCompareResult;
  581. return er;
  582. }
  583. /**
  584. * ulType is one of the RELOP_xx types. The result returned will indicate that at least one of the values in lpMVProp positively
  585. * matched the RELOP_xx comparison with lpProp2.
  586. **/
  587. ECRESULT CompareMVPropWithProp(struct propVal *lpMVProp1,
  588. const struct propVal *lpProp2, unsigned int ulType, const ECLocale &locale,
  589. bool *lpfMatch)
  590. {
  591. ECRESULT er;
  592. int nCompareResult = -1; // Default, Don't change this to 0
  593. bool fMatch = false;
  594. MVPropProxy pxyMVProp1(lpMVProp1);
  595. if (lpMVProp1 == NULL || lpProp2 == NULL || lpfMatch == NULL)
  596. return KCERR_INVALID_PARAMETER;
  597. if ((PROP_TYPE(lpMVProp1->ulPropTag) & ~MV_FLAG) != PROP_TYPE(lpProp2->ulPropTag))
  598. // Treat this as equal
  599. return KCERR_INVALID_PARAMETER;
  600. // check soap union types and null pointers
  601. if (PropCheck(lpMVProp1) != erSuccess || PropCheck(lpProp2) != erSuccess)
  602. return KCERR_INVALID_PARAMETER;
  603. for (unsigned int i = 0; !fMatch && i < pxyMVProp1.size(); ++i) {
  604. er = pxyMVProp1.compare(i, lpProp2, locale, &nCompareResult);
  605. if (er != erSuccess)
  606. return er;
  607. switch(ulType) {
  608. case RELOP_GE:
  609. fMatch = nCompareResult >= 0;
  610. break;
  611. case RELOP_GT:
  612. fMatch = nCompareResult > 0;
  613. break;
  614. case RELOP_LE:
  615. fMatch = nCompareResult <= 0;
  616. break;
  617. case RELOP_LT:
  618. fMatch = nCompareResult < 0;
  619. break;
  620. case RELOP_NE:
  621. fMatch = nCompareResult != 0;
  622. break;
  623. case RELOP_RE:
  624. fMatch = false; // FIXME ?? how should this work ??
  625. break;
  626. case RELOP_EQ:
  627. fMatch = nCompareResult == 0;
  628. break;
  629. }
  630. }
  631. *lpfMatch = fMatch;
  632. return erSuccess;
  633. }
  634. size_t PropSize(const struct propVal *lpProp)
  635. {
  636. size_t ulSize;
  637. if(lpProp == NULL)
  638. return 0;
  639. switch(PROP_TYPE(lpProp->ulPropTag)) {
  640. case PT_I2:
  641. return 2;
  642. case PT_BOOLEAN:
  643. case PT_R4:
  644. case PT_LONG:
  645. return 4;
  646. case PT_APPTIME:
  647. case PT_DOUBLE:
  648. case PT_I8:
  649. return 8;
  650. case PT_UNICODE:
  651. case PT_STRING8:
  652. return lpProp->Value.lpszA ? strlen(lpProp->Value.lpszA) : 0;
  653. case PT_SYSTIME:
  654. case PT_CURRENCY:
  655. return 8;
  656. case PT_BINARY:
  657. case PT_CLSID:
  658. return lpProp->Value.bin ? lpProp->Value.bin->__size : 0;
  659. case PT_MV_I2:
  660. return 2 * lpProp->Value.mvi.__size;
  661. case PT_MV_R4:
  662. return 4 * lpProp->Value.mvflt.__size;
  663. case PT_MV_LONG:
  664. return 4 * lpProp->Value.mvl.__size;
  665. case PT_MV_APPTIME:
  666. case PT_MV_DOUBLE:
  667. return 8 * lpProp->Value.mvdbl.__size;
  668. case PT_MV_I8:
  669. return 8 * lpProp->Value.mvli.__size;
  670. case PT_MV_UNICODE:
  671. case PT_MV_STRING8:
  672. ulSize = 0;
  673. for (gsoap_size_t i = 0; i < lpProp->Value.mvszA.__size; ++i)
  674. ulSize += lpProp->Value.mvszA.__ptr[i] ? strlen(lpProp->Value.mvszA.__ptr[i]) : 0;
  675. return ulSize;
  676. case PT_MV_SYSTIME:
  677. case PT_MV_CURRENCY:
  678. return 8 * lpProp->Value.mvhilo.__size;
  679. case PT_MV_BINARY:
  680. case PT_MV_CLSID:
  681. ulSize = 0;
  682. for (gsoap_size_t i = 0; i < lpProp->Value.mvbin.__size; ++i)
  683. ulSize+= lpProp->Value.mvbin.__ptr[i].__size;
  684. return ulSize;
  685. default:
  686. return 0;
  687. }
  688. }
  689. ECRESULT FreePropVal(struct propVal *lpProp, bool bBasePointerDel)
  690. {
  691. ECRESULT er = erSuccess;
  692. if(lpProp == NULL)
  693. return er;
  694. switch(PROP_TYPE(lpProp->ulPropTag)) {
  695. case PT_I2:
  696. case PT_LONG:
  697. case PT_R4:
  698. case PT_BOOLEAN:
  699. case PT_DOUBLE:
  700. case PT_APPTIME:
  701. case PT_I8:
  702. // no extra cleanup needed
  703. break;
  704. case PT_SYSTIME:
  705. case PT_CURRENCY:
  706. s_free(nullptr, lpProp->Value.hilo);
  707. break;
  708. case PT_STRING8:
  709. case PT_UNICODE:
  710. s_free(nullptr, lpProp->Value.lpszA);
  711. break;
  712. case PT_CLSID:
  713. case PT_BINARY:
  714. if (lpProp->Value.bin) {
  715. s_free(nullptr, lpProp->Value.bin->__ptr);
  716. s_free(nullptr, lpProp->Value.bin);
  717. }
  718. break;
  719. case PT_MV_I2:
  720. s_free(nullptr, lpProp->Value.mvi.__ptr);
  721. break;
  722. case PT_MV_LONG:
  723. s_free(nullptr, lpProp->Value.mvl.__ptr);
  724. break;
  725. case PT_MV_R4:
  726. s_free(nullptr, lpProp->Value.mvflt.__ptr);
  727. break;
  728. case PT_MV_DOUBLE:
  729. case PT_MV_APPTIME:
  730. s_free(nullptr, lpProp->Value.mvdbl.__ptr);
  731. break;
  732. case PT_MV_I8:
  733. s_free(nullptr, lpProp->Value.mvli.__ptr);
  734. break;
  735. case PT_MV_SYSTIME:
  736. case PT_MV_CURRENCY:
  737. s_free(nullptr, lpProp->Value.mvhilo.__ptr);
  738. break;
  739. case PT_MV_CLSID:
  740. case PT_MV_BINARY:
  741. if(lpProp->Value.mvbin.__ptr)
  742. {
  743. for (gsoap_size_t i = 0; i < lpProp->Value.mvbin.__size; ++i)
  744. s_free(nullptr, lpProp->Value.mvbin.__ptr[i].__ptr);
  745. s_free(nullptr, lpProp->Value.mvbin.__ptr);
  746. }
  747. break;
  748. case PT_MV_STRING8:
  749. case PT_MV_UNICODE:
  750. if(lpProp->Value.mvszA.__ptr)
  751. {
  752. for (gsoap_size_t i = 0; i < lpProp->Value.mvszA.__size; ++i)
  753. s_free(nullptr, lpProp->Value.mvszA.__ptr[i]);
  754. s_free(nullptr, lpProp->Value.mvszA.__ptr);
  755. }
  756. break;
  757. case PT_SRESTRICTION:
  758. if(lpProp->Value.res)
  759. FreeRestrictTable(lpProp->Value.res);
  760. break;
  761. case PT_ACTIONS:
  762. if(lpProp->Value.actions) {
  763. struct actions *lpActions = lpProp->Value.actions;
  764. for (gsoap_size_t i = 0; i < lpActions->__size; ++i) {
  765. struct action *lpAction = &lpActions->__ptr[i];
  766. switch(lpAction->acttype) {
  767. case OP_COPY:
  768. case OP_MOVE:
  769. s_free(nullptr, lpAction->act.moveCopy.store.__ptr);
  770. s_free(nullptr, lpAction->act.moveCopy.folder.__ptr);
  771. break;
  772. case OP_REPLY:
  773. case OP_OOF_REPLY:
  774. s_free(nullptr, lpAction->act.reply.message.__ptr);
  775. s_free(nullptr, lpAction->act.reply.guid.__ptr);
  776. break;
  777. case OP_DEFER_ACTION:
  778. s_free(nullptr, lpAction->act.defer.bin.__ptr);
  779. break;
  780. case OP_BOUNCE:
  781. break;
  782. case OP_FORWARD:
  783. case OP_DELEGATE:
  784. FreeRowSet(lpAction->act.adrlist, true);
  785. break;
  786. case OP_TAG:
  787. FreePropVal(lpAction->act.prop, true);
  788. break;
  789. }
  790. }
  791. s_free(nullptr, lpActions->__ptr);
  792. s_free(nullptr, lpProp->Value.actions);
  793. }
  794. break;
  795. default:
  796. er = KCERR_INVALID_TYPE;
  797. }
  798. if(bBasePointerDel)
  799. s_free(nullptr, lpProp);
  800. return er;
  801. }
  802. void FreeRowSet(struct rowSet *lpRowSet, bool bBasePointerDel)
  803. {
  804. if(lpRowSet == NULL)
  805. return;
  806. for (gsoap_size_t i = 0; i < lpRowSet->__size; ++i)
  807. FreePropValArray(&lpRowSet->__ptr[i]);
  808. s_free(nullptr, lpRowSet->__ptr);
  809. if(bBasePointerDel)
  810. s_free(nullptr, lpRowSet);
  811. }
  812. /**
  813. * Frees a soap restriction table
  814. *
  815. * @param[in] lpRestrict the soap restriction table to free and everything below it
  816. * @param[in] base always true, except when you know what you're doing (aka restriction optimizer for the kopano-search)
  817. *
  818. * @return
  819. */
  820. ECRESULT FreeRestrictTable(struct restrictTable *lpRestrict, bool base)
  821. {
  822. ECRESULT er;
  823. if(lpRestrict == NULL)
  824. return erSuccess;
  825. switch(lpRestrict->ulType) {
  826. case RES_OR:
  827. if(lpRestrict->lpOr && lpRestrict->lpOr->__ptr) {
  828. for (gsoap_size_t i = 0; i < lpRestrict->lpOr->__size; ++i) {
  829. er = FreeRestrictTable(lpRestrict->lpOr->__ptr[i]);
  830. if(er != erSuccess)
  831. return er;
  832. }
  833. s_free(nullptr, lpRestrict->lpOr->__ptr);
  834. }
  835. s_free(nullptr, lpRestrict->lpOr);
  836. break;
  837. case RES_AND:
  838. if(lpRestrict->lpAnd && lpRestrict->lpAnd->__ptr) {
  839. for (gsoap_size_t i = 0; i < lpRestrict->lpAnd->__size; ++i) {
  840. er = FreeRestrictTable(lpRestrict->lpAnd->__ptr[i]);
  841. if(er != erSuccess)
  842. return er;
  843. }
  844. s_free(nullptr, lpRestrict->lpAnd->__ptr);
  845. }
  846. s_free(nullptr, lpRestrict->lpAnd);
  847. break;
  848. case RES_NOT:
  849. if(lpRestrict->lpNot && lpRestrict->lpNot->lpNot)
  850. FreeRestrictTable(lpRestrict->lpNot->lpNot);
  851. s_free(nullptr, lpRestrict->lpNot);
  852. break;
  853. case RES_CONTENT:
  854. if(lpRestrict->lpContent && lpRestrict->lpContent->lpProp)
  855. FreePropVal(lpRestrict->lpContent->lpProp, true);
  856. s_free(nullptr, lpRestrict->lpContent);
  857. break;
  858. case RES_PROPERTY:
  859. if(lpRestrict->lpProp && lpRestrict->lpProp->lpProp)
  860. FreePropVal(lpRestrict->lpProp->lpProp, true);
  861. s_free(nullptr, lpRestrict->lpProp);
  862. break;
  863. case RES_COMPAREPROPS:
  864. s_free(nullptr, lpRestrict->lpCompare);
  865. break;
  866. case RES_BITMASK:
  867. s_free(nullptr, lpRestrict->lpBitmask);
  868. break;
  869. case RES_SIZE:
  870. s_free(nullptr, lpRestrict->lpSize);
  871. break;
  872. case RES_EXIST:
  873. s_free(nullptr, lpRestrict->lpExist);
  874. break;
  875. case RES_COMMENT:
  876. if (lpRestrict->lpComment) {
  877. if (lpRestrict->lpComment->lpResTable)
  878. FreeRestrictTable(lpRestrict->lpComment->lpResTable);
  879. FreePropValArray(&lpRestrict->lpComment->sProps);
  880. s_free(nullptr, lpRestrict->lpComment);
  881. }
  882. break;
  883. case RES_SUBRESTRICTION:
  884. if(lpRestrict->lpSub && lpRestrict->lpSub->lpSubObject)
  885. FreeRestrictTable(lpRestrict->lpSub->lpSubObject);
  886. s_free(nullptr, lpRestrict->lpSub);
  887. break;
  888. default:
  889. er = KCERR_INVALID_TYPE;
  890. // NOTE: don't exit here, delete lpRestrict
  891. break;
  892. }
  893. // only when we're optimizing restrictions we must keep the base pointer, so we can replace it with new content
  894. if (base)
  895. s_free(nullptr, lpRestrict);
  896. return erSuccess;
  897. }
  898. ECRESULT CopyPropVal(const struct propVal *lpSrc, struct propVal *lpDst,
  899. struct soap *soap, bool bTruncate)
  900. {
  901. ECRESULT er = PropCheck(lpSrc);
  902. if(er != erSuccess)
  903. return er;
  904. lpDst->ulPropTag = lpSrc->ulPropTag;
  905. lpDst->__union = lpSrc->__union;
  906. switch(PROP_TYPE(lpSrc->ulPropTag)) {
  907. case PT_I2:
  908. lpDst->Value.i = lpSrc->Value.i;
  909. break;
  910. case PT_NULL:
  911. case PT_ERROR:
  912. case PT_LONG:
  913. lpDst->Value.ul = lpSrc->Value.ul;
  914. break;
  915. case PT_R4:
  916. lpDst->Value.flt = lpSrc->Value.flt;
  917. break;
  918. case PT_BOOLEAN:
  919. lpDst->Value.b = lpSrc->Value.b;
  920. break;
  921. case PT_DOUBLE:
  922. case PT_APPTIME:
  923. lpDst->Value.dbl = lpSrc->Value.dbl;
  924. break;
  925. case PT_I8:
  926. lpDst->Value.li = lpSrc->Value.li;
  927. break;
  928. case PT_CURRENCY:
  929. case PT_SYSTIME:
  930. if (lpSrc->Value.hilo == NULL)
  931. return KCERR_INVALID_TYPE;
  932. lpDst->Value.hilo = s_alloc<hiloLong>(soap);
  933. lpDst->Value.hilo->hi = lpSrc->Value.hilo->hi;
  934. lpDst->Value.hilo->lo = lpSrc->Value.hilo->lo;
  935. break;
  936. case PT_UNICODE:
  937. case PT_STRING8: {
  938. size_t len;
  939. if (lpSrc->Value.lpszA == NULL)
  940. return KCERR_INVALID_TYPE;
  941. if (bTruncate)
  942. len = u8_cappedbytes(lpSrc->Value.lpszA, TABLE_CAP_STRING);
  943. else
  944. len = strlen(lpSrc->Value.lpszA);
  945. lpDst->Value.lpszA = s_alloc<char>(soap, len+1);
  946. strncpy(lpDst->Value.lpszA, lpSrc->Value.lpszA, len);
  947. *(lpDst->Value.lpszA+len) = 0; // null terminate after strncpy
  948. break;
  949. }
  950. case PT_BINARY:
  951. case PT_CLSID:
  952. if (lpSrc->Value.bin == NULL)
  953. return KCERR_INVALID_TYPE;
  954. lpDst->Value.bin = s_alloc<struct xsd__base64Binary>(soap);
  955. lpDst->Value.bin->__size = lpSrc->Value.bin->__size;
  956. if (bTruncate && lpDst->Value.bin->__size > TABLE_CAP_BINARY)
  957. lpDst->Value.bin->__size = TABLE_CAP_BINARY;
  958. lpDst->Value.bin->__ptr = s_alloc<unsigned char>(soap, lpSrc->Value.bin->__size);
  959. memcpy(lpDst->Value.bin->__ptr, lpSrc->Value.bin->__ptr, lpDst->Value.bin->__size);
  960. break;
  961. case PT_MV_I2:
  962. if (lpSrc->Value.mvi.__ptr == NULL)
  963. return KCERR_INVALID_TYPE;
  964. lpDst->Value.mvi.__size = lpSrc->Value.mvi.__size;
  965. lpDst->Value.mvi.__ptr = s_alloc<short int>(soap, lpSrc->Value.mvi.__size);
  966. memcpy(lpDst->Value.mvi.__ptr, lpSrc->Value.mvi.__ptr, sizeof(short int) * lpDst->Value.mvi.__size);
  967. break;
  968. case PT_MV_LONG:
  969. if (lpSrc->Value.mvl.__ptr == NULL)
  970. return KCERR_INVALID_TYPE;
  971. lpDst->Value.mvl.__size = lpSrc->Value.mvl.__size;
  972. lpDst->Value.mvl.__ptr = s_alloc<unsigned int>(soap, lpSrc->Value.mvl.__size);
  973. memcpy(lpDst->Value.mvl.__ptr, lpSrc->Value.mvl.__ptr, sizeof(unsigned int) * lpDst->Value.mvl.__size);
  974. break;
  975. case PT_MV_R4:
  976. if (lpSrc->Value.mvflt.__ptr == NULL)
  977. return KCERR_INVALID_TYPE;
  978. lpDst->Value.mvflt.__size = lpSrc->Value.mvflt.__size;
  979. lpDst->Value.mvflt.__ptr = s_alloc<float>(soap, lpSrc->Value.mvflt.__size);
  980. memcpy(lpDst->Value.mvflt.__ptr, lpSrc->Value.mvflt.__ptr, sizeof(float) * lpDst->Value.mvflt.__size);
  981. break;
  982. case PT_MV_DOUBLE:
  983. case PT_MV_APPTIME:
  984. if (lpSrc->Value.mvdbl.__ptr == NULL)
  985. return KCERR_INVALID_TYPE;
  986. lpDst->Value.mvdbl.__size = lpSrc->Value.mvdbl.__size;
  987. lpDst->Value.mvdbl.__ptr = s_alloc<double>(soap, lpSrc->Value.mvdbl.__size);
  988. memcpy(lpDst->Value.mvdbl.__ptr, lpSrc->Value.mvdbl.__ptr, sizeof(double) * lpDst->Value.mvdbl.__size);
  989. break;
  990. case PT_MV_I8:
  991. if (lpSrc->Value.mvli.__ptr == NULL)
  992. return KCERR_INVALID_TYPE;
  993. lpDst->Value.mvli.__size = lpSrc->Value.mvli.__size;
  994. lpDst->Value.mvli.__ptr = s_alloc<LONG64>(soap, lpSrc->Value.mvli.__size);
  995. memcpy(lpDst->Value.mvli.__ptr, lpSrc->Value.mvli.__ptr, sizeof(LONG64) * lpDst->Value.mvli.__size);
  996. break;
  997. case PT_MV_CURRENCY:
  998. case PT_MV_SYSTIME:
  999. if (lpSrc->Value.mvhilo.__ptr == NULL)
  1000. return KCERR_INVALID_TYPE;
  1001. lpDst->Value.mvhilo.__size = lpSrc->Value.mvhilo.__size;
  1002. lpDst->Value.mvhilo.__ptr = s_alloc<hiloLong>(soap, lpSrc->Value.mvhilo.__size);
  1003. memcpy(lpDst->Value.mvhilo.__ptr, lpSrc->Value.mvhilo.__ptr, sizeof(hiloLong) * lpDst->Value.mvhilo.__size);
  1004. break;
  1005. case PT_MV_STRING8:
  1006. case PT_MV_UNICODE:
  1007. if (lpSrc->Value.mvszA.__ptr == NULL)
  1008. return KCERR_INVALID_TYPE;
  1009. lpDst->Value.mvszA.__size = lpSrc->Value.mvszA.__size;
  1010. lpDst->Value.mvszA.__ptr = s_alloc<char*>(soap, lpSrc->Value.mvszA.__size);
  1011. for (gsoap_size_t i = 0; i < lpSrc->Value.mvszA.__size; ++i) {
  1012. lpDst->Value.mvszA.__ptr[i] = s_alloc<char>(soap, strlen(lpSrc->Value.mvszA.__ptr[i])+1);
  1013. if(lpSrc->Value.mvszA.__ptr[i] == NULL)
  1014. strcpy(lpDst->Value.mvszA.__ptr[i], "");
  1015. else
  1016. strcpy(lpDst->Value.mvszA.__ptr[i], lpSrc->Value.mvszA.__ptr[i]);
  1017. }
  1018. break;
  1019. case PT_MV_BINARY:
  1020. case PT_MV_CLSID:
  1021. if (lpSrc->Value.mvbin.__ptr == NULL)
  1022. return KCERR_INVALID_TYPE;
  1023. lpDst->Value.mvbin.__size = lpSrc->Value.mvbin.__size;
  1024. lpDst->Value.mvbin.__ptr = s_alloc<struct xsd__base64Binary>(soap, lpSrc->Value.mvbin.__size);
  1025. for (gsoap_size_t i = 0; i < lpSrc->Value.mvbin.__size; ++i) {
  1026. lpDst->Value.mvbin.__ptr[i].__ptr = s_alloc<unsigned char>(soap, lpSrc->Value.mvbin.__ptr[i].__size);
  1027. if(lpSrc->Value.mvbin.__ptr[i].__ptr == NULL) {
  1028. lpDst->Value.mvbin.__ptr[i].__size = 0;
  1029. } else {
  1030. memcpy(lpDst->Value.mvbin.__ptr[i].__ptr, lpSrc->Value.mvbin.__ptr[i].__ptr, lpSrc->Value.mvbin.__ptr[i].__size);
  1031. lpDst->Value.mvbin.__ptr[i].__size = lpSrc->Value.mvbin.__ptr[i].__size;
  1032. }
  1033. }
  1034. break;
  1035. default:
  1036. return KCERR_INVALID_TYPE;
  1037. }
  1038. return erSuccess;
  1039. }
  1040. ECRESULT CopyPropVal(const struct propVal *lpSrc, struct propVal **lppDst,
  1041. struct soap *soap, bool bTruncate)
  1042. {
  1043. ECRESULT er;
  1044. struct propVal *lpDst;
  1045. lpDst = s_alloc<struct propVal>(soap);
  1046. er = CopyPropVal(lpSrc, lpDst, soap);
  1047. if (er != erSuccess) {
  1048. // there is no sub-alloc when there's an error, so we can remove lpDst
  1049. if (!soap)
  1050. s_free(nullptr, lpDst);
  1051. return er;
  1052. }
  1053. *lppDst = lpDst;
  1054. return erSuccess;
  1055. }
  1056. ECRESULT CopyPropValArray(const struct propValArray *lpSrc,
  1057. struct propValArray **lppDst, struct soap *soap)
  1058. {
  1059. ECRESULT er;
  1060. struct propValArray *lpDst = NULL;
  1061. if (lpSrc == NULL || lppDst == NULL)
  1062. return KCERR_INVALID_PARAMETER;
  1063. lpDst = s_alloc<struct propValArray>(soap);
  1064. if(lpSrc->__size > 0) {
  1065. er = CopyPropValArray(lpSrc, lpDst, soap);
  1066. if(er != erSuccess)
  1067. return er;
  1068. }else {
  1069. lpDst->__ptr = NULL;
  1070. lpDst->__size = 0;
  1071. }
  1072. *lppDst = lpDst;
  1073. return erSuccess;
  1074. }
  1075. ECRESULT CopyPropValArray(const struct propValArray *lpSrc,
  1076. struct propValArray *lpDst, struct soap *soap)
  1077. {
  1078. ECRESULT er;
  1079. if (lpSrc == NULL)
  1080. return KCERR_INVALID_PARAMETER;
  1081. lpDst->__ptr = s_alloc<struct propVal>(soap, lpSrc->__size);
  1082. lpDst->__size = lpSrc->__size;
  1083. memset(lpDst->__ptr, 0, sizeof(propVal)*lpDst->__size);
  1084. for (gsoap_size_t i = 0; i < lpSrc->__size; ++i) {
  1085. er = CopyPropVal(&lpSrc->__ptr[i], &lpDst->__ptr[i], soap);
  1086. if(er != erSuccess) {
  1087. if (!soap) {
  1088. s_free(nullptr, lpDst->__ptr);
  1089. lpDst->__ptr = NULL;
  1090. }
  1091. lpDst->__size = 0;
  1092. return er;
  1093. }
  1094. }
  1095. return erSuccess;
  1096. }
  1097. ECRESULT CopyRestrictTable(struct soap *soap,
  1098. const struct restrictTable *lpSrc, struct restrictTable **lppDst)
  1099. {
  1100. ECRESULT er;
  1101. struct restrictTable *lpDst = NULL;
  1102. if (lpSrc == NULL)
  1103. return KCERR_INVALID_PARAMETER;
  1104. lpDst = s_alloc<struct restrictTable>(soap);
  1105. memset(lpDst, 0, sizeof(restrictTable));
  1106. lpDst->ulType = lpSrc->ulType;
  1107. switch(lpSrc->ulType) {
  1108. case RES_OR:
  1109. if (lpSrc->lpOr == NULL)
  1110. return KCERR_INVALID_TYPE;
  1111. lpDst->lpOr = s_alloc<restrictOr>(soap);
  1112. lpDst->lpOr->__ptr = s_alloc<restrictTable *>(soap, lpSrc->lpOr->__size);
  1113. lpDst->lpOr->__size = lpSrc->lpOr->__size;
  1114. memset(lpDst->lpOr->__ptr, 0, sizeof(restrictTable *) * lpSrc->lpOr->__size);
  1115. for (gsoap_size_t i = 0; i < lpSrc->lpOr->__size; ++i) {
  1116. er = CopyRestrictTable(soap, lpSrc->lpOr->__ptr[i], &lpDst->lpOr->__ptr[i]);
  1117. if(er != erSuccess)
  1118. return er;
  1119. }
  1120. break;
  1121. case RES_AND:
  1122. if(lpSrc->lpAnd == NULL)
  1123. return KCERR_INVALID_TYPE;
  1124. lpDst->lpAnd = s_alloc<restrictAnd>(soap);
  1125. lpDst->lpAnd->__ptr = s_alloc<restrictTable *>(soap, lpSrc->lpAnd->__size);
  1126. lpDst->lpAnd->__size = lpSrc->lpAnd->__size;
  1127. memset(lpDst->lpAnd->__ptr, 0, sizeof(restrictTable *) * lpSrc->lpAnd->__size);
  1128. for (gsoap_size_t i = 0; i < lpSrc->lpAnd->__size; ++i) {
  1129. er = CopyRestrictTable(soap, lpSrc->lpAnd->__ptr[i], &lpDst->lpAnd->__ptr[i]);
  1130. if(er != erSuccess)
  1131. return er;
  1132. }
  1133. break;
  1134. case RES_NOT:
  1135. lpDst->lpNot = s_alloc<restrictNot>(soap);
  1136. memset(lpDst->lpNot, 0, sizeof(restrictNot));
  1137. er = CopyRestrictTable(soap, lpSrc->lpNot->lpNot, &lpDst->lpNot->lpNot);
  1138. if(er != erSuccess)
  1139. return er;
  1140. break;
  1141. case RES_CONTENT:
  1142. lpDst->lpContent = s_alloc<restrictContent>(soap);
  1143. memset(lpDst->lpContent, 0, sizeof(restrictContent));
  1144. lpDst->lpContent->ulFuzzyLevel = lpSrc->lpContent->ulFuzzyLevel;
  1145. lpDst->lpContent->ulPropTag = lpSrc->lpContent->ulPropTag;
  1146. if(lpSrc->lpContent->lpProp) {
  1147. er = CopyPropVal(lpSrc->lpContent->lpProp, &lpDst->lpContent->lpProp, soap);
  1148. if(er != erSuccess)
  1149. return er;
  1150. }
  1151. break;
  1152. case RES_PROPERTY:
  1153. lpDst->lpProp = s_alloc<restrictProp>(soap);
  1154. memset(lpDst->lpProp, 0, sizeof(restrictProp));
  1155. lpDst->lpProp->ulType = lpSrc->lpProp->ulType;
  1156. lpDst->lpProp->ulPropTag = lpSrc->lpProp->ulPropTag;
  1157. er = CopyPropVal(lpSrc->lpProp->lpProp, &lpDst->lpProp->lpProp, soap);
  1158. if(er != erSuccess)
  1159. return er;
  1160. break;
  1161. case RES_COMPAREPROPS:
  1162. lpDst->lpCompare = s_alloc<restrictCompare>(soap);
  1163. memset(lpDst->lpCompare, 0 , sizeof(restrictCompare));
  1164. lpDst->lpCompare->ulType = lpSrc->lpCompare->ulType;
  1165. lpDst->lpCompare->ulPropTag1 = lpSrc->lpCompare->ulPropTag1;
  1166. lpDst->lpCompare->ulPropTag2 = lpSrc->lpCompare->ulPropTag2;
  1167. break;
  1168. case RES_BITMASK:
  1169. lpDst->lpBitmask = s_alloc<restrictBitmask>(soap);
  1170. memset(lpDst->lpBitmask, 0, sizeof(restrictBitmask));
  1171. lpDst->lpBitmask->ulMask = lpSrc->lpBitmask->ulMask;
  1172. lpDst->lpBitmask->ulPropTag = lpSrc->lpBitmask->ulPropTag;
  1173. lpDst->lpBitmask->ulType = lpSrc->lpBitmask->ulType;
  1174. break;
  1175. case RES_SIZE:
  1176. lpDst->lpSize = s_alloc<restrictSize>(soap);
  1177. memset(lpDst->lpSize, 0, sizeof(restrictSize));
  1178. lpDst->lpSize->ulPropTag = lpSrc->lpSize->ulPropTag;
  1179. lpDst->lpSize->ulType = lpSrc->lpSize->ulType;
  1180. lpDst->lpSize->cb = lpSrc->lpSize->cb;
  1181. break;
  1182. case RES_EXIST:
  1183. lpDst->lpExist = s_alloc<restrictExist>(soap);
  1184. memset(lpDst->lpExist, 0, sizeof(restrictExist));
  1185. lpDst->lpExist->ulPropTag = lpSrc->lpExist->ulPropTag;
  1186. break;
  1187. case RES_COMMENT:
  1188. lpDst->lpComment = s_alloc<restrictComment>(soap);
  1189. memset(lpDst->lpComment, 0, sizeof(restrictComment));
  1190. er = CopyPropValArray(&lpSrc->lpComment->sProps, &lpDst->lpComment->sProps, soap);
  1191. if (er != erSuccess)
  1192. return er;
  1193. er = CopyRestrictTable(soap, lpSrc->lpComment->lpResTable, &lpDst->lpComment->lpResTable);
  1194. if(er != erSuccess)
  1195. return er;
  1196. break;
  1197. case RES_SUBRESTRICTION:
  1198. lpDst->lpSub = s_alloc<restrictSub>(soap);
  1199. memset(lpDst->lpSub, 0, sizeof(restrictSub));
  1200. lpDst->lpSub->ulSubObject = lpSrc->lpSub->ulSubObject;
  1201. er = CopyRestrictTable(soap, lpSrc->lpSub->lpSubObject, &lpDst->lpSub->lpSubObject);
  1202. if(er != erSuccess)
  1203. return er;
  1204. break;
  1205. default:
  1206. return KCERR_INVALID_TYPE;
  1207. }
  1208. *lppDst = lpDst;
  1209. return erSuccess;
  1210. }
  1211. ECRESULT FreePropValArray(struct propValArray *lpPropValArray, bool bFreeBase)
  1212. {
  1213. if(lpPropValArray) {
  1214. for (gsoap_size_t i = 0; i < lpPropValArray->__size; ++i)
  1215. FreePropVal(&(lpPropValArray->__ptr[i]), false);
  1216. s_free(nullptr, lpPropValArray->__ptr);
  1217. if(bFreeBase)
  1218. s_free(nullptr, lpPropValArray);
  1219. }
  1220. return erSuccess;
  1221. }
  1222. ECRESULT CopyEntryId(struct soap *soap, entryId* lpSrc, entryId** lppDst)
  1223. {
  1224. entryId* lpDst = NULL;
  1225. if (lpSrc == NULL)
  1226. return KCERR_INVALID_PARAMETER;
  1227. lpDst = s_alloc<entryId>(soap);
  1228. lpDst->__size = lpSrc->__size;
  1229. if(lpSrc->__size > 0) {
  1230. lpDst->__ptr = s_alloc<unsigned char>(soap, lpSrc->__size);
  1231. memcpy(lpDst->__ptr, lpSrc->__ptr, sizeof(unsigned char) * lpSrc->__size);
  1232. } else {
  1233. lpDst->__ptr = NULL;
  1234. }
  1235. *lppDst = lpDst;
  1236. return erSuccess;
  1237. }
  1238. ECRESULT CopyEntryList(struct soap *soap, struct entryList *lpSrc, struct entryList **lppDst)
  1239. {
  1240. struct entryList *lpDst = NULL;
  1241. if (lpSrc == NULL)
  1242. return KCERR_INVALID_PARAMETER;
  1243. lpDst = s_alloc<entryList>(soap);
  1244. lpDst->__size = lpSrc->__size;
  1245. if(lpSrc->__size > 0)
  1246. lpDst->__ptr = s_alloc<entryId>(soap, lpSrc->__size);
  1247. else
  1248. lpDst->__ptr = NULL;
  1249. for (unsigned int i = 0; i < lpSrc->__size; ++i) {
  1250. lpDst->__ptr[i].__size = lpSrc->__ptr[i].__size;
  1251. lpDst->__ptr[i].__ptr = s_alloc<unsigned char>(soap, lpSrc->__ptr[i].__size);
  1252. memcpy(lpDst->__ptr[i].__ptr, lpSrc->__ptr[i].__ptr, sizeof(unsigned char) * lpSrc->__ptr[i].__size);
  1253. }
  1254. *lppDst = lpDst;
  1255. return erSuccess;
  1256. }
  1257. ECRESULT FreeEntryList(struct entryList *lpEntryList, bool bFreeBase)
  1258. {
  1259. if(lpEntryList == NULL)
  1260. return erSuccess;
  1261. if(lpEntryList->__ptr) {
  1262. for (unsigned int i = 0; i < lpEntryList->__size; ++i)
  1263. s_free(nullptr, lpEntryList->__ptr[i].__ptr);
  1264. s_free(nullptr, lpEntryList->__ptr);
  1265. }
  1266. if (bFreeBase)
  1267. s_free(nullptr, lpEntryList);
  1268. return erSuccess;
  1269. }
  1270. ECRESULT FreeNotificationStruct(notification *lpNotification, bool bFreeBase)
  1271. {
  1272. if(lpNotification == NULL)
  1273. return erSuccess;
  1274. if(lpNotification->obj != NULL){
  1275. FreePropTagArray(lpNotification->obj->pPropTagArray);
  1276. FreeEntryId(lpNotification->obj->pEntryId, true);
  1277. FreeEntryId(lpNotification->obj->pOldId, true);
  1278. FreeEntryId(lpNotification->obj->pOldParentId, true);
  1279. FreeEntryId(lpNotification->obj->pParentId, true);
  1280. s_free(nullptr, lpNotification->obj);
  1281. }
  1282. if(lpNotification->tab != NULL) {
  1283. if(lpNotification->tab->pRow != NULL)
  1284. FreePropValArray(lpNotification->tab->pRow, true);
  1285. if(lpNotification->tab->propIndex.Value.bin != NULL) {
  1286. s_free(nullptr, lpNotification->tab->propIndex.Value.bin->__ptr);
  1287. s_free(nullptr, lpNotification->tab->propIndex.Value.bin);
  1288. }
  1289. if(lpNotification->tab->propPrior.Value.bin != NULL) {
  1290. s_free(nullptr, lpNotification->tab->propPrior.Value.bin->__ptr);
  1291. s_free(nullptr, lpNotification->tab->propPrior.Value.bin);
  1292. }
  1293. s_free(nullptr, lpNotification->tab);
  1294. }
  1295. if (lpNotification->newmail != NULL) {
  1296. s_free(nullptr, lpNotification->newmail->lpszMessageClass);
  1297. FreeEntryId(lpNotification->newmail->pEntryId, true);
  1298. FreeEntryId(lpNotification->newmail->pParentId, true);
  1299. s_free(nullptr, lpNotification->newmail);
  1300. }
  1301. if(lpNotification->ics != NULL) {
  1302. FreeEntryId(lpNotification->ics->pSyncState, true);
  1303. s_free(nullptr, lpNotification->ics);
  1304. }
  1305. if(bFreeBase)
  1306. s_free(nullptr, lpNotification);
  1307. return erSuccess;
  1308. }
  1309. // Make a copy of the struct notification.
  1310. ECRESULT CopyNotificationStruct(struct soap *soap,
  1311. const notification *lpNotification, notification &rNotifyTo)
  1312. {
  1313. int nLen;
  1314. if (lpNotification == NULL)
  1315. return KCERR_INVALID_PARAMETER;
  1316. memset(&rNotifyTo, 0, sizeof(rNotifyTo));
  1317. rNotifyTo.ulEventType = lpNotification->ulEventType;
  1318. rNotifyTo.ulConnection = lpNotification->ulConnection;
  1319. if(lpNotification->tab != NULL) {
  1320. rNotifyTo.tab = s_alloc<notificationTable>(soap);
  1321. memset(rNotifyTo.tab, 0, sizeof(notificationTable));
  1322. rNotifyTo.tab->hResult = lpNotification->tab->hResult;
  1323. rNotifyTo.tab->ulTableEvent = lpNotification->tab->ulTableEvent;
  1324. CopyPropVal(&lpNotification->tab->propIndex, &rNotifyTo.tab->propIndex, soap);
  1325. CopyPropVal(&lpNotification->tab->propPrior, &rNotifyTo.tab->propPrior, soap);
  1326. // Ignore errors
  1327. CopyPropValArray(lpNotification->tab->pRow, &rNotifyTo.tab->pRow, soap);
  1328. rNotifyTo.tab->ulObjType = lpNotification->tab->ulObjType;
  1329. }else if(lpNotification->obj != NULL) {
  1330. rNotifyTo.obj = s_alloc<notificationObject>(soap);
  1331. memset(rNotifyTo.obj, 0, sizeof(notificationObject));
  1332. rNotifyTo.obj->ulObjType = lpNotification->obj->ulObjType;
  1333. // Ignore errors, sometimes nothing to copy
  1334. CopyEntryId(soap, lpNotification->obj->pEntryId, &rNotifyTo.obj->pEntryId);
  1335. CopyEntryId(soap, lpNotification->obj->pParentId, &rNotifyTo.obj->pParentId);
  1336. CopyEntryId(soap, lpNotification->obj->pOldId, &rNotifyTo.obj->pOldId);
  1337. CopyEntryId(soap, lpNotification->obj->pOldParentId, &rNotifyTo.obj->pOldParentId);
  1338. CopyPropTagArray(soap, lpNotification->obj->pPropTagArray, &rNotifyTo.obj->pPropTagArray);
  1339. }else if(lpNotification->newmail != NULL){
  1340. rNotifyTo.newmail = s_alloc<notificationNewMail>(soap);
  1341. memset(rNotifyTo.newmail, 0, sizeof(notificationNewMail));
  1342. // Ignore errors, sometimes nothing to copy
  1343. CopyEntryId(soap, lpNotification->newmail->pEntryId, &rNotifyTo.newmail->pEntryId);
  1344. CopyEntryId(soap, lpNotification->newmail->pParentId, &rNotifyTo.newmail->pParentId);
  1345. rNotifyTo.newmail->ulMessageFlags = lpNotification->newmail->ulMessageFlags;
  1346. if(lpNotification->newmail->lpszMessageClass) {
  1347. nLen = (int)strlen(lpNotification->newmail->lpszMessageClass)+1;
  1348. rNotifyTo.newmail->lpszMessageClass = s_alloc<char>(soap, nLen);
  1349. memcpy(rNotifyTo.newmail->lpszMessageClass, lpNotification->newmail->lpszMessageClass, nLen);
  1350. }
  1351. }else if(lpNotification->ics != NULL){
  1352. rNotifyTo.ics = s_alloc<notificationICS>(soap);
  1353. memset(rNotifyTo.ics, 0, sizeof(notificationICS));
  1354. // We use CopyEntryId as it just copied binary data
  1355. CopyEntryId(soap, lpNotification->ics->pSyncState, &rNotifyTo.ics->pSyncState);
  1356. }
  1357. return erSuccess;
  1358. }
  1359. ECRESULT FreeNotificationArrayStruct(notificationArray *lpNotifyArray, bool bFreeBase)
  1360. {
  1361. if(lpNotifyArray == NULL)
  1362. return erSuccess;
  1363. for (gsoap_size_t i = 0; i < lpNotifyArray->__size; ++i)
  1364. FreeNotificationStruct(&lpNotifyArray->__ptr[i], false);
  1365. s_free(nullptr, lpNotifyArray->__ptr);
  1366. if(bFreeBase)
  1367. s_free(nullptr, lpNotifyArray);
  1368. else
  1369. lpNotifyArray->__size = 0;
  1370. return erSuccess;
  1371. }
  1372. ECRESULT CopyNotificationArrayStruct(notificationArray *lpNotifyArrayFrom, notificationArray *lpNotifyArrayTo)
  1373. {
  1374. if (lpNotifyArrayFrom == NULL)
  1375. return KCERR_INVALID_PARAMETER;
  1376. if (lpNotifyArrayFrom->__size > 0)
  1377. lpNotifyArrayTo->__ptr = s_alloc<notification>(nullptr, lpNotifyArrayFrom->__size);
  1378. else
  1379. lpNotifyArrayTo->__ptr = NULL;
  1380. lpNotifyArrayTo->__size = lpNotifyArrayFrom->__size;
  1381. for (gsoap_size_t i = 0; i < lpNotifyArrayFrom->__size; ++i)
  1382. CopyNotificationStruct(NULL, &lpNotifyArrayFrom->__ptr[i], lpNotifyArrayTo->__ptr[i]);
  1383. return erSuccess;
  1384. }
  1385. ECRESULT FreeEntryId(entryId* lpEntryId, bool bFreeBase)
  1386. {
  1387. if(lpEntryId == NULL)
  1388. return erSuccess;
  1389. s_free(nullptr, lpEntryId->__ptr);
  1390. if(bFreeBase == true)
  1391. s_free(nullptr, lpEntryId);
  1392. else
  1393. lpEntryId->__size = 0;
  1394. return erSuccess;
  1395. }
  1396. ECRESULT CopyRightsArrayToSoap(struct soap *soap, struct rightsArray *lpRightsArraySrc, struct rightsArray **lppRightsArrayDst)
  1397. {
  1398. struct rightsArray *lpRightsArrayDst = NULL;
  1399. if (soap == NULL || lpRightsArraySrc == NULL || lppRightsArrayDst == NULL)
  1400. return KCERR_INVALID_PARAMETER;
  1401. lpRightsArrayDst = s_alloc<struct rightsArray>(soap);
  1402. memset(lpRightsArrayDst, 0, sizeof *lpRightsArrayDst);
  1403. lpRightsArrayDst->__size = lpRightsArraySrc->__size;
  1404. lpRightsArrayDst->__ptr = s_alloc<struct rights>(soap, lpRightsArraySrc->__size);
  1405. for (gsoap_size_t i = 0; i < lpRightsArraySrc->__size; ++i) {
  1406. lpRightsArrayDst->__ptr[i] = lpRightsArraySrc->__ptr[i];
  1407. lpRightsArrayDst->__ptr[i].sUserId.__ptr = s_alloc<unsigned char>(soap, lpRightsArrayDst->__ptr[i].sUserId.__size);
  1408. memcpy(lpRightsArrayDst->__ptr[i].sUserId.__ptr, lpRightsArraySrc->__ptr[i].sUserId.__ptr, lpRightsArraySrc->__ptr[i].sUserId.__size);
  1409. }
  1410. *lppRightsArrayDst = lpRightsArrayDst;
  1411. return erSuccess;
  1412. }
  1413. ECRESULT FreeRightsArray(struct rightsArray *lpRights)
  1414. {
  1415. if(lpRights == NULL)
  1416. return erSuccess;
  1417. if(lpRights->__ptr)
  1418. {
  1419. s_free(nullptr, lpRights->__ptr->sUserId.__ptr);
  1420. s_free(nullptr, lpRights->__ptr);
  1421. }
  1422. s_free(nullptr, lpRights);
  1423. return erSuccess;
  1424. }
  1425. static const struct propVal *
  1426. SpropValFindPropVal(const struct propValArray *lpsPropValArray,
  1427. unsigned int ulPropTag)
  1428. {
  1429. if(PROP_TYPE(ulPropTag) == PT_ERROR)
  1430. return NULL;
  1431. for (gsoap_size_t i = 0; i < lpsPropValArray->__size; ++i)
  1432. if(lpsPropValArray->__ptr[i].ulPropTag == ulPropTag ||
  1433. (PROP_ID(lpsPropValArray->__ptr[i].ulPropTag) == PROP_ID(ulPropTag) &&
  1434. PROP_TYPE(ulPropTag) == PT_UNSPECIFIED &&
  1435. PROP_TYPE(lpsPropValArray->__ptr[i].ulPropTag) != PT_ERROR) )
  1436. return &lpsPropValArray->__ptr[i];
  1437. return NULL;
  1438. }
  1439. // NOTE: PropValArray 2 overruled PropValArray 1, except if proptype is PT_ERROR
  1440. ECRESULT MergePropValArray(struct soap *soap,
  1441. const struct propValArray *lpsPropValArray1,
  1442. const struct propValArray *lpsPropValArray2,
  1443. struct propValArray *lpPropValArrayNew)
  1444. {
  1445. ECRESULT er;
  1446. const struct propVal *lpsPropVal;
  1447. lpPropValArrayNew->__ptr = s_alloc<struct propVal>(soap, lpsPropValArray1->__size + lpsPropValArray2->__size);
  1448. lpPropValArrayNew->__size = 0;
  1449. for (gsoap_size_t i = 0; i < lpsPropValArray1->__size; ++i) {
  1450. lpsPropVal = SpropValFindPropVal(lpsPropValArray2, lpsPropValArray1->__ptr[i].ulPropTag);
  1451. if(lpsPropVal == NULL)
  1452. lpsPropVal = &lpsPropValArray1->__ptr[i];
  1453. er = CopyPropVal(lpsPropVal, &lpPropValArrayNew->__ptr[lpPropValArrayNew->__size], soap);
  1454. if(er != erSuccess)
  1455. return er;
  1456. ++lpPropValArrayNew->__size;
  1457. }
  1458. //Merge items
  1459. for (gsoap_size_t i = 0; i < lpsPropValArray2->__size; ++i) {
  1460. lpsPropVal = SpropValFindPropVal(lpPropValArrayNew, lpsPropValArray2->__ptr[i].ulPropTag);
  1461. if(lpsPropVal != NULL)
  1462. continue; // Already exist
  1463. er = CopyPropVal(&lpsPropValArray2->__ptr[i], &lpPropValArrayNew->__ptr[lpPropValArrayNew->__size], soap);
  1464. if(er != erSuccess)
  1465. return er;
  1466. ++lpPropValArrayNew->__size;
  1467. }
  1468. return erSuccess;
  1469. }
  1470. ECRESULT CopySearchCriteria(struct soap *soap,
  1471. const struct searchCriteria *lpSrc, struct searchCriteria **lppDst)
  1472. {
  1473. ECRESULT er = erSuccess;
  1474. struct searchCriteria *lpDst = NULL;
  1475. if (lpSrc == NULL)
  1476. return KCERR_NOT_FOUND;
  1477. lpDst = s_alloc<searchCriteria>(nullptr);
  1478. memset(lpDst, '\0', sizeof(*lpDst));
  1479. if(lpSrc->lpRestrict) {
  1480. er = CopyRestrictTable(soap, lpSrc->lpRestrict, &lpDst->lpRestrict);
  1481. if (er != erSuccess)
  1482. goto exit;
  1483. } else {
  1484. lpDst->lpRestrict = NULL;
  1485. }
  1486. if(lpSrc->lpFolders) {
  1487. er = CopyEntryList(soap, lpSrc->lpFolders, &lpDst->lpFolders);
  1488. if (er != erSuccess)
  1489. goto exit;
  1490. } else {
  1491. lpDst->lpFolders = NULL;
  1492. }
  1493. lpDst->ulFlags = lpSrc->ulFlags;
  1494. *lppDst = lpDst;
  1495. exit:
  1496. if (er != erSuccess && lpDst != NULL) {
  1497. FreeRestrictTable(lpDst->lpRestrict, true);
  1498. FreeEntryList(lpDst->lpFolders, true);
  1499. s_free(nullptr, lpDst);
  1500. }
  1501. return er;
  1502. }
  1503. ECRESULT FreeSearchCriteria(struct searchCriteria *lpSearchCriteria)
  1504. {
  1505. ECRESULT er = erSuccess;
  1506. if(lpSearchCriteria->lpRestrict)
  1507. FreeRestrictTable(lpSearchCriteria->lpRestrict);
  1508. if(lpSearchCriteria->lpFolders)
  1509. FreeEntryList(lpSearchCriteria->lpFolders);
  1510. s_free(nullptr, lpSearchCriteria);
  1511. return er;
  1512. }
  1513. /**
  1514. * Copy extra user details into propmap, (only the string values)
  1515. *
  1516. */
  1517. static ECRESULT CopyAnonymousDetailsToSoap(struct soap *soap,
  1518. const objectdetails_t &details, bool bCopyBinary,
  1519. struct propmapPairArray **lppsoapPropmap,
  1520. struct propmapMVPairArray **lppsoapMVPropmap)
  1521. {
  1522. ECRESULT er = erSuccess;
  1523. struct propmapPairArray *lpsoapPropmap = NULL;
  1524. struct propmapMVPairArray *lpsoapMVPropmap = NULL;
  1525. property_map propmap = details.GetPropMapAnonymous();
  1526. property_mv_map propmvmap = details.GetPropMapListAnonymous();
  1527. unsigned int j = 0;
  1528. if (!propmap.empty()) {
  1529. lpsoapPropmap = s_alloc<struct propmapPairArray>(soap, 1);
  1530. lpsoapPropmap->__size = 0;
  1531. lpsoapPropmap->__ptr = s_alloc<struct propmapPair>(soap, propmap.size());
  1532. for (const auto &iter : propmap) {
  1533. if (PROP_TYPE(iter.first) == PT_BINARY && bCopyBinary) {
  1534. string strData = base64_encode((const unsigned char *)iter.second.data(), iter.second.size());
  1535. lpsoapPropmap->__ptr[lpsoapPropmap->__size].ulPropId = iter.first;
  1536. lpsoapPropmap->__ptr[lpsoapPropmap->__size++].lpszValue = s_strcpy(soap, strData.c_str());
  1537. continue;
  1538. }
  1539. if (PROP_TYPE(iter.first) != PT_STRING8 && PROP_TYPE(iter.first) != PT_UNICODE)
  1540. continue;
  1541. lpsoapPropmap->__ptr[lpsoapPropmap->__size].ulPropId = iter.first;
  1542. lpsoapPropmap->__ptr[lpsoapPropmap->__size++].lpszValue = s_strcpy(soap, iter.second.c_str());
  1543. }
  1544. }
  1545. if (!propmvmap.empty()) {
  1546. lpsoapMVPropmap = s_alloc<struct propmapMVPairArray>(soap, 1);
  1547. lpsoapMVPropmap->__size = 0;
  1548. lpsoapMVPropmap->__ptr = s_alloc<struct propmapMVPair>(soap, propmvmap.size());
  1549. for (const auto &iter : propmvmap) {
  1550. if (PROP_TYPE(iter.first) == PT_MV_BINARY && bCopyBinary) {
  1551. j = 0;
  1552. lpsoapMVPropmap->__ptr[lpsoapMVPropmap->__size].ulPropId = iter.first;
  1553. lpsoapMVPropmap->__ptr[lpsoapMVPropmap->__size].sValues.__size = iter.second.size();
  1554. lpsoapMVPropmap->__ptr[lpsoapMVPropmap->__size].sValues.__ptr = s_alloc<char *>(soap, lpsoapMVPropmap->__ptr[lpsoapMVPropmap->__size].sValues.__size);
  1555. for (const auto &entry : iter.second) {
  1556. string strData = base64_encode(reinterpret_cast<const unsigned char *>(entry.data()), entry.size());
  1557. lpsoapMVPropmap->__ptr[lpsoapMVPropmap->__size].sValues.__ptr[j] = s_strcpy(soap, strData.c_str());
  1558. ++j;
  1559. }
  1560. ++lpsoapMVPropmap->__size;
  1561. continue;
  1562. }
  1563. if (PROP_TYPE(iter.first) != PT_MV_STRING8 && PROP_TYPE(iter.first) != PT_MV_UNICODE)
  1564. continue;
  1565. j = 0;
  1566. lpsoapMVPropmap->__ptr[lpsoapMVPropmap->__size].ulPropId = iter.first;
  1567. lpsoapMVPropmap->__ptr[lpsoapMVPropmap->__size].sValues.__size = iter.second.size();
  1568. lpsoapMVPropmap->__ptr[lpsoapMVPropmap->__size].sValues.__ptr = s_alloc<char *>(soap, lpsoapMVPropmap->__ptr[lpsoapMVPropmap->__size].sValues.__size);
  1569. for (const auto &entry : iter.second) {
  1570. lpsoapMVPropmap->__ptr[lpsoapMVPropmap->__size].sValues.__ptr[j] = s_strcpy(soap, entry.c_str());
  1571. ++j;
  1572. }
  1573. ++lpsoapMVPropmap->__size;
  1574. }
  1575. }
  1576. if (lppsoapPropmap)
  1577. *lppsoapPropmap = lpsoapPropmap;
  1578. if (lppsoapMVPropmap)
  1579. *lppsoapMVPropmap = lpsoapMVPropmap;
  1580. return er;
  1581. }
  1582. static ECRESULT
  1583. CopyAnonymousDetailsFromSoap(struct propmapPairArray *lpsoapPropmap,
  1584. struct propmapMVPairArray *lpsoapMVPropmap, objectdetails_t *details)
  1585. {
  1586. if (lpsoapPropmap) {
  1587. for (gsoap_size_t i = 0; i < lpsoapPropmap->__size; ++i)
  1588. if (PROP_TYPE(lpsoapPropmap->__ptr[i].ulPropId) == PT_BINARY) {
  1589. string strData = base64_decode(lpsoapPropmap->__ptr[i].lpszValue);
  1590. details->SetPropString((property_key_t)lpsoapPropmap->__ptr[i].ulPropId, strData);
  1591. } else if (PROP_TYPE(lpsoapPropmap->__ptr[i].ulPropId) == PT_STRING8) {
  1592. details->SetPropString((property_key_t)lpsoapPropmap->__ptr[i].ulPropId, lpsoapPropmap->__ptr[i].lpszValue);
  1593. }
  1594. }
  1595. if (lpsoapMVPropmap)
  1596. for (gsoap_size_t i = 0; i < lpsoapMVPropmap->__size; ++i) {
  1597. details->SetPropListString((property_key_t)lpsoapMVPropmap->__ptr[i].ulPropId, list<string>());
  1598. for (gsoap_size_t j = 0; j < lpsoapMVPropmap->__ptr[i].sValues.__size; ++j)
  1599. if (PROP_TYPE(lpsoapMVPropmap->__ptr[i].ulPropId) == PT_MV_BINARY) {
  1600. string strData = base64_decode(lpsoapMVPropmap->__ptr[i].sValues.__ptr[j]);
  1601. details->AddPropString((property_key_t)lpsoapMVPropmap->__ptr[i].ulPropId, strData);
  1602. } else {
  1603. details->AddPropString((property_key_t)lpsoapMVPropmap->__ptr[i].ulPropId, lpsoapMVPropmap->__ptr[i].sValues.__ptr[j]);
  1604. }
  1605. }
  1606. return erSuccess;
  1607. }
  1608. ECRESULT CopyUserDetailsToSoap(unsigned int ulId, entryId *lpUserEid, const objectdetails_t &details, bool bCopyBinary, struct soap *soap, struct user *lpUser)
  1609. {
  1610. ECRESULT er = erSuccess;
  1611. const objectclass_t objClass = details.GetClass();
  1612. // assert(OBJECTCLASS_TYPE(objClass) == OBJECTTYPE_MAILUSER);
  1613. lpUser->ulUserId = ulId;
  1614. lpUser->lpszUsername = s_strcpy(soap, details.GetPropString(OB_PROP_S_LOGIN).c_str());
  1615. lpUser->ulIsNonActive = (objClass == ACTIVE_USER ? 0 : 1); // Needed for pre 6.40 clients
  1616. lpUser->ulObjClass = objClass;
  1617. lpUser->lpszMailAddress = s_strcpy(soap, details.GetPropString(OB_PROP_S_EMAIL).c_str());
  1618. lpUser->lpszFullName = s_strcpy(soap, details.GetPropString(OB_PROP_S_FULLNAME).c_str());
  1619. lpUser->ulIsAdmin = details.GetPropInt(OB_PROP_I_ADMINLEVEL);
  1620. lpUser->lpszPassword = const_cast<char *>("");
  1621. lpUser->lpszServername = s_strcpy(soap, details.GetPropString(OB_PROP_S_SERVERNAME).c_str());
  1622. lpUser->ulIsABHidden = details.GetPropBool(OB_PROP_B_AB_HIDDEN);
  1623. lpUser->ulCapacity = details.GetPropInt(OB_PROP_I_RESOURCE_CAPACITY);
  1624. lpUser->lpsPropmap = NULL;
  1625. lpUser->lpsMVPropmap = NULL;
  1626. CopyAnonymousDetailsToSoap(soap, details, bCopyBinary, &lpUser->lpsPropmap, &lpUser->lpsMVPropmap);
  1627. // Lazy copy
  1628. lpUser->sUserId.__size = lpUserEid->__size;
  1629. lpUser->sUserId.__ptr = lpUserEid->__ptr;
  1630. return er;
  1631. }
  1632. ECRESULT CopyUserDetailsFromSoap(struct user *lpUser, string *lpstrExternId, objectdetails_t *details, struct soap *soap)
  1633. {
  1634. ECRESULT er = erSuccess;
  1635. if (lpUser->lpszUsername)
  1636. details->SetPropString(OB_PROP_S_LOGIN, lpUser->lpszUsername);
  1637. if (lpUser->lpszMailAddress)
  1638. details->SetPropString(OB_PROP_S_EMAIL, lpUser->lpszMailAddress);
  1639. if (lpUser->ulIsAdmin != (ULONG)-1)
  1640. details->SetPropInt(OB_PROP_I_ADMINLEVEL, lpUser->ulIsAdmin);
  1641. if (lpUser->ulObjClass != (ULONG)-1)
  1642. details->SetClass((objectclass_t)lpUser->ulObjClass);
  1643. if (lpUser->lpszFullName)
  1644. details->SetPropString(OB_PROP_S_FULLNAME, lpUser->lpszFullName);
  1645. if (lpUser->lpszPassword)
  1646. details->SetPropString(OB_PROP_S_PASSWORD, lpUser->lpszPassword);
  1647. if (lpstrExternId)
  1648. details->SetPropObject(OB_PROP_O_EXTERNID, objectid_t(*lpstrExternId, details->GetClass()));
  1649. if (lpUser->lpszServername)
  1650. details->SetPropString(OB_PROP_S_SERVERNAME, lpUser->lpszServername);
  1651. if (lpUser->ulIsABHidden != (ULONG)-1)
  1652. details->SetPropBool(OB_PROP_B_AB_HIDDEN, !!lpUser->ulIsABHidden);
  1653. if (lpUser->ulCapacity != (ULONG)-1)
  1654. details->SetPropInt(OB_PROP_I_RESOURCE_CAPACITY, lpUser->ulCapacity);
  1655. CopyAnonymousDetailsFromSoap(lpUser->lpsPropmap, lpUser->lpsMVPropmap, details);
  1656. return er;
  1657. }
  1658. ECRESULT CopyGroupDetailsToSoap(unsigned int ulId, entryId *lpGroupEid, const objectdetails_t &details, bool bCopyBinary, struct soap *soap, struct group *lpGroup)
  1659. {
  1660. ECRESULT er = erSuccess;
  1661. // assert(OBJECTCLASS_TYPE(details.GetClass()) == OBJECTTYPE_DISTLIST);
  1662. lpGroup->ulGroupId = ulId;
  1663. lpGroup->lpszGroupname = s_strcpy(soap, details.GetPropString(OB_PROP_S_LOGIN).c_str());
  1664. lpGroup->lpszFullname = s_strcpy(soap, details.GetPropString(OB_PROP_S_FULLNAME).c_str());
  1665. lpGroup->lpszFullEmail = s_strcpy(soap, details.GetPropString(OB_PROP_S_EMAIL).c_str());
  1666. lpGroup->ulIsABHidden = details.GetPropBool(OB_PROP_B_AB_HIDDEN);
  1667. lpGroup->lpsPropmap = NULL;
  1668. lpGroup->lpsMVPropmap = NULL;
  1669. CopyAnonymousDetailsToSoap(soap, details, bCopyBinary, &lpGroup->lpsPropmap, &lpGroup->lpsMVPropmap);
  1670. // Lazy copy
  1671. lpGroup->sGroupId.__size = lpGroupEid->__size;
  1672. lpGroup->sGroupId.__ptr = lpGroupEid->__ptr;
  1673. return er;
  1674. }
  1675. ECRESULT CopyGroupDetailsFromSoap(struct group *lpGroup, string *lpstrExternId, objectdetails_t *details, struct soap *soap)
  1676. {
  1677. ECRESULT er = erSuccess;
  1678. if (lpGroup->lpszGroupname)
  1679. details->SetPropString(OB_PROP_S_LOGIN, lpGroup->lpszGroupname);
  1680. if (lpGroup->lpszFullname)
  1681. details->SetPropString(OB_PROP_S_FULLNAME, lpGroup->lpszFullname);
  1682. if (lpGroup->lpszFullEmail)
  1683. details->SetPropString(OB_PROP_S_EMAIL, lpGroup->lpszFullEmail);
  1684. if (lpstrExternId)
  1685. details->SetPropObject(OB_PROP_O_EXTERNID, objectid_t(*lpstrExternId, details->GetClass()));
  1686. if (lpGroup->ulIsABHidden != (ULONG)-1)
  1687. details->SetPropBool(OB_PROP_B_AB_HIDDEN, !!lpGroup->ulIsABHidden);
  1688. CopyAnonymousDetailsFromSoap(lpGroup->lpsPropmap, lpGroup->lpsMVPropmap, details);
  1689. return er;
  1690. }
  1691. ECRESULT CopyCompanyDetailsToSoap(unsigned int ulId, entryId *lpCompanyEid, unsigned int ulAdmin, entryId *lpAdminEid, const objectdetails_t &details, bool bCopyBinary, struct soap *soap, struct company *lpCompany)
  1692. {
  1693. ECRESULT er = erSuccess;
  1694. // assert(details.GetClass() == CONTAINER_COMPANY);
  1695. lpCompany->ulCompanyId = ulId;
  1696. lpCompany->lpszCompanyname = s_strcpy(soap, details.GetPropString(OB_PROP_S_FULLNAME).c_str());
  1697. lpCompany->ulAdministrator = ulAdmin;
  1698. lpCompany->lpszServername = s_strcpy(soap, details.GetPropString(OB_PROP_S_SERVERNAME).c_str());
  1699. lpCompany->ulIsABHidden = details.GetPropBool(OB_PROP_B_AB_HIDDEN);
  1700. lpCompany->lpsPropmap = NULL;
  1701. lpCompany->lpsMVPropmap = NULL;
  1702. CopyAnonymousDetailsToSoap(soap, details, bCopyBinary, &lpCompany->lpsPropmap, &lpCompany->lpsMVPropmap);
  1703. // Lazy copy
  1704. lpCompany->sCompanyId.__size = lpCompanyEid->__size;
  1705. lpCompany->sCompanyId.__ptr = lpCompanyEid->__ptr;
  1706. // Lazy copy
  1707. lpCompany->sAdministrator.__size = lpAdminEid->__size;
  1708. lpCompany->sAdministrator.__ptr = lpAdminEid->__ptr;
  1709. return er;
  1710. }
  1711. ECRESULT CopyCompanyDetailsFromSoap(struct company *lpCompany, string *lpstrExternId, unsigned int ulAdmin, objectdetails_t *details, struct soap *soap)
  1712. {
  1713. ECRESULT er = erSuccess;
  1714. if (lpCompany->lpszCompanyname)
  1715. details->SetPropString(OB_PROP_S_FULLNAME, lpCompany->lpszCompanyname);
  1716. if (lpCompany->lpszServername)
  1717. details->SetPropString(OB_PROP_S_SERVERNAME, lpCompany->lpszServername);
  1718. if (lpstrExternId)
  1719. details->SetPropObject(OB_PROP_O_EXTERNID, objectid_t(*lpstrExternId, details->GetClass()));
  1720. if (ulAdmin)
  1721. details->SetPropInt(OB_PROP_I_SYSADMIN, ulAdmin);
  1722. if (lpCompany->ulIsABHidden != (ULONG)-1)
  1723. details->SetPropBool(OB_PROP_B_AB_HIDDEN, !!lpCompany->ulIsABHidden);
  1724. CopyAnonymousDetailsFromSoap(lpCompany->lpsPropmap, lpCompany->lpsMVPropmap, details);
  1725. return er;
  1726. }
  1727. DynamicPropValArray::DynamicPropValArray(struct soap *soap,
  1728. unsigned int ulHint) :
  1729. m_soap(soap), m_ulCapacity(ulHint)
  1730. {
  1731. m_lpPropVals = s_alloc<struct propVal>(m_soap, m_ulCapacity);
  1732. }
  1733. DynamicPropValArray::~DynamicPropValArray()
  1734. {
  1735. if (m_lpPropVals == nullptr || m_soap != nullptr)
  1736. return;
  1737. for (unsigned int i = 0; i < m_ulPropCount; ++i)
  1738. FreePropVal(&m_lpPropVals[i], false);
  1739. s_free(nullptr, m_lpPropVals);
  1740. }
  1741. ECRESULT DynamicPropValArray::AddPropVal(struct propVal &propVal)
  1742. {
  1743. ECRESULT er;
  1744. if(m_ulCapacity == m_ulPropCount) {
  1745. if(m_ulCapacity == 0)
  1746. ++m_ulCapacity;
  1747. er = Resize(m_ulCapacity * 2);
  1748. if(er != erSuccess)
  1749. return er;
  1750. }
  1751. er = CopyPropVal(&propVal, &m_lpPropVals[m_ulPropCount], m_soap);
  1752. if(er != erSuccess)
  1753. return er;
  1754. ++m_ulPropCount;
  1755. return erSuccess;
  1756. }
  1757. ECRESULT DynamicPropValArray::GetPropValArray(struct propValArray *lpPropValArray)
  1758. {
  1759. ECRESULT er = erSuccess;
  1760. lpPropValArray->__size = m_ulPropCount;
  1761. lpPropValArray->__ptr = m_lpPropVals; // Transfer ownership to the caller
  1762. m_lpPropVals = NULL; // We don't own these anymore
  1763. m_ulPropCount = 0;
  1764. m_ulCapacity = 0;
  1765. return er;
  1766. }
  1767. ECRESULT DynamicPropValArray::Resize(unsigned int ulSize)
  1768. {
  1769. ECRESULT er;
  1770. struct propVal *lpNew = NULL;
  1771. if (ulSize < m_ulCapacity)
  1772. return KCERR_INVALID_PARAMETER;
  1773. lpNew = s_alloc_nothrow<struct propVal>(m_soap, ulSize);
  1774. if (lpNew == NULL)
  1775. return KCERR_NOT_ENOUGH_MEMORY;
  1776. for (unsigned int i = 0; i < m_ulPropCount; ++i) {
  1777. er = CopyPropVal(&m_lpPropVals[i], &lpNew[i], m_soap);
  1778. if(er != erSuccess)
  1779. return er;
  1780. }
  1781. if(!m_soap) {
  1782. for (unsigned int i = 0; i < m_ulPropCount; ++i)
  1783. FreePropVal(&m_lpPropVals[i], false);
  1784. s_free(nullptr, m_lpPropVals);
  1785. }
  1786. m_lpPropVals = lpNew;
  1787. m_ulCapacity = ulSize;
  1788. return erSuccess;
  1789. }
  1790. DynamicPropTagArray::DynamicPropTagArray(struct soap *soap)
  1791. {
  1792. m_soap = soap;
  1793. }
  1794. ECRESULT DynamicPropTagArray::AddPropTag(unsigned int ulPropTag) {
  1795. m_lstPropTags.push_back(ulPropTag);
  1796. return erSuccess;
  1797. }
  1798. BOOL DynamicPropTagArray::HasPropTag(unsigned int ulPropTag) const {
  1799. return std::find(m_lstPropTags.begin(), m_lstPropTags.end(), ulPropTag) != m_lstPropTags.end();
  1800. }
  1801. ECRESULT DynamicPropTagArray::GetPropTagArray(struct propTagArray *lpsPropTagArray) {
  1802. size_t n = 0;
  1803. lpsPropTagArray->__size = m_lstPropTags.size();
  1804. lpsPropTagArray->__ptr = s_alloc<unsigned int>(m_soap, lpsPropTagArray->__size);
  1805. for (auto tag : m_lstPropTags)
  1806. lpsPropTagArray->__ptr[n++] = tag;
  1807. return erSuccess;
  1808. }
  1809. /**
  1810. * Calculate the propValArray size
  1811. *
  1812. * @param[in] lpSrc Pointer to a propVal array object
  1813. *
  1814. * @return the size of the object. If there is an error, object size is zero.
  1815. */
  1816. size_t PropValArraySize(const struct propValArray *lpSrc)
  1817. {
  1818. if (lpSrc == NULL)
  1819. return 0;
  1820. size_t ulSize = sizeof(struct propValArray) * lpSrc->__size;
  1821. for (gsoap_size_t i = 0; i < lpSrc->__size; ++i)
  1822. ulSize += PropSize(&lpSrc->__ptr[i]);
  1823. return ulSize;
  1824. }
  1825. /**
  1826. * Calculate the restrict table size
  1827. *
  1828. * @param[in] lpSrc Ponter to a restrict table object
  1829. * @return the size of the object. If there is an error, object size is zero.
  1830. */
  1831. size_t RestrictTableSize(const struct restrictTable *lpSrc)
  1832. {
  1833. size_t ulSize = 0;
  1834. if (lpSrc == NULL)
  1835. return 0;
  1836. switch(lpSrc->ulType) {
  1837. case RES_OR:
  1838. ulSize += sizeof(restrictOr);
  1839. for (gsoap_size_t i = 0; i < lpSrc->lpOr->__size; ++i)
  1840. ulSize += RestrictTableSize(lpSrc->lpOr->__ptr[i]);
  1841. break;
  1842. case RES_AND:
  1843. ulSize += sizeof(restrictAnd);
  1844. for (gsoap_size_t i = 0; i < lpSrc->lpAnd->__size; ++i)
  1845. ulSize += RestrictTableSize(lpSrc->lpAnd->__ptr[i]);
  1846. break;
  1847. case RES_NOT:
  1848. ulSize += sizeof(restrictNot);
  1849. ulSize += RestrictTableSize(lpSrc->lpNot->lpNot);
  1850. break;
  1851. case RES_CONTENT:
  1852. ulSize += sizeof(restrictContent);
  1853. if(lpSrc->lpContent->lpProp) {
  1854. ulSize += PropSize(lpSrc->lpContent->lpProp);
  1855. }
  1856. break;
  1857. case RES_PROPERTY:
  1858. ulSize += sizeof(restrictProp);
  1859. ulSize += PropSize(lpSrc->lpProp->lpProp);
  1860. break;
  1861. case RES_COMPAREPROPS:
  1862. ulSize += sizeof(restrictCompare);
  1863. break;
  1864. case RES_BITMASK:
  1865. ulSize += sizeof(restrictBitmask);
  1866. break;
  1867. case RES_SIZE:
  1868. ulSize += sizeof(restrictSize);
  1869. break;
  1870. case RES_EXIST:
  1871. ulSize += sizeof(restrictExist);
  1872. break;
  1873. case RES_COMMENT:
  1874. ulSize += sizeof(restrictComment) + sizeof(restrictTable);
  1875. ulSize += PropValArraySize(&lpSrc->lpComment->sProps);
  1876. ulSize += RestrictTableSize(lpSrc->lpComment->lpResTable);
  1877. break;
  1878. case RES_SUBRESTRICTION:
  1879. ulSize += sizeof(restrictSub);
  1880. ulSize += RestrictTableSize(lpSrc->lpSub->lpSubObject);
  1881. break;
  1882. default:
  1883. break;
  1884. }
  1885. return ulSize;
  1886. }
  1887. /**
  1888. * Calculate the size of a list of entries
  1889. *
  1890. * @param[in] lpSrc pointer to a list of entries
  1891. * @return the size of the object. If there is an error, object size is zero.
  1892. */
  1893. size_t EntryListSize(const struct entryList *lpSrc)
  1894. {
  1895. if (lpSrc == NULL)
  1896. return 0;
  1897. size_t ulSize = sizeof(entryList);
  1898. ulSize += sizeof(entryId) * lpSrc->__size;
  1899. for (unsigned int i = 0; i < lpSrc->__size; ++i)
  1900. ulSize += lpSrc->__ptr[i].__size * sizeof(unsigned char);
  1901. return ulSize;
  1902. }
  1903. /**
  1904. * Calculate the size of a proptag array
  1905. *
  1906. * @param[in] pPropTagArray Pointer to a array of property tags
  1907. * @return the size of the object. If there is an error, object size is zero.
  1908. */
  1909. size_t PropTagArraySize(const struct propTagArray *pPropTagArray)
  1910. {
  1911. return (pPropTagArray)?((sizeof(unsigned int) * pPropTagArray->__size) + sizeof(struct propTagArray)) : 0;
  1912. }
  1913. /**
  1914. * Calculate the size of the search criteria object
  1915. *
  1916. * @param[in] lpSrc Pointer to a search criteria object.
  1917. * @return the size of the object. If there is an error, object size is zero.
  1918. */
  1919. size_t SearchCriteriaSize(const struct searchCriteria *lpSrc)
  1920. {
  1921. if (lpSrc == NULL)
  1922. return 0;
  1923. size_t ulSize = sizeof(struct searchCriteria);
  1924. if(lpSrc->lpRestrict) {
  1925. ulSize += RestrictTableSize(lpSrc->lpRestrict);
  1926. }
  1927. if(lpSrc->lpFolders) {
  1928. ulSize += EntryListSize(lpSrc->lpFolders);
  1929. }
  1930. return ulSize;
  1931. }
  1932. /**
  1933. * Calculate the size of a entryid
  1934. *
  1935. * @param[in] lpEntryid Pointer to an entryid object.
  1936. * @return the size of the object. If there is an error, object size is zero.
  1937. */
  1938. size_t EntryIdSize(const entryId *lpEntryid)
  1939. {
  1940. if(lpEntryid == NULL)
  1941. return 0;
  1942. return sizeof(entryId) + lpEntryid->__size;
  1943. }
  1944. /**
  1945. * Calculate the size of a notification struct
  1946. *
  1947. * @param[in] lpNotification Pointer to a notification struct.
  1948. * @return the size of the object. If there is an error, object size is zero.
  1949. */
  1950. size_t NotificationStructSize(const notification *lpNotification)
  1951. {
  1952. if (lpNotification == NULL)
  1953. return 0;
  1954. size_t ulSize = sizeof(notification);
  1955. if(lpNotification->tab != NULL) {
  1956. ulSize += sizeof(notificationTable);
  1957. ulSize += PropSize(&lpNotification->tab->propIndex);
  1958. ulSize += PropSize(&lpNotification->tab->propPrior);
  1959. ulSize += PropValArraySize(lpNotification->tab->pRow);
  1960. }else if(lpNotification->obj != NULL) {
  1961. ulSize += sizeof(notificationObject);
  1962. ulSize += EntryIdSize(lpNotification->obj->pEntryId);
  1963. ulSize += EntryIdSize(lpNotification->obj->pParentId);
  1964. ulSize += EntryIdSize(lpNotification->obj->pOldId);
  1965. ulSize += EntryIdSize(lpNotification->obj->pOldParentId);
  1966. ulSize += PropTagArraySize(lpNotification->obj->pPropTagArray);
  1967. }else if(lpNotification->newmail != NULL){
  1968. ulSize += sizeof(notificationNewMail);
  1969. ulSize += EntryIdSize(lpNotification->newmail->pEntryId);
  1970. ulSize += EntryIdSize(lpNotification->newmail->pParentId);
  1971. if(lpNotification->newmail->lpszMessageClass) {
  1972. ulSize += (unsigned int)strlen(lpNotification->newmail->lpszMessageClass)+1;
  1973. }
  1974. }else if(lpNotification->ics != NULL){
  1975. ulSize += sizeof(notificationICS);
  1976. ulSize += EntryIdSize(lpNotification->ics->pSyncState);
  1977. }
  1978. return ulSize;
  1979. }
  1980. /**
  1981. * Calculate the size of a sort order array.
  1982. *
  1983. * @param[in] lpsSortOrder Pointer to a sort order array.
  1984. * @return the size of the object. If there is an error, object size is zero.
  1985. */
  1986. size_t SortOrderArraySize(const struct sortOrderArray *lpsSortOrder)
  1987. {
  1988. if (lpsSortOrder == NULL)
  1989. return 0;
  1990. return sizeof(struct sortOrder) * lpsSortOrder->__size;
  1991. }
  1992. /**
  1993. * Normalize the property tag to the local property type depending on -DUNICODE:
  1994. *
  1995. * With -DUNICODE, the function:
  1996. * - replaces PT_STRING8 with PT_UNICODE
  1997. * - replaces PT_MV_STRING8 with PT_MV_UNICODE
  1998. * Without -DUNICODE, it:
  1999. * - replaces PT_UNICODE with PT_STRING8
  2000. * - replaces PT_MV_UNICODE with PT_MV_STRING8
  2001. */
  2002. ULONG NormalizePropTag(ULONG ulPropTag)
  2003. {
  2004. if((PROP_TYPE(ulPropTag) == PT_STRING8 || PROP_TYPE(ulPropTag) == PT_UNICODE) && PROP_TYPE(ulPropTag) != PT_TSTRING) {
  2005. return CHANGE_PROP_TYPE(ulPropTag, PT_TSTRING);
  2006. }
  2007. if((PROP_TYPE(ulPropTag) == PT_MV_STRING8 || PROP_TYPE(ulPropTag) == PT_MV_UNICODE) && PROP_TYPE(ulPropTag) != PT_MV_TSTRING) {
  2008. return CHANGE_PROP_TYPE(ulPropTag, PT_MV_TSTRING);
  2009. }
  2010. return ulPropTag;
  2011. }
  2012. /**
  2013. * Get logical source address for a request
  2014. *
  2015. * Normally returns the string representation of the IP address of the connected client. However,
  2016. * when a proxy is detected (bProxy is true) and an X-Forwarded-From header is available, returns
  2017. * the contents of that header
  2018. *
  2019. * @param[in] soap Soap object of the request
  2020. * @result String representation of the requester's source address, valid for as long as the soap object exists.
  2021. */
  2022. const char *GetSourceAddr(struct soap *soap)
  2023. {
  2024. if (soap_info(soap)->bProxy && soap->proxy_from != nullptr)
  2025. return soap->proxy_from;
  2026. else
  2027. return soap->host;
  2028. }
  2029. } /* namespace */