Skip to content

Commit 0d83100

Browse files
committed
ab_tree: restore pre-filtering of objects with AB_HIDE_FROM_GAL for NSP
ab_base::m_users always carries all users (no hiding), because different users can have different cloak_bits. zcore has knowledge about when a GAL container is to be opened, and that it has to create a MAPI table for it. So, zcore will make a copy of the corresponding ab_base user list, curate it (filter hidden users), and then attach the list object to the MAPI table for later cleanup. Unlike zcore RPC or EMSMDB, the NSPI protocol is rather stateless. A server does not know when the client-side MAPI implementation opens a GAL container/creates a MAPI table. All we see are requests "read GAL at x, for y rows". This means that ab_base needs to do the filtering ahead of time and keep that state, since nsp/ has no (good) way to keep it. That filtered list for container 0 was lost in the ab_tree rewrite. Reinstate it. The filtered list for container ids !=0 was retained, but was not filtered. Fixes: gromox-2.40-23-g91fc5e139 References: GXL-611, DESK-3546
1 parent 36bd364 commit 0d83100

File tree

4 files changed

+39
-15
lines changed

4 files changed

+39
-15
lines changed

exch/nsp/nsp_interface.cpp

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -634,7 +634,7 @@ ec_error_t nsp_interface_unbind(NSPI_HANDLE *phandle, uint32_t reserved)
634634
static void nsp_interface_position_in_list(const STAT *pstat,
635635
const ab_tree::ab_base *base, uint32_t *pout_row, uint32_t *pcount)
636636
{
637-
*pcount = base->user_count();
637+
*pcount = base->filtered_user_count();
638638
if (pstat->cur_rec == ab_tree::minid::CURRENT) {
639639
/* fractional positioning MS-OXNSPI v14 §3.1.4.5.2 */
640640
*pout_row = *pcount * static_cast<double>(pstat->num_pos) / pstat->total_rec;
@@ -647,12 +647,12 @@ static void nsp_interface_position_in_list(const STAT *pstat,
647647
} else if (pstat->cur_rec == ab_tree::minid::END_OF_TABLE) {
648648
*pout_row = *pcount;
649649
} else {
650-
auto it = base->find(pstat->cur_rec);
651650
/*
652651
* When not found, the position is undefined.
653-
* To avoid problems we will use first row.
652+
* To avoid problems, Gromox will use the first row.
653+
* (pos_in_filtered has been made to do this directly)
654654
*/
655-
*pout_row = it != base->end() && it->type() == ab_tree::minid::address ? it.pos()-base->ubegin().pos() : 0;
655+
*pout_row = base->pos_in_filtered_users(pstat->cur_rec);
656656
}
657657
}
658658

@@ -671,14 +671,15 @@ static void nsp_interface_position_in_table(const STAT *pstat,
671671
*pout_row = *pcount;
672672
} else {
673673
auto it = std::find(node.begin(), node.end(), pstat->cur_rec);
674-
if (it == node.end() || node.base->hidden(pstat->cur_rec) & AB_HIDE_FROM_AL)
674+
if (it == node.end() || node.base->hidden(pstat->cur_rec) & AB_HIDE_FROM_AL) {
675675
/*
676676
* In this case, the position is undefined.
677677
* To avoid problems, we will use the first row.
678678
*/
679679
*pout_row = 0;
680-
else
681-
*pout_row = uint32_t(std::distance(node.begin(), it));
680+
return;
681+
}
682+
*pout_row = std::distance(node.begin(), it);
682683
}
683684
}
684685

