ECConvenientDepthABObjectTable.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  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 <memory>
  19. #include <new>
  20. #include <utility>
  21. #include <kopano/tie.hpp>
  22. #include "ECDatabase.h"
  23. #include <mapidefs.h>
  24. #include <mapitags.h>
  25. #include <kopano/EMSAbTag.h>
  26. #include "ECSessionManager.h"
  27. #include "ECConvenientDepthABObjectTable.h"
  28. #include "ECSession.h"
  29. #include "ECMAPI.h"
  30. #include <kopano/stringutil.h>
  31. using namespace KCHL;
  32. namespace KC {
  33. ECConvenientDepthABObjectTable::ECConvenientDepthABObjectTable(ECSession *lpSession, unsigned int ulABId, unsigned int ulABType, unsigned int ulABParentId, unsigned int ulABParentType, unsigned int ulFlags, const ECLocale &locale) : ECABObjectTable(lpSession, ulABId, ulABType, ulABParentId, ulABParentType, ulFlags, locale) {
  34. m_lpfnQueryRowData = ECConvenientDepthABObjectTable::QueryRowData;
  35. /* We require the details to construct the PR_EMS_AB_HIERARCHY_PATH */
  36. m_ulUserManagementFlags &= ~USERMANAGEMENT_IDS_ONLY;
  37. }
  38. ECRESULT ECConvenientDepthABObjectTable::Create(ECSession *lpSession,
  39. unsigned int ulABId, unsigned int ulABType, unsigned int ulABParentId,
  40. unsigned int ulABParentType, unsigned int ulFlags, const ECLocale &locale,
  41. ECABObjectTable **lppTable)
  42. {
  43. *lppTable = new(std::nothrow) ECConvenientDepthABObjectTable(lpSession,
  44. ulABId, ulABType, ulABParentId, ulABParentType, ulFlags,
  45. locale);
  46. if (*lppTable == nullptr)
  47. return KCERR_NOT_ENOUGH_MEMORY;
  48. (*lppTable)->AddRef();
  49. return erSuccess;
  50. }
  51. /*
  52. * We override the standard QueryRowData call so that we can correctly generate PR_DEPTH and PR_EMS_AB_HIERARCHY_PARENT. Since this is
  53. * dependent on data which is not available for ECUserManagement, we have to do those properties here.
  54. */
  55. ECRESULT ECConvenientDepthABObjectTable::QueryRowData(ECGenericObjectTable *lpGenTable, struct soap *soap, ECSession *lpSession, ECObjectTableList* lpRowList, struct propTagArray *lpsPropTagArray, void* lpObjectData, struct rowSet **lppRowSet, bool bTableData,bool bTableLimit)
  56. {
  57. ECRESULT er;
  58. unsigned int n = 0;
  59. struct propVal *lpProp = NULL;
  60. auto lpThis = static_cast<ECConvenientDepthABObjectTable *>(lpGenTable);
  61. er = ECABObjectTable::QueryRowData(lpThis, soap, lpSession, lpRowList, lpsPropTagArray, lpObjectData, lppRowSet, bTableData, bTableLimit);
  62. if(er != erSuccess)
  63. return er;
  64. // Insert the PR_DEPTH for all the rows since the row engine has no knowledge of depth
  65. for (const auto &row : *lpRowList) {
  66. lpProp = FindProp(&(*lppRowSet)->__ptr[n], PROP_TAG(PT_ERROR, PROP_ID(PR_DEPTH)));
  67. if(lpProp) {
  68. lpProp->Value.ul = lpThis->m_mapDepth[row.ulObjId];
  69. lpProp->ulPropTag = PR_DEPTH;
  70. lpProp->__union = SOAP_UNION_propValData_ul;
  71. }
  72. lpProp = FindProp(&(*lppRowSet)->__ptr[n], PROP_TAG(PT_ERROR, PROP_ID(PR_EMS_AB_HIERARCHY_PATH)));
  73. if(lpProp) {
  74. lpProp->Value.lpszA = s_strcpy(soap, lpThis->m_mapPath[row.ulObjId].c_str());
  75. lpProp->ulPropTag = PR_EMS_AB_HIERARCHY_PATH;
  76. lpProp->__union = SOAP_UNION_propValData_lpszA;
  77. }
  78. ++n;
  79. }
  80. return erSuccess;
  81. }
  82. /*
  83. * Loads an entire multi-depth hierarchy table recursively.
  84. */
  85. ECRESULT ECConvenientDepthABObjectTable::Load()
  86. {
  87. auto lpODAB = static_cast<ECODAB *>(m_lpObjectData);
  88. sObjectTableKey sRowItem;
  89. std::list<CONTAINERINFO> lstObjects;
  90. CONTAINERINFO root;
  91. if (lpODAB->ulABType != MAPI_ABCONT)
  92. return KCERR_INVALID_PARAMETER;
  93. // Load this container
  94. root.ulId = lpODAB->ulABParentId;
  95. root.ulDepth = -1; // Our children are at depth 0, so the root object is depth -1. Note that this object is not actually added as a row in the end.
  96. root.strPath = "";
  97. lstObjects.push_back(std::move(root));
  98. // 'Recursively' loop through all our containers and add each of those children to our object list
  99. for (const auto &obj : lstObjects) {
  100. std::unique_ptr<std::list<localobjectdetails_t> > lpSubObjects;
  101. if (LoadHierarchyContainer(obj.ulId, 0, &unique_tie(lpSubObjects)) != erSuccess)
  102. continue;
  103. for (const auto &subobj : *lpSubObjects) {
  104. CONTAINERINFO folder;
  105. folder.ulId = subobj.ulId;
  106. folder.ulDepth = obj.ulDepth + 1;
  107. folder.strPath = obj.strPath + "/" + subobj.GetPropString(OB_PROP_S_LOGIN);
  108. lstObjects.push_back(std::move(folder));
  109. }
  110. }
  111. // Add all the rows into the row engine, except the root object (the folder itself does not show in its own hierarchy table)
  112. for (const auto &obj : lstObjects) {
  113. if (obj.ulId == lpODAB->ulABParentId)
  114. continue;
  115. m_mapDepth[obj.ulId] = obj.ulDepth;
  116. m_mapPath[obj.ulId] = obj.strPath;
  117. UpdateRow(ECKeyTable::TABLE_ROW_ADD, obj.ulId, 0);
  118. }
  119. return erSuccess;
  120. }
  121. } /* namespace */