ClientUtil.cpp 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023
  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 <algorithm>
  19. #include <memory>
  20. #include <cctype>
  21. #include "ClientUtil.h"
  22. #include <kopano/ECGetText.h>
  23. #include <mapi.h>
  24. #include <mapidefs.h>
  25. #include <mapiutil.h>
  26. #include <kopano/CommonUtil.h>
  27. #include "WSTransport.h"
  28. #include <kopano/ECConfig.h>
  29. #include "kcore.hpp"
  30. #include <kopano/ECGuid.h>
  31. #include <edkguid.h>
  32. #include <kopano/mapiguidext.h>
  33. #include <kopano/mapiext.h>
  34. #include <kopano/memory.hpp>
  35. #include "Mem.h"
  36. #include <kopano/stringutil.h>
  37. #include <kopano/charset/convstring.h>
  38. #include "EntryPoint.h"
  39. using namespace std;
  40. using namespace KCHL;
  41. // profile properties
  42. static constexpr const SizedSPropTagArray(22, sptaKopanoProfile) =
  43. {22, {PR_EC_PATH, PR_PROFILE_NAME_A, PR_EC_USERNAME_A,
  44. PR_EC_USERNAME_W, PR_EC_USERPASSWORD_A, PR_EC_USERPASSWORD_W,
  45. PR_EC_IMPERSONATEUSER_A, PR_EC_IMPERSONATEUSER_W, PR_EC_FLAGS,
  46. PR_EC_SSLKEY_FILE, PR_EC_SSLKEY_PASS, PR_EC_PROXY_HOST,
  47. PR_EC_PROXY_PORT, PR_EC_PROXY_USERNAME, PR_EC_PROXY_PASSWORD,
  48. PR_EC_PROXY_FLAGS, PR_EC_CONNECTION_TIMEOUT, PR_EC_OFFLINE_PATH_A,
  49. PR_EC_OFFLINE_PATH_W, PR_SERVICE_NAME,
  50. PR_EC_STATS_SESSION_CLIENT_APPLICATION_VERSION,
  51. PR_EC_STATS_SESSION_CLIENT_APPLICATION_MISC}};
  52. HRESULT ClientUtil::HrInitializeStatusRow (const char * lpszProviderDisplay, ULONG ulResourceType, LPMAPISUP lpMAPISup, LPSPropValue lpspvIdentity, ULONG ulFlags)
  53. {
  54. HRESULT hResult = hrSuccess;
  55. memory_ptr<SPropValue> lpspvStatusRow;
  56. ULONG cCurVal = 0;
  57. unsigned int size = 0;
  58. std::wstring wstrSearchKey;
  59. hResult = MAPIAllocateBuffer(sizeof(SPropValue) * 13, &~lpspvStatusRow);
  60. if(hResult != hrSuccess)
  61. return hResult;
  62. memset(lpspvStatusRow, 0, sizeof(SPropValue) * 13);
  63. if(lpszProviderDisplay)
  64. {
  65. size = strlen(lpszProviderDisplay)+1;
  66. // Set the PR_PROVIDER_DISPLAY property:
  67. lpspvStatusRow[cCurVal].ulPropTag = PR_PROVIDER_DISPLAY_A;
  68. hResult = MAPIAllocateMore(size, lpspvStatusRow, (void**)&lpspvStatusRow[cCurVal].Value.lpszA);
  69. if(hResult != hrSuccess)
  70. return hResult;
  71. memcpy(lpspvStatusRow[cCurVal].Value.lpszA, lpszProviderDisplay, size);
  72. ++cCurVal;
  73. // Set the PR_DISPLAY_NAME property
  74. lpspvStatusRow[cCurVal].ulPropTag = PR_DISPLAY_NAME_A;
  75. hResult = MAPIAllocateMore(size, lpspvStatusRow, (void**)&lpspvStatusRow[cCurVal].Value.lpszA);
  76. if(hResult != hrSuccess)
  77. return hResult;
  78. memcpy(lpspvStatusRow[cCurVal].Value.lpszA, lpszProviderDisplay, size);
  79. ++cCurVal;
  80. }
  81. // PR_PROVIDER_DLL_NAME
  82. lpspvStatusRow[cCurVal].ulPropTag = PR_PROVIDER_DLL_NAME_A;
  83. lpspvStatusRow[cCurVal++].Value.lpszA = (LPSTR)WCLIENT_DLL_NAME;
  84. // Set the PR_STATUS_CODE property:
  85. lpspvStatusRow[cCurVal].ulPropTag = PR_STATUS_CODE;
  86. lpspvStatusRow[cCurVal++].Value.l = 1;
  87. // Set the PR_STATUS_STRING property
  88. lpspvStatusRow[cCurVal].ulPropTag = PR_STATUS_STRING_W;
  89. lpspvStatusRow[cCurVal++].Value.lpszW = _W("Available");
  90. // Set the PR_IDENTITY_ENTRYID property
  91. lpspvStatusRow[cCurVal].ulPropTag = PR_IDENTITY_ENTRYID;
  92. lpspvStatusRow[cCurVal++].Value.bin = lpspvIdentity[XPID_EID].Value.bin;
  93. // Set the PR_IDENTITY_DISPLAY property
  94. lpspvStatusRow[cCurVal].ulPropTag = PROP_TAG(PROP_TYPE(lpspvIdentity[XPID_NAME].ulPropTag), PROP_ID(PR_IDENTITY_DISPLAY));
  95. lpspvStatusRow[cCurVal++].Value.LPSZ = lpspvIdentity[XPID_NAME].Value.LPSZ;
  96. // Set the PR_IDENTITY_SEARCH_KEY property
  97. lpspvStatusRow[cCurVal].ulPropTag = PR_IDENTITY_SEARCH_KEY;
  98. lpspvStatusRow[cCurVal++].Value.bin = lpspvIdentity[XPID_SEARCH_KEY].Value.bin;
  99. // Set the PR_OWN_STORE_ENTRYID property
  100. lpspvStatusRow[cCurVal].ulPropTag = PR_OWN_STORE_ENTRYID;
  101. lpspvStatusRow[cCurVal++].Value.bin = lpspvIdentity[XPID_STORE_EID].Value.bin;
  102. lpspvStatusRow[cCurVal].ulPropTag = PR_RESOURCE_METHODS;
  103. lpspvStatusRow[cCurVal++].Value.l = STATUS_VALIDATE_STATE;
  104. lpspvStatusRow[cCurVal].ulPropTag = PR_RESOURCE_TYPE;
  105. lpspvStatusRow[cCurVal++].Value.l = ulResourceType; //like MAPI_STORE_PROVIDER or MAPI_TRANSPORT_PROVIDER
  106. return lpMAPISup->ModifyStatusRow(cCurVal, lpspvStatusRow, ulFlags);
  107. }
  108. HRESULT ClientUtil::HrSetIdentity(WSTransport *lpTransport, LPMAPISUP lpMAPISup, LPSPropValue* lppIdentityProps)
  109. {
  110. HRESULT hr = hrSuccess;
  111. ULONG cbEntryStore = 0;
  112. memory_ptr<ENTRYID> lpEntryStore, lpEID;
  113. ULONG cbEID = 0;
  114. ULONG cValues = 0;
  115. ULONG ulSize = 0;
  116. memory_ptr<ECUSER> lpUser;
  117. tstring strProfileSenderSearchKey;
  118. memory_ptr<SPropValue> lpIdentityProps;
  119. // Get the username and email adress
  120. hr = lpTransport->HrGetUser(0, NULL, fMapiUnicode, &~lpUser);
  121. if(hr != hrSuccess)
  122. return hr;
  123. cValues = NUM_IDENTITY_PROPS;
  124. hr = MAPIAllocateBuffer(sizeof(SPropValue) * cValues, &~lpIdentityProps);
  125. if (hr != hrSuccess)
  126. return hr;
  127. memset(lpIdentityProps, 0, sizeof(SPropValue) * cValues);
  128. strProfileSenderSearchKey = strToUpper(tstring(TRANSPORT_ADDRESS_TYPE_ZARAFA) + _T(":") + lpUser->lpszMailAddress);
  129. lpIdentityProps[XPID_EID].ulPropTag = PR_SENDER_ENTRYID;
  130. lpIdentityProps[XPID_EID].Value.bin.cb = lpUser->sUserId.cb;
  131. hr = MAPIAllocateMore(lpUser->sUserId.cb, (LPVOID)lpIdentityProps, (void**)&lpIdentityProps[XPID_EID].Value.bin.lpb);
  132. if (hr != hrSuccess)
  133. return hr;
  134. memcpy(lpIdentityProps[XPID_EID].Value.bin.lpb, lpUser->sUserId.lpb, lpUser->sUserId.cb);
  135. // Create the PR_SENDER_NAME property value.
  136. lpIdentityProps[XPID_NAME].ulPropTag = PR_SENDER_NAME;
  137. ulSize = sizeof(TCHAR) * (_tcslen(lpUser->lpszFullName) + 1);
  138. hr = MAPIAllocateMore(ulSize, (LPVOID)lpIdentityProps , (void**)&lpIdentityProps[XPID_NAME].Value.LPSZ);
  139. if (hr != hrSuccess)
  140. return hr;
  141. memcpy(lpIdentityProps[XPID_NAME].Value.LPSZ, lpUser->lpszFullName, ulSize);
  142. // Create the PR_SENDER_SEARCH_KEY value.
  143. lpIdentityProps[XPID_SEARCH_KEY].ulPropTag = PR_SENDER_SEARCH_KEY;
  144. lpIdentityProps[XPID_SEARCH_KEY].Value.bin.cb = strProfileSenderSearchKey.size()+1;
  145. hr = MAPIAllocateMore(lpIdentityProps[XPID_SEARCH_KEY].Value.bin.cb, (LPVOID)lpIdentityProps , (void**)&lpIdentityProps[XPID_SEARCH_KEY].Value.bin.lpb);
  146. if (hr != hrSuccess)
  147. return hr;
  148. memcpy(lpIdentityProps[XPID_SEARCH_KEY].Value.bin.lpb, strProfileSenderSearchKey.c_str(), lpIdentityProps[XPID_SEARCH_KEY].Value.bin.cb);
  149. // PR_SENDER_EMAIL_ADDRESS
  150. lpIdentityProps[XPID_ADDRESS].ulPropTag = PR_SENDER_EMAIL_ADDRESS;
  151. ulSize = sizeof(TCHAR) * (_tcslen(lpUser->lpszMailAddress) + 1);
  152. hr = MAPIAllocateMore(ulSize, (LPVOID)lpIdentityProps , (void**)&lpIdentityProps[XPID_ADDRESS].Value.LPSZ);
  153. if (hr != hrSuccess)
  154. return hr;
  155. memcpy(lpIdentityProps[XPID_ADDRESS].Value.LPSZ, lpUser->lpszMailAddress, ulSize);
  156. // PR_SENDER_ADDRTYPE
  157. lpIdentityProps[XPID_ADDRTYPE].ulPropTag = PR_SENDER_ADDRTYPE;
  158. ulSize = sizeof(TCHAR) * (_tcslen(TRANSPORT_ADDRESS_TYPE_ZARAFA) + 1);
  159. hr = MAPIAllocateMore(ulSize, (LPVOID)lpIdentityProps , (void**)&lpIdentityProps[XPID_ADDRTYPE].Value.LPSZ);
  160. if (hr != hrSuccess)
  161. return hr;
  162. memcpy(lpIdentityProps[XPID_ADDRTYPE].Value.LPSZ, TRANSPORT_ADDRESS_TYPE_ZARAFA, ulSize);
  163. //PR_OWN_STORE_ENTRYID
  164. // Get the default store for this user, not an issue if it fails when not on home server
  165. if (lpTransport->HrGetStore(0, nullptr, &cbEntryStore, &~lpEntryStore, 0, nullptr) == hrSuccess) {
  166. hr = lpMAPISup->WrapStoreEntryID(cbEntryStore, lpEntryStore, &cbEID, (&~lpEID).as<ENTRYID>());
  167. if(hr != hrSuccess)
  168. return hr;
  169. lpIdentityProps[XPID_STORE_EID].ulPropTag = PR_OWN_STORE_ENTRYID;
  170. lpIdentityProps[XPID_STORE_EID].Value.bin.cb = cbEID;
  171. hr = MAPIAllocateMore(cbEID, (LPVOID)lpIdentityProps , (void**)&lpIdentityProps[XPID_STORE_EID].Value.bin.lpb);
  172. if (hr != hrSuccess)
  173. return hr;
  174. memcpy(lpIdentityProps[XPID_STORE_EID].Value.bin.lpb, lpEID.get(), cbEID);
  175. }
  176. // Set the identity in the global provider identity
  177. *lppIdentityProps = lpIdentityProps.release();
  178. return hrSuccess;
  179. }
  180. /**
  181. * ReadReceipt replace function of MAPI for windows. MAPI for windows
  182. * support only UNICODE properties. We still can't use the support
  183. * version, since mapi4linux doesn't implement it. We could move this
  184. * code there, but then outlook and webaccess will sent different read
  185. * receipt messages.
  186. *
  187. * @param[in] ulFlags 0 or MAPI_NON_READ
  188. * @param[in] lpReadMessage Original message to send read receipt for
  189. * @param[in,out] lppEmptyMessage Message to edit
  190. *
  191. * @return MAPI Error code
  192. */
  193. HRESULT ClientUtil::ReadReceipt(ULONG ulFlags, LPMESSAGE lpReadMessage, LPMESSAGE* lppEmptyMessage)
  194. {
  195. HRESULT hr = hrSuccess;
  196. memory_ptr<SPropValue> spv, dpv;
  197. ULONG ulMaxDestValues = 0;
  198. ULONG dval = 0;
  199. ULONG cSrcValues = 0;
  200. ULONG cbTmp = 0;
  201. memory_ptr<BYTE> lpByteTmp;
  202. const TCHAR *lpMsgClass = NULL;
  203. LPTSTR lpReportText = NULL;
  204. LPTSTR lpReadText = NULL;
  205. FILETIME ft;
  206. adrlist_ptr lpMods;
  207. std::wstring strName;
  208. std::wstring strType;
  209. std::wstring strAddress;
  210. tstring strBodyText;
  211. time_t zero = 0;
  212. time_t tt;
  213. struct tm* tm;
  214. char szTime[255];
  215. object_ptr<IStream> lpBodyStream;
  216. tstring tSubject;
  217. // The same properties as under windows
  218. enum ePropReadReceipt{ RR_REPORT_TAG, RR_CONVERSATION_TOPIC, RR_CONVERSATION_INDEX,
  219. RR_SEARCH_KEY, RR_MESSAGE_CLASS, RR_SENDER_SEARCH_KEY,
  220. RR_SUBJECT, RR_SUBJECT_PREFIX, RR_NORMALIZED_SUBJECT,
  221. RR_SENDER_NAME, RR_SENDER_ENTRYID, RR_SENDER_ADDRTYPE,
  222. RR_SENDER_EMAIL_ADDRESS, RR_REPORT_NAME, RR_REPORT_ENTRYID,
  223. RR_READ_RECEIPT_ENTRYID, RR_RECEIVED_BY_NAME, RR_RECEIVED_BY_ENTRYID, RR_RECEIVED_BY_ADDRTYPE, RR_RECEIVED_BY_EMAIL_ADDRESS,
  224. RR_PRIORITY, RR_IMPORTANCE, RR_SENT_REPRESENTING_NAME,
  225. RR_SENT_REPRESENTING_ENTRYID, RR_SENT_REPRESENTING_SEARCH_KEY, RR_RCVD_REPRESENTING_NAME, RR_RCVD_REPRESENTING_ENTRYID,
  226. RR_MESSAGE_DELIVERY_TIME, RR_CLIENT_SUBMIT_TIME, RR_DISPLAY_TO,
  227. RR_DISPLAY_CC, RR_DISPLAY_BCC, RR_SENSITIVITY,
  228. RR_INTERNET_MESSAGE_ID, RR_DELIVER_TIME, RR_SENT_REPRESENTING_ADDRTYPE, RR_SENT_REPRESENTING_EMAIL_ADDRESS,
  229. RR_MDN_DISPOSITION_TYPE, RR_MDN_DISPOSITION_SENDINGMODE};
  230. static constexpr const SizedSPropTagArray(39, sPropReadReceipt) =
  231. {39, { PR_REPORT_TAG, PR_CONVERSATION_TOPIC,
  232. PR_CONVERSATION_INDEX, PR_SEARCH_KEY, PR_MESSAGE_CLASS,
  233. PR_SENDER_SEARCH_KEY, PR_SUBJECT, PR_SUBJECT_PREFIX,
  234. PR_NORMALIZED_SUBJECT, PR_SENDER_NAME, PR_SENDER_ENTRYID,
  235. PR_SENDER_ADDRTYPE, PR_SENDER_EMAIL_ADDRESS, PR_REPORT_NAME,
  236. PR_REPORT_ENTRYID, PR_READ_RECEIPT_ENTRYID, PR_RECEIVED_BY_NAME,
  237. PR_RECEIVED_BY_ENTRYID, PR_RECEIVED_BY_ADDRTYPE,
  238. PR_RECEIVED_BY_EMAIL_ADDRESS, PR_PRIORITY, PR_IMPORTANCE,
  239. PR_SENT_REPRESENTING_NAME, PR_SENT_REPRESENTING_ENTRYID,
  240. PR_SENT_REPRESENTING_SEARCH_KEY, PR_RCVD_REPRESENTING_NAME,
  241. PR_RCVD_REPRESENTING_ENTRYID, PR_MESSAGE_DELIVERY_TIME,
  242. PR_CLIENT_SUBMIT_TIME, PR_DISPLAY_TO, PR_DISPLAY_CC,
  243. PR_DISPLAY_BCC, PR_SENSITIVITY, PR_INTERNET_MESSAGE_ID,
  244. PR_DELIVER_TIME, PR_SENT_REPRESENTING_ADDRTYPE,
  245. PR_SENT_REPRESENTING_EMAIL_ADDRESS, PR_MDN_DISPOSITION_TYPE,
  246. PR_MDN_DISPOSITION_SENDINGMODE}};
  247. // Check incoming parameters
  248. if (lpReadMessage == nullptr || lppEmptyMessage == nullptr ||
  249. *lppEmptyMessage == nullptr)
  250. return MAPI_E_INVALID_OBJECT;
  251. if ((ulFlags &~ MAPI_NON_READ) != 0)
  252. return MAPI_E_INVALID_PARAMETER;
  253. GetSystemTimeAsFileTime(&ft);
  254. if (ulFlags & MAPI_NON_READ) {
  255. lpMsgClass = _T("REPORT.IPM.Note.IPNNRN");
  256. lpReadText = _("Not read:");
  257. lpReportText = _("was not read because it expired before reading at time");
  258. }else{
  259. lpMsgClass = _T("REPORT.IPM.Note.IPNRN");
  260. lpReadText = _("Read:");
  261. lpReportText = _("was read on");
  262. }
  263. hr = lpReadMessage->GetProps(sPropReadReceipt, fMapiUnicode, &cSrcValues, &~spv);
  264. if(FAILED(hr) != hrSuccess)
  265. return hr;
  266. #define HAVE(tag) (spv[RR_ ## tag].ulPropTag != (PR_ ## tag))
  267. // important properties
  268. if (!HAVE(REPORT_ENTRYID))
  269. return MAPI_E_INVALID_PARAMETER;
  270. strBodyText = _("Your message");
  271. strBodyText+= _T("\r\n\r\n");
  272. if (HAVE(DISPLAY_TO)) {
  273. strBodyText+= _T("\t");
  274. strBodyText+= _("To:");
  275. strBodyText+= _T(" ");
  276. strBodyText += spv[RR_DISPLAY_TO].Value.LPSZ;
  277. strBodyText+= _T("\r\n");
  278. }
  279. if (HAVE(DISPLAY_CC)) {
  280. strBodyText+= _T("\t");
  281. strBodyText+= _("Cc:");
  282. strBodyText+= _T(" ");
  283. strBodyText += spv[RR_DISPLAY_CC].Value.LPSZ;
  284. strBodyText+= _T("\r\n");
  285. }
  286. if (HAVE(SUBJECT)) {
  287. strBodyText+= _T("\t");
  288. strBodyText+= _("Subject:");
  289. strBodyText+= _T(" ");
  290. strBodyText += spv[RR_SUBJECT].Value.LPSZ;
  291. strBodyText+= _T("\r\n");
  292. }
  293. if (HAVE(CLIENT_SUBMIT_TIME)) {
  294. strBodyText+= _T("\t");
  295. strBodyText+= _("Sent on:");
  296. strBodyText+= _T(" ");
  297. FileTimeToUnixTime(spv[RR_CLIENT_SUBMIT_TIME].Value.ft, &tt);
  298. tm = localtime(&tt);
  299. if (tm == NULL)
  300. tm = localtime(&zero);
  301. strftime(szTime, 255, "%c", tm);
  302. strBodyText+= convert_to<tstring>(szTime, strlen(szTime), CHARSET_CHAR);
  303. strBodyText+= _T("\r\n");
  304. }
  305. strBodyText+= _T("\r\n");
  306. strBodyText+= lpReportText;
  307. strBodyText+= _T(" ");
  308. FileTimeToUnixTime(ft, &tt);
  309. tm = localtime(&tt);
  310. if (tm == NULL)
  311. tm = localtime(&zero);
  312. strftime(szTime, 255, "%c", tm);
  313. strBodyText+= convert_to<tstring>(szTime, strlen(szTime), CHARSET_CHAR);
  314. strBodyText+= _T("\r\n");
  315. ulMaxDestValues = cSrcValues + 4;//+ default properties
  316. hr = MAPIAllocateBuffer(sizeof(SPropValue) * ulMaxDestValues, &~dpv);
  317. if(hr != hrSuccess)
  318. return hr;
  319. memset(dpv, 0, sizeof(SPropValue) * ulMaxDestValues);
  320. // Default properties
  321. dpv[dval].ulPropTag = PR_DELETE_AFTER_SUBMIT;
  322. dpv[dval++].Value.b = true;
  323. dpv[dval].ulPropTag = PR_READ_RECEIPT_REQUESTED;
  324. dpv[dval++].Value.b = false;
  325. dpv[dval].ulPropTag = PR_MESSAGE_FLAGS;
  326. dpv[dval++].Value.ul = 0;
  327. dpv[dval].ulPropTag = PR_MESSAGE_CLASS;
  328. dpv[dval++].Value.LPSZ = const_cast<TCHAR *>(lpMsgClass);
  329. dpv[dval].ulPropTag = PR_REPORT_TEXT;
  330. dpv[dval++].Value.LPSZ = lpReportText;
  331. dpv[dval].ulPropTag = PR_REPORT_TIME;
  332. dpv[dval++].Value.ft = ft;
  333. dpv[dval].ulPropTag = PR_SUBJECT_PREFIX;
  334. dpv[dval++].Value.LPSZ = lpReadText;
  335. if (HAVE(SUBJECT)) {
  336. dpv[dval].ulPropTag = PR_ORIGINAL_SUBJECT;
  337. dpv[dval++].Value.LPSZ = spv[RR_SUBJECT].Value.LPSZ;
  338. tSubject = tstring(lpReadText) + _T(" ") + spv[RR_SUBJECT].Value.LPSZ;
  339. dpv[dval].ulPropTag = PR_SUBJECT;
  340. dpv[dval++].Value.LPSZ = const_cast<TCHAR *>(tSubject.c_str());
  341. }else {
  342. dpv[dval].ulPropTag = PR_SUBJECT;
  343. dpv[dval++].Value.LPSZ = lpReadText;
  344. }
  345. if (HAVE(REPORT_TAG)) {
  346. dpv[dval].ulPropTag = PR_REPORT_TAG;
  347. dpv[dval++].Value.bin = spv[RR_REPORT_TAG].Value.bin;
  348. }
  349. if (HAVE(DISPLAY_TO)) {
  350. dpv[dval].ulPropTag = PR_ORIGINAL_DISPLAY_TO;
  351. dpv[dval++].Value.LPSZ = spv[RR_DISPLAY_TO].Value.LPSZ;
  352. }
  353. if (HAVE(DISPLAY_CC)) {
  354. dpv[dval].ulPropTag = PR_ORIGINAL_DISPLAY_CC;
  355. dpv[dval++].Value.LPSZ = spv[RR_DISPLAY_CC].Value.LPSZ;
  356. }
  357. if (HAVE(DISPLAY_BCC)) {
  358. dpv[dval].ulPropTag = PR_ORIGINAL_DISPLAY_BCC;
  359. dpv[dval++].Value.LPSZ = spv[RR_DISPLAY_BCC].Value.LPSZ;
  360. }
  361. if (HAVE(CLIENT_SUBMIT_TIME)) {
  362. dpv[dval].ulPropTag = PR_ORIGINAL_SUBMIT_TIME;
  363. dpv[dval++].Value.ft = spv[RR_CLIENT_SUBMIT_TIME].Value.ft;
  364. }
  365. if (HAVE(DELIVER_TIME)) {
  366. dpv[dval].ulPropTag = PR_ORIGINAL_DELIVERY_TIME;
  367. dpv[dval++].Value.ft = spv[RR_DELIVER_TIME].Value.ft;
  368. }
  369. if (HAVE(CONVERSATION_TOPIC)) {
  370. dpv[dval].ulPropTag = PR_CONVERSATION_TOPIC;
  371. dpv[dval++].Value.LPSZ = spv[RR_CONVERSATION_TOPIC].Value.LPSZ;
  372. }
  373. if (HAVE(CONVERSATION_INDEX) &&
  374. ScCreateConversationIndex(spv[RR_CONVERSATION_INDEX].Value.bin.cb, spv[RR_CONVERSATION_INDEX].Value.bin.lpb, &cbTmp, &~lpByteTmp) == hrSuccess)
  375. {
  376. hr = MAPIAllocateMore(cbTmp, dpv, reinterpret_cast<void **>(&dpv[dval].Value.bin.lpb));
  377. if(hr != hrSuccess)
  378. return hr;
  379. dpv[dval].Value.bin.cb = cbTmp;
  380. memcpy(dpv[dval].Value.bin.lpb, lpByteTmp, cbTmp);
  381. dpv[dval++].ulPropTag = PR_CONVERSATION_INDEX;
  382. }
  383. if (HAVE(IMPORTANCE)) {
  384. dpv[dval].ulPropTag = PR_IMPORTANCE;
  385. dpv[dval++].Value.ul = spv[RR_IMPORTANCE].Value.ul;
  386. }
  387. if (HAVE(PRIORITY)) {
  388. dpv[dval].ulPropTag = PR_PRIORITY;
  389. dpv[dval++].Value.ul = spv[RR_PRIORITY].Value.ul;
  390. }
  391. if (HAVE(SENDER_NAME)) {
  392. dpv[dval].ulPropTag = PR_ORIGINAL_SENDER_NAME;
  393. dpv[dval++].Value.LPSZ = spv[RR_SENDER_NAME].Value.LPSZ;
  394. }
  395. if (HAVE(SENDER_ADDRTYPE)) {
  396. dpv[dval].ulPropTag = PR_ORIGINAL_SENDER_ADDRTYPE;
  397. dpv[dval++].Value.LPSZ = spv[RR_SENDER_ADDRTYPE].Value.LPSZ;
  398. }
  399. if (HAVE(SENDER_ENTRYID)) {
  400. dpv[dval].ulPropTag = PR_ORIGINAL_SENDER_ENTRYID;
  401. dpv[dval++].Value.bin = spv[RR_SENDER_ENTRYID].Value.bin;
  402. }
  403. if (HAVE(SENDER_SEARCH_KEY)) {
  404. dpv[dval].ulPropTag = PR_ORIGINAL_SENDER_SEARCH_KEY;
  405. dpv[dval++].Value.bin = spv[RR_SENDER_SEARCH_KEY].Value.bin;
  406. }
  407. if (HAVE(SENDER_EMAIL_ADDRESS)) {
  408. dpv[dval].ulPropTag = PR_ORIGINAL_SENDER_EMAIL_ADDRESS;
  409. dpv[dval++].Value.LPSZ = spv[RR_SENDER_EMAIL_ADDRESS].Value.LPSZ;
  410. }
  411. if (HAVE(SENT_REPRESENTING_NAME)) {
  412. dpv[dval].ulPropTag = PR_ORIGINAL_SENT_REPRESENTING_NAME;
  413. dpv[dval++].Value.LPSZ = spv[RR_SENT_REPRESENTING_NAME].Value.LPSZ;
  414. }
  415. if (HAVE(SENT_REPRESENTING_ADDRTYPE)) {
  416. dpv[dval].ulPropTag = PR_ORIGINAL_SENT_REPRESENTING_ADDRTYPE;
  417. dpv[dval++].Value.LPSZ = spv[RR_SENT_REPRESENTING_ADDRTYPE].Value.LPSZ;
  418. }
  419. if (HAVE(SENT_REPRESENTING_ENTRYID)) {
  420. dpv[dval].ulPropTag = PR_ORIGINAL_SENT_REPRESENTING_ENTRYID;
  421. dpv[dval++].Value.bin = spv[RR_SENT_REPRESENTING_ENTRYID].Value.bin;
  422. }
  423. if (HAVE(SENT_REPRESENTING_SEARCH_KEY)) {
  424. dpv[dval].ulPropTag = PR_ORIGINAL_SENT_REPRESENTING_SEARCH_KEY;
  425. dpv[dval++].Value.bin = spv[RR_SENT_REPRESENTING_SEARCH_KEY].Value.bin;
  426. }
  427. if (HAVE(SENT_REPRESENTING_EMAIL_ADDRESS)) {
  428. dpv[dval].ulPropTag = PR_ORIGINAL_SENT_REPRESENTING_EMAIL_ADDRESS;
  429. dpv[dval++].Value.LPSZ = spv[RR_SENT_REPRESENTING_EMAIL_ADDRESS].Value.LPSZ;
  430. }
  431. if (HAVE(MDN_DISPOSITION_SENDINGMODE)) {
  432. dpv[dval].ulPropTag = PR_MDN_DISPOSITION_SENDINGMODE;
  433. dpv[dval++].Value.LPSZ = spv[RR_MDN_DISPOSITION_SENDINGMODE].Value.LPSZ;
  434. }
  435. if (HAVE(MDN_DISPOSITION_TYPE)) {
  436. dpv[dval].ulPropTag = PR_MDN_DISPOSITION_TYPE;
  437. dpv[dval++].Value.LPSZ = spv[RR_MDN_DISPOSITION_TYPE].Value.LPSZ;
  438. }
  439. // We are representing the person who received the email if we're sending the read receipt for someone else.
  440. if (HAVE(RECEIVED_BY_ENTRYID)) {
  441. dpv[dval].ulPropTag = PR_SENT_REPRESENTING_ENTRYID;
  442. dpv[dval++].Value = spv[RR_RECEIVED_BY_ENTRYID].Value;
  443. }
  444. if (HAVE(RECEIVED_BY_NAME)) {
  445. dpv[dval].ulPropTag = PR_SENT_REPRESENTING_NAME;
  446. dpv[dval++].Value = spv[RR_RECEIVED_BY_NAME].Value;
  447. }
  448. if (HAVE(RECEIVED_BY_EMAIL_ADDRESS)) {
  449. dpv[dval].ulPropTag = PR_SENT_REPRESENTING_EMAIL_ADDRESS;
  450. dpv[dval++].Value = spv[RR_RECEIVED_BY_EMAIL_ADDRESS].Value;
  451. }
  452. if (HAVE(RECEIVED_BY_ADDRTYPE)) {
  453. dpv[dval].ulPropTag = PR_SENT_REPRESENTING_ADDRTYPE;
  454. dpv[dval++].Value = spv[RR_RECEIVED_BY_ADDRTYPE].Value;
  455. }
  456. // PR_RCVD_REPRESENTING_NAME, PR_RCVD_REPRESENTING_ENTRYID
  457. if (HAVE(INTERNET_MESSAGE_ID)) {
  458. dpv[dval].ulPropTag = PR_INTERNET_MESSAGE_ID;
  459. dpv[dval++].Value.LPSZ = spv[RR_INTERNET_MESSAGE_ID].Value.LPSZ;
  460. }
  461. #undef HAVE
  462. hr = (*lppEmptyMessage)->OpenProperty(PR_BODY, &IID_IStream, 0, MAPI_CREATE | MAPI_MODIFY, &~lpBodyStream);
  463. if (hr != hrSuccess)
  464. return hr;
  465. hr = lpBodyStream->Write(strBodyText.c_str(), strBodyText.size() * sizeof(TCHAR), NULL);
  466. if (hr != hrSuccess)
  467. return hr;
  468. hr = lpBodyStream->Commit( 0 );//0 = STGC_DEFAULT
  469. if (hr != hrSuccess)
  470. return hr;
  471. hr = MAPIAllocateBuffer(CbNewADRLIST(1), &~lpMods);
  472. if (hr != hrSuccess)
  473. return hr;
  474. lpMods->cEntries = 1;
  475. hr = MAPIAllocateBuffer(sizeof(SPropValue) * 8, (void**)&lpMods->aEntries->rgPropVals);
  476. if (hr != hrSuccess)
  477. return hr;
  478. hr = ECParseOneOff(reinterpret_cast<ENTRYID *>(spv[RR_REPORT_ENTRYID].Value.bin.lpb), spv[RR_REPORT_ENTRYID].Value.bin.cb, strName, strType, strAddress);
  479. if (hr != hrSuccess)
  480. return hr;
  481. auto &pv = lpMods->aEntries->rgPropVals;
  482. pv[0].ulPropTag = PR_ENTRYID;
  483. pv[0].Value.bin = spv[RR_REPORT_ENTRYID].Value.bin;
  484. pv[1].ulPropTag = PR_ADDRTYPE_W;
  485. pv[1].Value.lpszW = const_cast<wchar_t *>(strType.c_str());
  486. pv[2].ulPropTag = PR_DISPLAY_NAME_W;
  487. pv[2].Value.lpszW = const_cast<wchar_t *>(strName.c_str());
  488. pv[3].ulPropTag = PR_TRANSMITABLE_DISPLAY_NAME_W;
  489. pv[3].Value.lpszW = const_cast<wchar_t *>(strName.c_str());
  490. pv[4].ulPropTag = PR_SMTP_ADDRESS_W;
  491. pv[4].Value.lpszW = const_cast<wchar_t *>(strAddress.c_str());
  492. pv[5].ulPropTag = PR_EMAIL_ADDRESS_W;
  493. pv[5].Value.lpszW = const_cast<wchar_t *>(strAddress.c_str());
  494. hr = HrCreateEmailSearchKey((LPSTR)strType.c_str(), (LPSTR)strAddress.c_str(), &cbTmp, &~lpByteTmp);
  495. if (hr != hrSuccess)
  496. return hr;
  497. pv[6].ulPropTag = PR_SEARCH_KEY;
  498. pv[6].Value.bin.cb = cbTmp;
  499. pv[6].Value.bin.lpb = lpByteTmp;
  500. pv[7].ulPropTag = PR_RECIPIENT_TYPE;
  501. pv[7].Value.ul = MAPI_TO;
  502. lpMods->aEntries->cValues = 8;
  503. hr = (*lppEmptyMessage)->ModifyRecipients(MODRECIP_ADD, lpMods);
  504. if (hr != hrSuccess)
  505. return hr;
  506. return (*lppEmptyMessage)->SetProps(dval, dpv, nullptr);
  507. }
  508. HRESULT ClientUtil::GetGlobalProfileProperties(LPMAPISUP lpMAPISup, struct sGlobalProfileProps* lpsProfileProps)
  509. {
  510. HRESULT hr = hrSuccess;
  511. object_ptr<IProfSect> lpGlobalProfSect;
  512. hr = lpMAPISup->OpenProfileSection((LPMAPIUID)pbGlobalProfileSectionGuid, MAPI_MODIFY, &~lpGlobalProfSect);
  513. if(hr != hrSuccess)
  514. return hr;
  515. return ClientUtil::GetGlobalProfileProperties(lpGlobalProfSect, lpsProfileProps);
  516. }
  517. HRESULT ClientUtil::GetGlobalProfileProperties(LPPROFSECT lpGlobalProfSect, struct sGlobalProfileProps* lpsProfileProps)
  518. {
  519. HRESULT hr = hrSuccess;
  520. memory_ptr<SPropValue> lpsPropArray, lpsEMSPropArray, lpPropEMS;
  521. ULONG cValues = 0;
  522. ULONG cEMSValues = 0;
  523. const SPropValue *lpProp = NULL;
  524. bool bIsEMS = false;
  525. if (lpGlobalProfSect == nullptr || lpsProfileProps == nullptr)
  526. return MAPI_E_INVALID_OBJECT;
  527. if (HrGetOneProp(lpGlobalProfSect, PR_PROFILE_UNRESOLVED_NAME, &~lpPropEMS) == hrSuccess || g_ulLoadsim)
  528. bIsEMS = true;
  529. if(bIsEMS) {
  530. static constexpr const SizedSPropTagArray(4, sptaEMSProfile) =
  531. {4, {PR_PROFILE_NAME_A, PR_PROFILE_UNRESOLVED_SERVER,
  532. PR_PROFILE_UNRESOLVED_NAME, PR_PROFILE_USER}};
  533. // This is an emulated MSEMS store. Get the properties we need and convert them to ZARAFA-style properties
  534. hr = lpGlobalProfSect->GetProps(sptaEMSProfile, 0, &cEMSValues, &~lpsEMSPropArray);
  535. if(FAILED(hr))
  536. return hr;
  537. hr = ConvertMSEMSProps(cEMSValues, lpsEMSPropArray, &cValues, &~lpsPropArray);
  538. if(FAILED(hr))
  539. return hr;
  540. } else {
  541. // Get the properties we need directly from the global profile section
  542. hr = lpGlobalProfSect->GetProps(sptaKopanoProfile, 0, &cValues, &~lpsPropArray);
  543. if(FAILED(hr))
  544. return hr;
  545. }
  546. if ((lpProp = PCpropFindProp(lpsPropArray, cValues, PR_EC_PATH)) != NULL)
  547. lpsProfileProps->strServerPath = lpProp->Value.lpszA;
  548. if ((lpProp = PCpropFindProp(lpsPropArray, cValues, PR_PROFILE_NAME_A)) != NULL)
  549. lpsProfileProps->strProfileName = lpProp->Value.lpszA;
  550. if ((lpProp = PCpropFindProp(lpsPropArray, cValues, PR_EC_USERNAME_W)) != NULL)
  551. lpsProfileProps->strUserName = convstring::from_SPropValue(lpProp);
  552. else if ((lpProp = PCpropFindProp(lpsPropArray, cValues, PR_EC_USERNAME_A)) != NULL)
  553. lpsProfileProps->strUserName = convstring::from_SPropValue(lpProp);
  554. if ((lpProp = PCpropFindProp(lpsPropArray, cValues, PR_EC_USERPASSWORD_W)) != NULL)
  555. lpsProfileProps->strPassword = convstring::from_SPropValue(lpProp);
  556. else if ((lpProp = PCpropFindProp(lpsPropArray, cValues, PR_EC_USERPASSWORD_A)) != NULL)
  557. lpsProfileProps->strPassword = convstring::from_SPropValue(lpProp);
  558. if ((lpProp = PCpropFindProp(lpsPropArray, cValues, PR_EC_IMPERSONATEUSER_W)) != NULL)
  559. lpsProfileProps->strImpersonateUser = convstring::from_SPropValue(lpProp);
  560. else if ((lpProp = PCpropFindProp(lpsPropArray, cValues, PR_EC_IMPERSONATEUSER_A)) != NULL)
  561. lpsProfileProps->strImpersonateUser = convstring::from_SPropValue(lpProp);
  562. if ((lpProp = PCpropFindProp(lpsPropArray, cValues, PR_EC_FLAGS)) != NULL)
  563. lpsProfileProps->ulProfileFlags = lpProp->Value.ul;
  564. else
  565. lpsProfileProps->ulProfileFlags = 0;
  566. if ((lpProp = PCpropFindProp(lpsPropArray, cValues, PR_EC_SSLKEY_FILE)) != NULL)
  567. lpsProfileProps->strSSLKeyFile = lpProp->Value.lpszA;
  568. if ((lpProp = PCpropFindProp(lpsPropArray, cValues, PR_EC_SSLKEY_PASS)) != NULL)
  569. lpsProfileProps->strSSLKeyPass = lpProp->Value.lpszA;
  570. if ((lpProp = PCpropFindProp(lpsPropArray, cValues, PR_EC_PROXY_HOST)) != NULL)
  571. lpsProfileProps->strProxyHost = lpProp->Value.lpszA;
  572. if ((lpProp = PCpropFindProp(lpsPropArray, cValues, PR_EC_PROXY_PORT)) != NULL)
  573. lpsProfileProps->ulProxyPort = lpProp->Value.ul;
  574. else
  575. lpsProfileProps->ulProxyPort = 0;
  576. if ((lpProp = PCpropFindProp(lpsPropArray, cValues, PR_EC_PROXY_FLAGS)) != NULL)
  577. lpsProfileProps->ulProxyFlags = lpProp->Value.ul;
  578. else
  579. lpsProfileProps->ulProxyFlags = 0;
  580. if ((lpProp = PCpropFindProp(lpsPropArray, cValues, PR_EC_PROXY_USERNAME)) != NULL)
  581. lpsProfileProps->strProxyUserName = lpProp->Value.lpszA;
  582. if ((lpProp = PCpropFindProp(lpsPropArray, cValues, PR_EC_PROXY_PASSWORD)) != NULL)
  583. lpsProfileProps->strProxyPassword = lpProp->Value.lpszA;
  584. if ((lpProp = PCpropFindProp(lpsPropArray, cValues, PR_EC_CONNECTION_TIMEOUT)) != NULL)
  585. lpsProfileProps->ulConnectionTimeOut = lpProp->Value.ul;
  586. else
  587. lpsProfileProps->ulConnectionTimeOut = 10;
  588. if ((lpProp = PCpropFindProp(lpsPropArray, cValues, PR_EC_OFFLINE_PATH_W)) != NULL)
  589. lpsProfileProps->strOfflinePath = convstring::from_SPropValue(lpProp);
  590. else if ((lpProp = PCpropFindProp(lpsPropArray, cValues, PR_EC_OFFLINE_PATH_A)) != NULL)
  591. lpsProfileProps->strOfflinePath = convstring::from_SPropValue(lpProp);
  592. if ((lpProp = PCpropFindProp(lpsPropArray, cValues, PR_EC_STATS_SESSION_CLIENT_APPLICATION_VERSION)) != NULL)
  593. lpsProfileProps->strClientAppVersion = lpProp->Value.lpszA;
  594. if ((lpProp = PCpropFindProp(lpsPropArray, cValues, PR_EC_STATS_SESSION_CLIENT_APPLICATION_MISC)) != NULL)
  595. lpsProfileProps->strClientAppMisc = lpProp->Value.lpszA;
  596. lpsProfileProps->bIsEMS = bIsEMS;
  597. return hrSuccess;
  598. }
  599. HRESULT ClientUtil::GetGlobalProfileDelegateStoresProp(LPPROFSECT lpGlobalProfSect, ULONG *lpcDelegates, LPBYTE *lppDelegateStores)
  600. {
  601. HRESULT hr = hrSuccess;
  602. memory_ptr<SPropValue> lpsPropValue;
  603. ULONG cValues = 0;
  604. SizedSPropTagArray(1, sPropTagArray);
  605. memory_ptr<BYTE> lpDelegateStores;
  606. if (lpGlobalProfSect == nullptr || lpcDelegates == nullptr ||
  607. lppDelegateStores == nullptr)
  608. return MAPI_E_INVALID_OBJECT;
  609. sPropTagArray.cValues = 1;
  610. sPropTagArray.aulPropTag[0] = PR_STORE_PROVIDERS;
  611. hr = lpGlobalProfSect->GetProps(sPropTagArray, 0, &cValues, &~lpsPropValue);
  612. if(hr != hrSuccess)
  613. return hr;
  614. if(lpsPropValue[0].Value.bin.cb > 0){
  615. hr = MAPIAllocateBuffer(lpsPropValue[0].Value.bin.cb, &~lpDelegateStores);
  616. if(hr != hrSuccess)
  617. return hr;
  618. memcpy(lpDelegateStores, lpsPropValue[0].Value.bin.lpb, lpsPropValue[0].Value.bin.cb);
  619. }
  620. *lpcDelegates = lpsPropValue[0].Value.bin.cb;
  621. *lppDelegateStores = lpDelegateStores.release();
  622. return hrSuccess;
  623. }
  624. /*
  625. * Read registry key to discover the installation directory for the exchange redirector
  626. *
  627. * @param[out] lpConfigPath String containing full config path
  628. */
  629. HRESULT ClientUtil::GetConfigPath(std::string *lpConfigPath)
  630. {
  631. return MAPI_E_NO_SUPPORT;
  632. }
  633. /**
  634. * Convert incoming MSEMS profile properties to ZARAFA properties
  635. *
  636. * Basically we take the username and servername from the exchange properties and set all other properties
  637. * by reading a configuration file.
  638. *
  639. * @param cValues[in] Number of props in pValues
  640. * @param pValues[in] Incoming exchange properties (must contain PR_PROFILE_UNRESOLVED_{USER,SERVER})
  641. * @param lpcValues[out] Number of properties in lppProps
  642. * @param lppProps[out] New ZARAFA properties
  643. */
  644. HRESULT ClientUtil::ConvertMSEMSProps(ULONG cValues, LPSPropValue pValues, ULONG *lpcValues, LPSPropValue *lppProps)
  645. {
  646. HRESULT hr = hrSuccess;
  647. memory_ptr<SPropValue> lpProps;
  648. char *szUsername;
  649. std::string strServerPath;
  650. std::wstring strUsername;
  651. ULONG cProps = 0;
  652. const SPropValue *lpServer = NULL;
  653. const SPropValue *lpUsername = NULL;
  654. const SPropValue *lpProfileName = NULL;
  655. static const configsetting_t settings[] = {
  656. { "ssl_port", "237" },
  657. { "ssl_key_file", "c:\\program files\\kopano\\exchange-redirector.pem" },
  658. { "ssl_key_pass", "kopano" },
  659. { "server_address", "" },
  660. { "log_method","file" },
  661. { "log_file","-" },
  662. { "log_level", "3", CONFIGSETTING_RELOADABLE },
  663. { "log_timestamp","1" },
  664. { "log_buffer_size", "0" },
  665. { NULL, NULL },
  666. };
  667. std::unique_ptr<ECConfig> lpConfig(ECConfig::Create(settings));
  668. std::string strConfigPath;
  669. hr = GetConfigPath(&strConfigPath);
  670. if(hr != hrSuccess) {
  671. TRACE_RELEASE("Unable to find config file (registry key missing)", (char *)strConfigPath.c_str());
  672. return hr;
  673. }
  674. // Remove trailing slash
  675. if(*(strConfigPath.end()-1) == '\\' )
  676. strConfigPath.resize(strConfigPath.size()-1);
  677. strConfigPath += "\\exchange-redirector.cfg";
  678. TRACE_RELEASE("Using config file '%s'", (char *)strConfigPath.c_str());
  679. if(!lpConfig->LoadSettings((char *)strConfigPath.c_str())) {
  680. TRACE_RELEASE("Unable to load config file '%s'", (char *)strConfigPath.c_str());
  681. return MAPI_E_NOT_FOUND;
  682. }
  683. if(g_ulLoadsim) {
  684. lpUsername = PCpropFindProp(pValues, cValues, PR_PROFILE_USER);
  685. if(!lpUsername) {
  686. TRACE_RELEASE("PR_PROFILE_USER not set");
  687. return MAPI_E_UNCONFIGURED;
  688. }
  689. } else {
  690. lpUsername = PCpropFindProp(pValues, cValues, PR_PROFILE_UNRESOLVED_NAME);
  691. lpServer = PCpropFindProp(pValues, cValues, PR_PROFILE_UNRESOLVED_SERVER);
  692. if(!lpServer || !lpUsername) {
  693. TRACE_RELEASE("PR_PROFILE_UNRESOLVED_NAME or PR_PROFILE_UNRESOLVED_SERVER not set");
  694. return MAPI_E_UNCONFIGURED;
  695. }
  696. }
  697. hr = MAPIAllocateBuffer(sizeof(SPropValue) * 7, &~lpProps);
  698. if (hr != hrSuccess)
  699. return hr;
  700. if (lpConfig->GetSetting("server_address")[0]) {
  701. strServerPath = (std::string)"https://" + lpConfig->GetSetting("server_address") + ":" + lpConfig->GetSetting("ssl_port") + "/";
  702. } else {
  703. if (lpServer == nullptr)
  704. return MAPI_E_UNCONFIGURED;
  705. strServerPath = (std::string)"https://" + lpServer->Value.lpszA + ":" + lpConfig->GetSetting("ssl_port") + "/";
  706. }
  707. szUsername = lpUsername->Value.lpszA;
  708. if(strrchr(szUsername, '='))
  709. szUsername = strrchr(szUsername, '=')+1;
  710. lpProps[cProps].ulPropTag = PR_EC_PATH;
  711. if ((hr = MAPIAllocateMore(strServerPath.size() + 1, lpProps, (void**)&lpProps[cProps].Value.lpszA)) != hrSuccess)
  712. return hr;
  713. strcpy(lpProps[cProps++].Value.lpszA, strServerPath.c_str());
  714. strUsername = convert_to<std::wstring>(szUsername);
  715. lpProps[cProps].ulPropTag = PR_EC_USERNAME;
  716. if ((hr = MAPIAllocateMore((strUsername.size() + 1) * sizeof(TCHAR), lpProps, (void**)&lpProps[cProps].Value.lpszW)) != hrSuccess)
  717. return hr;
  718. wcscpy(lpProps[cProps++].Value.lpszW, strUsername.c_str());
  719. lpProps[cProps].ulPropTag = PR_EC_USERPASSWORD;
  720. if ((hr = MAPIAllocateMore(sizeof(TCHAR), lpProps, (void**)&lpProps[cProps].Value.LPSZ)) != hrSuccess)
  721. return hr;
  722. _tcscpy(lpProps[cProps++].Value.LPSZ, L"");
  723. lpProps[cProps].ulPropTag = PR_EC_SSLKEY_FILE;
  724. if ((hr = MAPIAllocateMore(strlen(lpConfig->GetSetting("ssl_key_file")) + 1, lpProps, (void**)&lpProps[cProps].Value.lpszA)) != hrSuccess)
  725. return hr;
  726. strcpy(lpProps[cProps++].Value.lpszA, lpConfig->GetSetting("ssl_key_file"));
  727. lpProps[cProps].ulPropTag = PR_EC_SSLKEY_PASS;
  728. if ((hr = MAPIAllocateMore(strlen(lpConfig->GetSetting("ssl_key_pass")) + 1, lpProps, (void**)&lpProps[cProps].Value.lpszA)) != hrSuccess)
  729. return hr;
  730. strcpy(lpProps[cProps++].Value.lpszA, lpConfig->GetSetting("ssl_key_pass"));
  731. lpProps[cProps].ulPropTag = PR_EC_FLAGS; // Since we're emulating exchange, use 22-byte exchange-style sourcekeys
  732. lpProps[cProps++].Value.ul = EC_PROFILE_FLAGS_TRUNCATE_SOURCEKEY;
  733. lpProfileName = PCpropFindProp(pValues, cValues, PR_PROFILE_NAME_A);
  734. if(lpProfileName) {
  735. lpProps[cProps].ulPropTag = PR_PROFILE_NAME_A;
  736. if ((hr = MAPIAllocateMore(strlen(lpProfileName->Value.lpszA) + 1, lpProps, (void**)&lpProps[cProps].Value.lpszA)) != hrSuccess)
  737. return hr;
  738. strcpy(lpProps[cProps++].Value.lpszA, lpProfileName->Value.lpszA);
  739. }
  740. TRACE_RELEASE("Redirecting to %s", (char *)strServerPath.c_str());
  741. *lpcValues = cProps;
  742. *lppProps = lpProps;
  743. return hrSuccess;
  744. }
  745. /*
  746. entryid functions
  747. */
  748. HRESULT HrCreateEntryId(GUID guidStore, unsigned int ulObjType, ULONG* lpcbEntryId, LPENTRYID* lppEntryId)
  749. {
  750. HRESULT hr;
  751. EID eid;
  752. ULONG cbEntryId = 0;
  753. LPENTRYID lpEntryId = NULL;
  754. if (lpcbEntryId == NULL || lppEntryId == NULL)
  755. return MAPI_E_INVALID_PARAMETER;
  756. if (CoCreateGuid(&eid.uniqueId) != hrSuccess)
  757. return MAPI_E_CALL_FAILED;
  758. cbEntryId = CbNewEID("");
  759. hr = ECAllocateBuffer(cbEntryId, (void**)&lpEntryId);
  760. if(hr != hrSuccess)
  761. return hr;
  762. eid.guid = guidStore;
  763. eid.usType = ulObjType;
  764. memcpy(lpEntryId, &eid, cbEntryId);
  765. *lpcbEntryId = cbEntryId;
  766. *lppEntryId = lpEntryId;
  767. return hrSuccess;
  768. }
  769. /**
  770. * Extract the server URL from a store entryid.
  771. * @param[in] cbEntryId The length of the entryid pointed to by
  772. lpEntryId
  773. * @param[in] lpEntryId Pointer to the store entryid.
  774. * @param[out] rServerPath Reference to a std::string that will be
  775. * set to the server path extracted from
  776. * the entry id.
  777. * @param[out] lpbIsPseudoUrl Pointer to a boolean that will be set to
  778. * true if the extracted server path is a
  779. * pseudo URL.
  780. * @retval MAPI_E_INVALID_PARAMETER lpEntryId or lpbIsPseudoUrl is NULL
  781. * @retval MAPI_E_NOT_FOUND The extracted server path does not start
  782. * with http://, https://, file:// or pseudo://
  783. */
  784. HRESULT HrGetServerURLFromStoreEntryId(ULONG cbEntryId, LPENTRYID lpEntryId, std::string& rServerPath, bool *lpbIsPseudoUrl)
  785. {
  786. PEID peid = (PEID)lpEntryId;
  787. EID_V0* peid_V0 = NULL;
  788. ULONG ulMaxSize = 0;
  789. ULONG ulSize = 0;
  790. char* lpTmpServerName = NULL;
  791. bool bIsPseudoUrl = false;
  792. if (lpEntryId == NULL || lpbIsPseudoUrl == NULL)
  793. return MAPI_E_INVALID_PARAMETER;
  794. if (peid->ulVersion == 0)
  795. {
  796. peid_V0 = (EID_V0*)lpEntryId;
  797. ulMaxSize = cbEntryId - offsetof(EID_V0, szServer);
  798. ulSize = strnlen((char*)peid_V0->szServer, ulMaxSize);
  799. lpTmpServerName = (char*)peid_V0->szServer;
  800. } else {
  801. ulMaxSize = cbEntryId - offsetof(EID, szServer);
  802. ulSize = strnlen((char*)peid->szServer, ulMaxSize);
  803. lpTmpServerName = (char*)peid->szServer;
  804. }
  805. if (ulSize >= ulMaxSize)
  806. return MAPI_E_NOT_FOUND;
  807. if (strncasecmp(lpTmpServerName, "pseudo://", 9) == 0)
  808. bIsPseudoUrl = true;
  809. else if (strncasecmp(lpTmpServerName, "http://", 7) &&
  810. strncasecmp(lpTmpServerName, "https://", 8) &&
  811. strncasecmp(lpTmpServerName, "file://", 7) &&
  812. strncasecmp(lpTmpServerName, "default:", 8))
  813. return MAPI_E_NOT_FOUND;
  814. rServerPath = lpTmpServerName;
  815. *lpbIsPseudoUrl = bIsPseudoUrl;
  816. return hrSuccess;
  817. }
  818. /**
  819. * Resolve a pseudoURL
  820. * @param[in] lpTransport Pointer to a WebServices transport object
  821. * @param[in] lpszUrl C string containing pseudoURL.
  822. * @param[out] serverPath Reference to a std::string that will be
  823. * set to the iresolved server path.
  824. * @param[out] lpbIsPeer Pointer to a boolean that will be set to
  825. * true the server is a peer.
  826. * @retval MAPI_E_INVALID_PARAMETER lpTransport or lpszUrl are NULL
  827. * @retval MAPI_E_NOT_FOUND The extracted server path does not start
  828. * with pseudo://
  829. */
  830. HRESULT HrResolvePseudoUrl(WSTransport *lpTransport, const char *lpszUrl, std::string& serverPath, bool *lpbIsPeer)
  831. {
  832. HRESULT hr = hrSuccess;
  833. ecmem_ptr<char> lpszServerPath;
  834. bool bIsPeer = false;
  835. if (lpTransport == NULL || lpszUrl == NULL)
  836. return MAPI_E_INVALID_PARAMETER;
  837. if (strncmp(lpszUrl, "pseudo://", 9))
  838. return MAPI_E_NOT_FOUND;
  839. hr = lpTransport->HrResolvePseudoUrl(lpszUrl, &~lpszServerPath, &bIsPeer);
  840. if (hr != hrSuccess)
  841. return hr;
  842. serverPath = lpszServerPath.release();
  843. if (lpbIsPeer)
  844. *lpbIsPeer = bIsPeer;
  845. return hrSuccess;
  846. }
  847. HRESULT HrCompareEntryIdWithStoreGuid(ULONG cbEntryID, LPENTRYID lpEntryID, LPCGUID guidStore)
  848. {
  849. if (lpEntryID == NULL || guidStore == NULL)
  850. return MAPI_E_INVALID_PARAMETER;
  851. if (cbEntryID < 20)
  852. return MAPI_E_INVALID_ENTRYID;
  853. if (memcmp(lpEntryID->ab, guidStore, sizeof(GUID)) != 0)
  854. return MAPI_E_INVALID_ENTRYID;
  855. return hrSuccess;
  856. }
  857. HRESULT GetPublicEntryId(enumPublicEntryID ePublicEntryID, GUID guidStore, void *lpBase, ULONG *lpcbEntryID, LPENTRYID *lppEntryID)
  858. {
  859. HRESULT hr = hrSuccess;
  860. ULONG cbEntryID = 0;
  861. LPENTRYID lpEntryID = NULL;
  862. GUID guidEmpty = {0};
  863. EID eid = EID(MAPI_FOLDER, guidStore, guidEmpty);
  864. switch (ePublicEntryID) {
  865. case ePE_IPMSubtree:
  866. eid.uniqueId.Data4[7] = 1;
  867. break;
  868. case ePE_Favorites:
  869. eid.uniqueId.Data4[7] = 2;
  870. break;
  871. case ePE_PublicFolders:
  872. eid.uniqueId.Data4[7] = 3;
  873. break;
  874. default:
  875. return MAPI_E_INVALID_PARAMETER;
  876. }
  877. if (lpcbEntryID == NULL || lppEntryID == NULL)
  878. return MAPI_E_INVALID_PARAMETER;
  879. cbEntryID = CbEID(&eid);
  880. if (lpBase)
  881. hr = MAPIAllocateMore(cbEntryID, lpBase, (void**)&lpEntryID);
  882. else
  883. hr = MAPIAllocateBuffer(cbEntryID, (void**)&lpEntryID);
  884. if (hr != hrSuccess)
  885. return hr;
  886. memcpy(lpEntryID, &eid, cbEntryID);
  887. *lpcbEntryID = cbEntryID;
  888. *lppEntryID = lpEntryID;
  889. return hrSuccess;
  890. }
  891. BOOL CompareMDBProvider(LPBYTE lpguid, const GUID *lpguidKopano) {
  892. return CompareMDBProvider((MAPIUID*)lpguid, lpguidKopano);
  893. }
  894. BOOL CompareMDBProvider(MAPIUID* lpguid, const GUID *lpguidKopano)
  895. {
  896. if (memcmp(lpguid, lpguidKopano, sizeof(GUID)) == 0)
  897. return TRUE;
  898. return FALSE;
  899. }