LDAPCache.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  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 <kopano/lockhelper.hpp>
  19. #include "LDAPCache.h"
  20. #include "LDAPUserPlugin.h"
  21. #include <kopano/stringutil.h>
  22. LDAPCache::LDAPCache()
  23. {
  24. m_lpCompanyCache.reset(new dn_cache_t());
  25. m_lpGroupCache.reset(new dn_cache_t());
  26. m_lpUserCache.reset(new dn_cache_t());
  27. m_lpAddressListCache.reset(new dn_cache_t());
  28. }
  29. bool LDAPCache::isObjectTypeCached(objectclass_t objclass)
  30. {
  31. bool bCached = false;
  32. scoped_rlock biglock(m_hMutex);
  33. switch (objclass) {
  34. case OBJECTCLASS_USER:
  35. case ACTIVE_USER:
  36. case NONACTIVE_USER:
  37. case NONACTIVE_ROOM:
  38. case NONACTIVE_EQUIPMENT:
  39. case NONACTIVE_CONTACT:
  40. bCached = !m_lpUserCache->empty();
  41. break;
  42. case OBJECTCLASS_DISTLIST:
  43. case DISTLIST_GROUP:
  44. case DISTLIST_SECURITY:
  45. case DISTLIST_DYNAMIC:
  46. bCached = !m_lpGroupCache->empty();
  47. break;
  48. case CONTAINER_COMPANY:
  49. bCached = !m_lpCompanyCache->empty();
  50. break;
  51. case CONTAINER_ADDRESSLIST:
  52. bCached = !m_lpAddressListCache->empty();
  53. break;
  54. default:
  55. break;
  56. }
  57. return bCached;
  58. }
  59. void LDAPCache::setObjectDNCache(objectclass_t objclass,
  60. std::unique_ptr<dn_cache_t> lpCache)
  61. {
  62. /*
  63. * Always merge caches rather then overwritting them.
  64. */
  65. std::unique_ptr<dn_cache_t> lpTmp = getObjectDNCache(NULL, objclass);
  66. // cannot use insert() because it does not override existing entries
  67. for (const auto &i : *lpCache)
  68. (*lpTmp)[i.first] = i.second;
  69. lpCache = std::move(lpTmp);
  70. scoped_rlock biglock(m_hMutex);
  71. switch (objclass) {
  72. case OBJECTCLASS_USER:
  73. case ACTIVE_USER:
  74. case NONACTIVE_USER:
  75. case NONACTIVE_ROOM:
  76. case NONACTIVE_EQUIPMENT:
  77. case NONACTIVE_CONTACT:
  78. m_lpUserCache = std::move(lpCache);
  79. break;
  80. case OBJECTCLASS_DISTLIST:
  81. case DISTLIST_GROUP:
  82. case DISTLIST_SECURITY:
  83. case DISTLIST_DYNAMIC:
  84. m_lpGroupCache = std::move(lpCache);
  85. break;
  86. case CONTAINER_COMPANY:
  87. m_lpCompanyCache = std::move(lpCache);
  88. break;
  89. case CONTAINER_ADDRESSLIST:
  90. m_lpAddressListCache = std::move(lpCache);
  91. break;
  92. default:
  93. break;
  94. }
  95. }
  96. std::unique_ptr<dn_cache_t>
  97. LDAPCache::getObjectDNCache(LDAPUserPlugin *lpPlugin, objectclass_t objclass)
  98. {
  99. std::unique_ptr<dn_cache_t> cache;
  100. scoped_rlock biglock(m_hMutex);
  101. /* If item was not yet cached, make sure it is done now. */
  102. if (!isObjectTypeCached(objclass) && lpPlugin)
  103. lpPlugin->getAllObjects(objectid_t(), objclass); // empty company, so request all objects of type
  104. switch (objclass) {
  105. case OBJECTCLASS_USER:
  106. case ACTIVE_USER:
  107. case NONACTIVE_USER:
  108. case NONACTIVE_ROOM:
  109. case NONACTIVE_EQUIPMENT:
  110. case NONACTIVE_CONTACT:
  111. cache.reset(new dn_cache_t(*m_lpUserCache.get()));
  112. break;
  113. case OBJECTCLASS_DISTLIST:
  114. case DISTLIST_GROUP:
  115. case DISTLIST_SECURITY:
  116. case DISTLIST_DYNAMIC:
  117. cache.reset(new dn_cache_t(*m_lpGroupCache.get()));
  118. break;
  119. case CONTAINER_COMPANY:
  120. cache.reset(new dn_cache_t(*m_lpCompanyCache.get()));
  121. break;
  122. case CONTAINER_ADDRESSLIST:
  123. cache.reset(new dn_cache_t(*m_lpAddressListCache.get()));
  124. break;
  125. default:
  126. break;
  127. }
  128. return cache;
  129. }
  130. objectid_t LDAPCache::getParentForDN(const std::unique_ptr<dn_cache_t> &lpCache,
  131. const std::string &dn)
  132. {
  133. objectid_t entry;
  134. std::string parent_dn;
  135. if (lpCache->empty())
  136. return entry; /* empty */
  137. // @todo make sure we find the largest DN match
  138. for (const auto &i : *lpCache)
  139. /* Key should be larger then current guess, but has to be smaller then the userobject dn */
  140. /* If key matches the end of the userobject dn, we have a positive match */
  141. if (i.second.size() > parent_dn.size() && i.second.size() < dn.size() &&
  142. strcasecmp(dn.c_str() + (dn.size() - i.second.size()), i.second.c_str()) == 0) {
  143. parent_dn = i.second;
  144. entry = i.first;
  145. }
  146. /* Either empty, or the correct result */
  147. return entry;
  148. }
  149. std::unique_ptr<dn_list_t>
  150. LDAPCache::getChildrenForDN(const std::unique_ptr<dn_cache_t> &lpCache,
  151. const std::string &dn)
  152. {
  153. std::unique_ptr<dn_list_t> list(new dn_list_t());
  154. /* Find al DNs which are hierarchically below the given dn */
  155. for (const auto &i : *lpCache)
  156. /* Key should be larger then root DN */
  157. /* If key matches the end of the root dn, we have a positive match */
  158. if (i.second.size() > dn.size() &&
  159. strcasecmp(i.second.c_str() + (i.second.size() - dn.size()), dn.c_str()) == 0)
  160. list->push_back(i.second);
  161. return list;
  162. }
  163. std::string
  164. LDAPCache::getDNForObject(const std::unique_ptr<dn_cache_t> &lpCache,
  165. const objectid_t &externid)
  166. {
  167. dn_cache_t::const_iterator it = lpCache->find(externid);
  168. return it == lpCache->cend() ? std::string() : it->second;
  169. }
  170. bool LDAPCache::isDNInList(const std::unique_ptr<dn_list_t> &lpList,
  171. const std::string &dn)
  172. {
  173. /* We were given a DN, check if a parent of that dn is listed as filterd */
  174. for (const auto &i : *lpList)
  175. /* Key should be larger or equal then user DN */
  176. /* If key matches the end of the user dn, we have a positive match */
  177. if (i.size() <= dn.size() &&
  178. strcasecmp(dn.c_str() + (dn.size() - i.size()), i.c_str()) == 0)
  179. return true;
  180. return false;
  181. }