@@ -867,7 +868,7 @@ ec_error_t nsp_interface_query_rows(NSPI_HANDLE handle, uint32_t flags,
867868
return ecSuccess;
868869
}
869870
if (0 == pstat->container_id) {
870-
for (auto it = pbase->ubegin() + start_pos; it != pbase->ubegin() + start_pos + tmp_count; ++it) {
871+
for (auto it = pbase->ufbegin() + start_pos; it != pbase->ufbegin() + start_pos + tmp_count; ++it) {
871872
auto prow = common_util_proprowset_enlarge(rowset);
872873
if (prow == nullptr || common_util_propertyrow_init(prow) == nullptr)
873874
return ecServerOOM;
@@ -894,7 +895,9 @@ ec_error_t nsp_interface_query_rows(NSPI_HANDLE handle, uint32_t flags,
894895
if (start_pos + tmp_count >= total) {
895896
pstat->cur_rec = ab_tree::minid::END_OF_TABLE;
896897
} else {
897-
pstat->cur_rec = pstat->container_id == 0 ? pbase->at(start_pos + tmp_count) : node.at(start_pos + tmp_count);
898+
pstat->cur_rec = pstat->container_id == 0 ?
899+
pbase->at_filtered(start_pos + tmp_count) :
900+
node.at(start_pos + tmp_count);
898901
if (0 == pstat->cur_rec) {
899902
pstat->cur_rec = ab_tree::minid::END_OF_TABLE;
900903
start_pos = total;
@@ -1010,18 +1013,18 @@ ec_error_t nsp_interface_seek_entries(NSPI_HANDLE handle, uint32_t reserved,
10101013

10111014
start_pos = 0;
10121015
if (0 == pstat->container_id) {
1013-
auto it = std::lower_bound(pbase->ubegin(), pbase->uend(), ptarget->value.pstr,
1016+
auto it = std::lower_bound(pbase->ufbegin(), pbase->ufend(), ptarget->value.pstr,
10141017
[&](ab_tree::minid m1, const char *val)
10151018
{ return strcasecmp(pbase->displayname(m1).c_str(), val) < 0; });
1016-
if (it == pbase->uend())
1019+
if (it == pbase->ufend())
10171020
return ecNotFound;
10181021
auto prow = common_util_proprowset_enlarge(rowset);
10191022
if (prow == nullptr || common_util_propertyrow_init(prow) == nullptr)
10201023
return ecServerOOM;
10211024
if (nsp_interface_fetch_row({pbase, *it}, true, pstat->codepage, pproptags, prow) != ecSuccess)
10221025
return ecError;
10231026
pstat->cur_rec = *it;
1024-
pstat->num_pos = uint32_t(it.pos());
1027+
pstat->num_pos = it - pbase->ufbegin();
10251028
} else {
10261029
ab_tree::ab_node node(pbase, pstat->container_id);
10271030
if (start_pos >= node.children_count())

include/gromox/ab_tree.hpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,12 @@ class ab_base {
245245
inline iterator uend() const { return iterator(this, m_users.cend()); } ///< Iterator to end of user list
246246
iterator find(minid) const;
247247

248+
inline auto ufbegin() const { return filtered_gal.cbegin(); }
249+
inline auto ufend() const { return filtered_gal.cend(); }
250+
inline size_t filtered_user_count() const { return filtered_gal.size(); }
251+
minid at_filtered(uint32_t pos) const;
252+
uint32_t pos_in_filtered_users(minid) const;
253+
248254
static display_type dtypx_to_etyp(display_type);
249255

250256
private:
@@ -263,6 +269,7 @@ class ab_base {
263269
int m_base_id = 0;
264270
std::vector<ab_domain> domains; ///< list of domains belonging to the base
265271
std::vector<sql_user> m_users; ///< list of users from all those domains, sorted by displayname
272+
std::vector<minid> filtered_gal;
266273
std::unordered_map<minid, uint32_t> minid_idx_map; ///< map from minid to index in domain/user list
267274
mutable std::mutex m_lock;
268275
std::atomic<Status> m_status{Status::CONSTRUCTING};

include/gromox/mysql_adaptor.hpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ struct GX_EXPORT sql_domain {
6363
* %AB_HIDE_FROM_AL: hide from Address Lists, EXC style (container != 0)
6464
* %AB_HIDE_DELEGATE: hide from Delegate List
6565
* %AB_HIDE_RESOLVE: hide from name resolution ("Check Names" in g-web)
66-
* %AB_HIDE_MINID: disable resolution via MINID (experimental)
6766
*
6867
* %AB_HIDE__DEFAULT: default action if AB encounters PR_ATTR_HIDDEN
6968
*/

lib/ab_tree.cpp

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -214,8 +214,12 @@ bool ab_base::load()
214214
minid_idx_map.reserve(m_users.size() + dmemb.size());
215215
for (size_t i = 0; i < m_users.size(); ++i) {
216216
const sql_user &u = m_users[i];
217-
domains[domid_to_listidx[u.domain_id]].userref.emplace_back(minid(minid::address, u.id));
218-
minid_idx_map.emplace(minid(minid::address, u.id), i);
217+
minid mid(minid::address, u.id);
218+
if (!(u.cloak_bits & AB_HIDE_FROM_GAL)) {
219+
filtered_gal.emplace_back(mid);
220+
domains[domid_to_listidx[u.domain_id]].userref.emplace_back(mid);
221+
}
222+
minid_idx_map.emplace(mid, i);
219223
}
220224
for (size_t i = 0; i < domains.size(); ++i)
221225
minid_idx_map.emplace(minid(minid::domain, domains[i].id), i);
@@ -252,6 +256,11 @@ minid ab_base::at(uint32_t idx) const
252256
idx - domains.size() < m_users.size() ? minid(minid::address, m_users[idx-domains.size()].id) : minid();
253257
}
254258

259+
minid ab_base::at_filtered(uint32_t idx) const
260+
{
261+
return idx < filtered_gal.size() ? minid(minid::address, filtered_gal[idx]) : minid();
262+
}
263+
255264
/**
256265
* @brief Write company info to target strings
257266
*
@@ -741,6 +750,12 @@ ab_base::iterator ab_base::find(minid mid) const
741750
iterator(this, m_users.begin() + it->second);
742751
}
743752

753+
uint32_t ab_base::pos_in_filtered_users(minid mid) const
754+
{
755+
auto it = std::find(filtered_gal.cbegin(), filtered_gal.cend(), mid);
756+
return it != filtered_gal.cend() ? it - filtered_gal.cbegin() : 0;
757+
}
758+
744759
/**
745760
* @brief Find domain by id
746761
*

0 commit comments

Comments
 (0)