ECUserStoreTable.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  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 <new>
  18. #include <kopano/platform.h>
  19. #include "ECDatabase.h"
  20. #include <mapidefs.h>
  21. #include <edkmdb.h>
  22. #include "ECSecurity.h"
  23. #include "ECSessionManager.h"
  24. #include "ECUserStoreTable.h"
  25. #include "ECGenProps.h"
  26. #include "ECSession.h"
  27. #include <kopano/stringutil.h>
  28. namespace KC {
  29. // 1 == MAPI_STORE.. does it even matter?
  30. ECUserStoreTable::ECUserStoreTable(ECSession *lpSession, unsigned int ulFlags, const ECLocale &locale) :
  31. ECGenericObjectTable(lpSession, 1, ulFlags, locale)
  32. {
  33. // Set callback function for queryrowdata (again?)
  34. m_lpfnQueryRowData = QueryRowData;
  35. }
  36. ECRESULT ECUserStoreTable::Create(ECSession *lpSession, unsigned int ulFlags, const ECLocale &locale, ECUserStoreTable **lppTable)
  37. {
  38. *lppTable = new(std::nothrow) ECUserStoreTable(lpSession, ulFlags, locale);
  39. if (*lppTable == nullptr)
  40. return KCERR_NOT_ENOUGH_MEMORY;
  41. (*lppTable)->AddRef();
  42. return erSuccess;
  43. }
  44. ECRESULT ECUserStoreTable::QueryRowData(ECGenericObjectTable *lpThis, struct soap *soap, ECSession *lpSession, ECObjectTableList* lpRowList, struct propTagArray *lpsPropTagArray, void* lpObjectData, struct rowSet **lppRowSet, bool bCacheTableData, bool bTableLimit)
  45. {
  46. auto pThis = dynamic_cast<ECUserStoreTable *>(lpThis);
  47. if (pThis == nullptr)
  48. return KCERR_INVALID_PARAMETER;
  49. struct rowSet *lpsRowSet = NULL;
  50. gsoap_size_t i;
  51. GUID sZeroGuid = {0};
  52. lpsRowSet = s_alloc<rowSet>(soap);
  53. lpsRowSet->__size = 0;
  54. lpsRowSet->__ptr = NULL;
  55. if(lpRowList->empty()) {
  56. *lppRowSet = lpsRowSet;
  57. return erSuccess;
  58. }
  59. // We return a square array with all the values
  60. lpsRowSet->__size = lpRowList->size();
  61. lpsRowSet->__ptr = s_alloc<propValArray>(soap, lpsRowSet->__size);
  62. memset(lpsRowSet->__ptr, 0, sizeof(propValArray) * lpsRowSet->__size);
  63. // Allocate memory for all rows
  64. for (i = 0; i < lpsRowSet->__size; ++i) {
  65. lpsRowSet->__ptr[i].__size = lpsPropTagArray->__size;
  66. lpsRowSet->__ptr[i].__ptr = s_alloc<propVal>(soap, lpsPropTagArray->__size);
  67. memset(lpsRowSet->__ptr[i].__ptr, 0, sizeof(propVal) * lpsPropTagArray->__size);
  68. }
  69. i = 0;
  70. for (const auto &row : *lpRowList) {
  71. for (gsoap_size_t k = 0; k < lpsPropTagArray->__size; ++k) {
  72. lpsRowSet->__ptr[i].__ptr[k].ulPropTag = PROP_TAG(PT_ERROR, lpsPropTagArray->__ptr[k]);
  73. lpsRowSet->__ptr[i].__ptr[k].__union = SOAP_UNION_propValData_ul;
  74. lpsRowSet->__ptr[i].__ptr[k].Value.ul = KCERR_NOT_FOUND;
  75. switch (PROP_ID(lpsPropTagArray->__ptr[k])) {
  76. case PROP_ID(PR_INSTANCE_KEY):
  77. // generate key
  78. lpsRowSet->__ptr[i].__ptr[k].__union = SOAP_UNION_propValData_bin;
  79. lpsRowSet->__ptr[i].__ptr[k].ulPropTag = PR_INSTANCE_KEY;
  80. lpsRowSet->__ptr[i].__ptr[k].Value.bin = s_alloc<xsd__base64Binary>(soap);
  81. lpsRowSet->__ptr[i].__ptr[k].Value.bin->__size = sizeof(sObjectTableKey);
  82. lpsRowSet->__ptr[i].__ptr[k].Value.bin->__ptr = s_alloc<unsigned char>(soap, sizeof(sObjectTableKey));
  83. memcpy(lpsRowSet->__ptr[i].__ptr[k].Value.bin->__ptr, &row, sizeof(sObjectTableKey));
  84. break;
  85. case PROP_ID(PR_EC_USERNAME):
  86. if (!pThis->m_mapUserStoreData[row.ulObjId].strUsername.empty()) {
  87. lpsRowSet->__ptr[i].__ptr[k].ulPropTag = lpsPropTagArray->__ptr[k];
  88. lpsRowSet->__ptr[i].__ptr[k].__union = SOAP_UNION_propValData_lpszA;
  89. lpsRowSet->__ptr[i].__ptr[k].Value.lpszA = s_strcpy(soap, const_cast<char *>(pThis->m_mapUserStoreData[row.ulObjId].strUsername.c_str()));
  90. }
  91. break;
  92. case PROP_ID(PR_DISPLAY_NAME):
  93. if (!pThis->m_mapUserStoreData[row.ulObjId].strGuessname.empty()) {
  94. lpsRowSet->__ptr[i].__ptr[k].ulPropTag = lpsPropTagArray->__ptr[k];
  95. lpsRowSet->__ptr[i].__ptr[k].__union = SOAP_UNION_propValData_lpszA;
  96. lpsRowSet->__ptr[i].__ptr[k].Value.lpszA = s_strcpy(soap, const_cast<char *>(pThis->m_mapUserStoreData[row.ulObjId].strGuessname.c_str()));
  97. }
  98. break;
  99. case PROP_ID(PR_EC_STOREGUID):
  100. if (pThis->m_mapUserStoreData[row.ulObjId].sGuid != sZeroGuid) {
  101. lpsRowSet->__ptr[i].__ptr[k].ulPropTag = lpsPropTagArray->__ptr[k];
  102. lpsRowSet->__ptr[i].__ptr[k].__union = SOAP_UNION_propValData_bin;
  103. lpsRowSet->__ptr[i].__ptr[k].Value.bin = s_alloc<xsd__base64Binary>(soap);
  104. lpsRowSet->__ptr[i].__ptr[k].Value.bin->__size = sizeof(GUID);
  105. lpsRowSet->__ptr[i].__ptr[k].Value.bin->__ptr = s_alloc<unsigned char>(soap, sizeof(GUID));
  106. memcpy(lpsRowSet->__ptr[i].__ptr[k].Value.bin->__ptr, &pThis->m_mapUserStoreData[row.ulObjId].sGuid, sizeof(GUID));
  107. }
  108. break;
  109. case PROP_ID(PR_EC_STORETYPE):
  110. lpsRowSet->__ptr[i].__ptr[k].ulPropTag = lpsPropTagArray->__ptr[k];
  111. lpsRowSet->__ptr[i].__ptr[k].__union = SOAP_UNION_propValData_ul;
  112. lpsRowSet->__ptr[i].__ptr[k].Value.ul = pThis->m_mapUserStoreData[row.ulObjId].ulStoreType;
  113. break;
  114. case PROP_ID(PR_EC_COMPANYID):
  115. if (pThis->m_mapUserStoreData[row.ulObjId].ulCompanyId != 0) {
  116. lpsRowSet->__ptr[i].__ptr[k].ulPropTag = lpsPropTagArray->__ptr[k];
  117. lpsRowSet->__ptr[i].__ptr[k].__union = SOAP_UNION_propValData_ul;
  118. lpsRowSet->__ptr[i].__ptr[k].Value.ul = pThis->m_mapUserStoreData[row.ulObjId].ulCompanyId;
  119. }
  120. break;
  121. case PROP_ID(PR_EC_COMPANY_NAME):
  122. if (!pThis->m_mapUserStoreData[row.ulObjId].strCompanyName.empty()) {
  123. lpsRowSet->__ptr[i].__ptr[k].ulPropTag = lpsPropTagArray->__ptr[k];
  124. lpsRowSet->__ptr[i].__ptr[k].__union = SOAP_UNION_propValData_lpszA;
  125. lpsRowSet->__ptr[i].__ptr[k].Value.lpszA = s_strcpy(soap, const_cast<char *>(pThis->m_mapUserStoreData[row.ulObjId].strCompanyName.c_str()));
  126. }
  127. break;
  128. case PROP_ID(PR_STORE_ENTRYID):
  129. // ignore errors
  130. ECGenProps::GetPropComputedUncached(soap, NULL,
  131. lpSession, PR_STORE_ENTRYID,
  132. pThis->m_mapUserStoreData[row.ulObjId].ulObjId,
  133. 0, pThis->m_mapUserStoreData[row.ulObjId].ulObjId,
  134. 0, MAPI_STORE, &lpsRowSet->__ptr[i].__ptr[k]);
  135. break;
  136. case PROP_ID(PR_LAST_MODIFICATION_TIME):
  137. if (pThis->m_mapUserStoreData[row.ulObjId].tModTime != 0) {
  138. FILETIME ftTmp;
  139. UnixTimeToFileTime(pThis->m_mapUserStoreData[row.ulObjId].tModTime, &ftTmp);
  140. lpsRowSet->__ptr[i].__ptr[k].ulPropTag = lpsPropTagArray->__ptr[k];
  141. lpsRowSet->__ptr[i].__ptr[k].__union = SOAP_UNION_propValData_hilo;
  142. lpsRowSet->__ptr[i].__ptr[k].Value.hilo = s_alloc<struct hiloLong>(soap);
  143. lpsRowSet->__ptr[i].__ptr[k].Value.hilo->hi = ftTmp.dwHighDateTime;
  144. lpsRowSet->__ptr[i].__ptr[k].Value.hilo->lo = ftTmp.dwLowDateTime;
  145. }
  146. break;
  147. case PROP_ID(PR_MESSAGE_SIZE_EXTENDED):
  148. lpsRowSet->__ptr[i].__ptr[k].ulPropTag = lpsPropTagArray->__ptr[k];
  149. lpsRowSet->__ptr[i].__ptr[k].__union = SOAP_UNION_propValData_li;
  150. lpsRowSet->__ptr[i].__ptr[k].Value.li = pThis->m_mapUserStoreData[row.ulObjId].ullStoreSize;
  151. break;
  152. default:
  153. lpsRowSet->__ptr[i].__ptr[k].ulPropTag = PROP_TAG(PT_ERROR, lpsPropTagArray->__ptr[k]);
  154. lpsRowSet->__ptr[i].__ptr[k].__union = SOAP_UNION_propValData_ul;
  155. lpsRowSet->__ptr[i].__ptr[k].Value.ul = KCERR_NOT_FOUND;
  156. break;
  157. };
  158. }
  159. ++i;
  160. }
  161. *lppRowSet = lpsRowSet;
  162. return erSuccess;
  163. }
  164. ECRESULT ECUserStoreTable::Load() {
  165. ECRESULT er = erSuccess;
  166. ECListIntIterator i;
  167. ECDatabase *lpDatabase = NULL;
  168. DB_RESULT lpDBResult;
  169. DB_ROW lpDBRow = NULL;
  170. DB_LENGTHS lpDBLength = NULL;
  171. std::string strQuery;
  172. std::list<unsigned int> lstObjIds;
  173. ECUserStore sUserStore;
  174. int iRowId;
  175. ECUserManagement *lpUserManagement = lpSession->GetUserManagement();
  176. ECSecurity *lpSecurity = lpSession->GetSecurity();
  177. objectdetails_t sUserDetails;
  178. GUID sZeroGuid = {0};
  179. objectclass_t objclass = OBJECTCLASS_UNKNOWN;
  180. objectdetails_t sDetails;
  181. enum cols { USERID = 0, EXTERNID, OBJCLASS, UCOMPANY, STOREGUID, STORETYPE, USERNAME, SCOMPANY, HIERARCHYID, STORESIZE, MODTIME_HI, MODTIME_LO };
  182. er = lpSession->GetDatabase(&lpDatabase);
  183. if (er != erSuccess)
  184. return er;
  185. Clear();
  186. /*
  187. * The next query will first get the list of all users with their primary store details or NULL if
  188. * no primary store was found. Secondly it will get the list of all stores with their owner or NULL
  189. * if they're detached.
  190. * The most important difference id that the first query will return no store for users without a
  191. * primary store, even if they do have an archive store attached, while the second query will
  192. * return all stores types.
  193. */
  194. strQuery =
  195. " SELECT u.id, u.externid, u.objectclass, u.company, s.guid, s.type, s.user_name, s.company, s.hierarchy_id, p.val_longint, m.val_hi, m.val_lo FROM users AS u"
  196. " LEFT JOIN stores AS s ON s.user_id=u.id AND s.type=" + stringify(ECSTORE_TYPE_PRIVATE) + " LEFT JOIN hierarchy AS h ON h.id=s.hierarchy_id"
  197. " LEFT JOIN properties AS p ON p.hierarchyid=s.hierarchy_id and p.tag=0x0E08 and p.type=0x14"
  198. " LEFT JOIN properties AS m ON m.hierarchyid=s.hierarchy_id and m.tag=0x66A2 and m.type=0x40"
  199. " UNION"
  200. " SELECT u.id, u.externid, u.objectclass, u.company, s.guid, s.type, s.user_name, s.company, s.hierarchy_id, p.val_longint, m.val_hi, m.val_lo FROM users AS u"
  201. " RIGHT JOIN stores AS s ON s.user_id=u.id LEFT JOIN hierarchy AS h ON h.id=s.hierarchy_id"
  202. " LEFT JOIN properties AS p ON p.hierarchyid=s.hierarchy_id and p.tag=0x0E08 and p.type=0x14"
  203. " LEFT JOIN properties AS m ON m.hierarchyid=s.hierarchy_id and m.tag=0x66A2 and m.type=0x40";
  204. er = lpDatabase->DoSelect(strQuery, &lpDBResult);
  205. if(er != erSuccess)
  206. return er;
  207. iRowId = 0;
  208. while(1) {
  209. lpDBRow = lpDatabase->FetchRow(lpDBResult);
  210. if(lpDBRow == NULL)
  211. break;
  212. lpDBLength = lpDatabase->FetchRowLengths(lpDBResult);
  213. if (lpDBRow[OBJCLASS])
  214. objclass = (objectclass_t)atoi(lpDBRow[OBJCLASS]);
  215. if (lpDBRow[USERID]) {
  216. sUserStore.ulUserId = atoi(lpDBRow[USERID]);
  217. if (sUserStore.ulUserId == KOPANO_UID_SYSTEM) // everyone already filtered by object type
  218. continue;
  219. } else {
  220. sUserStore.ulUserId = -1;
  221. }
  222. sUserStore.ulCompanyId = 0;
  223. if (lpDBRow[UCOMPANY])
  224. sUserStore.ulCompanyId = atoi(lpDBRow[UCOMPANY]);
  225. if (lpDBRow[SCOMPANY])
  226. sUserStore.ulCompanyId = atoi(lpDBRow[SCOMPANY]); // might override from user.company
  227. // check if we're admin over this company
  228. if (lpSecurity->IsAdminOverUserObject(sUserStore.ulCompanyId) != erSuccess)
  229. continue;
  230. if (lpDBRow[EXTERNID]) {
  231. sUserStore.sExternId.id.assign(lpDBRow[EXTERNID], lpDBLength[EXTERNID]);
  232. sUserStore.sExternId.objclass = objclass;
  233. } else {
  234. sUserStore.sExternId.id.clear();
  235. sUserStore.sExternId.objclass = OBJECTCLASS_UNKNOWN;
  236. }
  237. sUserStore.strUsername.clear();
  238. // find and override real username if possible
  239. if (sUserStore.ulUserId != -1 && lpUserManagement->GetObjectDetails(sUserStore.ulUserId, &sUserDetails) == erSuccess) {
  240. if (lpSession->GetSessionManager()->IsDistributedSupported() &&
  241. sUserDetails.GetPropString(OB_PROP_S_SERVERNAME).compare(lpSession->GetSessionManager()->GetConfig()->GetSetting("server_name")) != 0)
  242. continue; // user not on this server
  243. sUserStore.strUsername = sUserDetails.GetPropString(OB_PROP_S_LOGIN);
  244. }
  245. sUserStore.sGuid = sZeroGuid;
  246. if (lpDBRow[STOREGUID])
  247. memcpy(&sUserStore.sGuid, lpDBRow[STOREGUID], lpDBLength[STOREGUID]);
  248. if (lpDBRow[STORETYPE])
  249. sUserStore.ulStoreType = atoi(lpDBRow[STORETYPE]);
  250. else
  251. sUserStore.ulStoreType = ECSTORE_TYPE_PRIVATE; // or invalid value?
  252. if (lpDBRow[USERNAME])
  253. sUserStore.strGuessname = lpDBRow[USERNAME];
  254. else
  255. sUserStore.strGuessname.clear();
  256. if (sUserStore.ulCompanyId > 0 && lpUserManagement->GetObjectDetails(sUserStore.ulCompanyId, &sDetails) == erSuccess)
  257. sUserStore.strCompanyName = sDetails.GetPropString(OB_PROP_S_LOGIN);
  258. if(lpDBRow[HIERARCHYID])
  259. sUserStore.ulObjId = atoui(lpDBRow[HIERARCHYID]);
  260. else
  261. sUserStore.ulObjId = 0;
  262. sUserStore.tModTime = 0;
  263. if(lpDBRow[MODTIME_HI] && lpDBRow[MODTIME_LO]) {
  264. FILETIME ft;
  265. ft.dwHighDateTime = atoui(lpDBRow[MODTIME_HI]);
  266. ft.dwLowDateTime = atoui(lpDBRow[MODTIME_LO]);
  267. sUserStore.tModTime = 0;
  268. FileTimeToUnixTime(ft, &sUserStore.tModTime);
  269. }
  270. if(lpDBRow[STORESIZE])
  271. sUserStore.ullStoreSize = atoll(lpDBRow[STORESIZE]);
  272. else
  273. sUserStore.ullStoreSize = 0;
  274. // add to table
  275. lstObjIds.push_back(iRowId);
  276. // remember details
  277. m_mapUserStoreData.insert(std::pair<unsigned int, ECUserStore>(iRowId++, sUserStore));
  278. }
  279. LoadRows(&lstObjIds, 0);
  280. return erSuccess;
  281. }
  282. } /* namespace KC */