2 OpenChange Storage Abstraction Layer library
6 Copyright (C) Julien Kerihuel 2010
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "mapistore.h"
23 #include "mapistore_errors.h"
24 #include "mapistore_private.h"
25 #include "libmapi/libmapi_private.h"
30 static struct MAPINAMEID **nameids_cache = NULL;
32 static const char *mapistore_namedprops_get_ldif_path(void)
34 return MAPISTORE_LDIF;
38 \details Initialize the named properties database or return pointer
39 to the existing one if already initialized/opened.
41 \param mem_ctx pointer to the memory context
42 \param ldb_ctx pointer on pointer to the ldb context the function
45 \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
47 enum mapistore_error mapistore_namedprops_init(TALLOC_CTX *mem_ctx, struct ldb_context **_ldb_ctx)
51 struct ldb_context *ldb_ctx = NULL;
52 struct ldb_ldif *ldif;
55 struct tevent_context *ev;
59 MAPISTORE_RETVAL_IF(!mem_ctx, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
60 MAPISTORE_RETVAL_IF(!_ldb_ctx, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
62 ev = tevent_context_init(mem_ctx);
63 MAPISTORE_RETVAL_IF(!ev, MAPISTORE_ERR_NO_MEMORY, NULL);
65 database = talloc_asprintf(mem_ctx, "%s/%s", mapistore_get_mapping_path(), MAPISTORE_DB_NAMED);
66 DEBUG(0, ("database = %s\n", database));
68 /* Step 1. Stat the database and populate it if it doesn't exist */
69 if (stat(database, &sb) == -1) {
70 ldb_ctx = mapistore_ldb_wrap_connect(ldb_ctx, ev, database, 0);
71 talloc_free(database);
72 MAPISTORE_RETVAL_IF(!ldb_ctx, MAPISTORE_ERR_DATABASE_INIT, NULL);
74 filename = talloc_asprintf(mem_ctx, "%s/mapistore_namedprops.ldif",
75 mapistore_namedprops_get_ldif_path());
76 f = fopen(filename, "r");
77 talloc_free(filename);
78 MAPISTORE_RETVAL_IF(!f, MAPISTORE_ERROR, NULL);
80 ldb_transaction_start(ldb_ctx);
82 while ((ldif = ldb_ldif_read_file(ldb_ctx, f))) {
83 struct ldb_message *normalized_msg;
84 ret = ldb_msg_normalize(ldb_ctx, mem_ctx, ldif->msg, &normalized_msg);
85 MAPISTORE_RETVAL_IF(ret, MAPISTORE_ERR_DATABASE_INIT, NULL);
86 ret = ldb_add(ldb_ctx, normalized_msg);
87 talloc_free(normalized_msg);
88 if (ret != LDB_SUCCESS) {
90 MAPISTORE_RETVAL_IF(ret, MAPISTORE_ERR_DATABASE_INIT, NULL);
92 ldb_ldif_read_free(ldb_ctx, ldif);
95 ldb_transaction_commit(ldb_ctx);
99 ldb_ctx = mapistore_ldb_wrap_connect(ldb_ctx, ev, database, 0);
100 talloc_free(database);
101 MAPISTORE_RETVAL_IF(!ldb_ctx, MAPISTORE_ERR_DATABASE_INIT, NULL);
106 return MAPISTORE_SUCCESS;
111 \details return the next unmapped property ID
113 \param ldb_ctx pointer to the namedprops ldb context
115 \return 0 on error, the next mapped id otherwise
117 _PUBLIC_ uint16_t mapistore_namedprops_next_unused_id(struct ldb_context *ldb_ctx)
119 uint16_t highest_id = 0, current_id;
121 struct ldb_result *res = NULL;
122 const char * const attrs[] = { "mappedId", NULL };
126 mem_ctx = talloc_named(NULL, 0, "mapistore_namedprops_get_mapped_propID");
128 ret = ldb_search(ldb_ctx, mem_ctx, &res, ldb_get_default_basedn(ldb_ctx),
129 LDB_SCOPE_SUBTREE, attrs, "(cn=*)");
130 MAPISTORE_RETVAL_IF(ret != LDB_SUCCESS, 0, mem_ctx);
132 for (i = 0; i < res->count; i++) {
133 current_id = ldb_msg_find_attr_as_uint(res->msgs[i], "mappedId", 0);
134 if (current_id > 0 && highest_id < current_id) {
135 highest_id = current_id;
139 talloc_free(mem_ctx);
141 DEBUG(5, ("next_mapped_id: %d\n", (highest_id + 1)));
143 return (highest_id + 1);
147 \details return the mapped property ID matching the nameid
148 structure passed in parameter.
150 \param ldb_ctx pointer to the namedprops ldb context
151 \param nameid the MAPINAMEID structure to lookup
152 \param propID pointer to the property ID the function returns
154 \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE_ERROR
156 _PUBLIC_ enum mapistore_error mapistore_namedprops_create_id(struct ldb_context *ldb_ctx, struct MAPINAMEID nameid, uint16_t mapped_id)
161 struct ldb_ldif *ldif;
162 char *hex_id, *dec_id, *dec_mappedid, *guid;
163 struct ldb_message *normalized_msg;
164 const char *ldif_records[] = { NULL, NULL };
166 mem_ctx = talloc_zero(NULL, TALLOC_CTX);
168 dec_mappedid = talloc_asprintf(mem_ctx, "%u", mapped_id);
169 guid = GUID_string(mem_ctx, &nameid.lpguid);
170 switch (nameid.ulKind) {
172 hex_id = talloc_asprintf(mem_ctx, "%.4x", nameid.kind.lid);
173 dec_id = talloc_asprintf(mem_ctx, "%u", nameid.kind.lid);
174 ldif_record = talloc_asprintf(mem_ctx, "dn: CN=0x%s,CN=%s,CN=default\nobjectClass: MNID_ID\ncn: 0x%s\npropType: PT_NULL\noleguid: %s\nmappedId: %s\npropId: %s\n",
175 hex_id, guid, hex_id, guid, dec_mappedid, dec_id);
178 ldif_record = talloc_asprintf(mem_ctx, "dn: CN=%s,CN=%s,CN=default\nobjectClass: MNID_STRING\ncn: %s\npropType: PT_NULL\noleguid: %s\nmappedId: %s\npropName: %s\n",
179 nameid.kind.lpwstr.Name, guid, nameid.kind.lpwstr.Name, guid, dec_mappedid, nameid.kind.lpwstr.Name);
185 DEBUG(5, ("inserting record:\n%s\n", ldif_record));
186 ldif_records[0] = ldif_record;
187 ldif = ldb_ldif_read_string(ldb_ctx, ldif_records);
188 ret = ldb_msg_normalize(ldb_ctx, mem_ctx, ldif->msg, &normalized_msg);
189 MAPISTORE_RETVAL_IF(ret, MAPISTORE_ERR_DATABASE_INIT, NULL);
190 ret = ldb_add(ldb_ctx, normalized_msg);
191 talloc_free(normalized_msg);
192 if (ret != LDB_SUCCESS) {
193 MAPISTORE_RETVAL_IF(ret, MAPISTORE_ERR_DATABASE_INIT, NULL);
196 /* we invalidate the cache, if present */
198 talloc_free(nameids_cache);
199 nameids_cache = NULL;
206 \details return the mapped property ID matching the nameid
207 structure passed in parameter.
209 \param ldb_ctx pointer to the namedprops ldb context
210 \param nameid the MAPINAMEID structure to lookup
211 \param propID pointer to the property ID the function returns
213 \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE_ERROR
215 _PUBLIC_ enum mapistore_error mapistore_namedprops_get_mapped_id(struct ldb_context *ldb_ctx, struct MAPINAMEID nameid, uint16_t *propID)
218 struct ldb_result *res = NULL;
219 const char * const attrs[] = { "*", NULL };
225 MAPISTORE_RETVAL_IF(!ldb_ctx, MAPISTORE_ERROR, NULL);
226 MAPISTORE_RETVAL_IF(!propID, MAPISTORE_ERROR, NULL);
229 mem_ctx = talloc_named(NULL, 0, "mapistore_namedprops_get_mapped_propID");
230 guid = GUID_string(mem_ctx, (const struct GUID *)&nameid.lpguid);
232 switch (nameid.ulKind) {
234 filter = talloc_asprintf(mem_ctx, "(&(objectClass=MNID_ID)(oleguid=%s)(cn=0x%.4x))",
235 guid, nameid.kind.lid);
238 filter = talloc_asprintf(mem_ctx, "(&(objectClass=MNID_STRING)(oleguid=%s)(cn=%s))",
239 guid, nameid.kind.lpwstr.Name);
244 ret = ldb_search(ldb_ctx, mem_ctx, &res, ldb_get_default_basedn(ldb_ctx),
245 LDB_SCOPE_SUBTREE, attrs, "%s", filter);
246 MAPISTORE_RETVAL_IF((ret != LDB_SUCCESS || !res->count), MAPISTORE_ERROR, mem_ctx);
248 *propID = ldb_msg_find_attr_as_uint(res->msgs[0], "mappedId", 0);
249 MAPISTORE_RETVAL_IF(!*propID, MAPISTORE_ERROR, mem_ctx);
251 talloc_free(mem_ctx);
253 return MAPISTORE_SUCCESS;
257 \details return the nameid structture matching the mapped property ID
260 \param ldb_ctx pointer to the namedprops ldb context
261 \param propID the property ID to lookup
262 \param nameid pointer to the MAPINAMEID structure the function returns
264 \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE_ERROR
266 _PUBLIC_ enum mapistore_error mapistore_namedprops_get_nameid(struct ldb_context *ldb_ctx,
268 struct MAPINAMEID **nameidp)
271 struct ldb_result *res = NULL;
272 const char * const attrs[] = { "*", NULL };
274 const char *guid, *oClass, *cn;
275 struct MAPINAMEID *nameid;
276 int rc = MAPISTORE_SUCCESS;
280 MAPISTORE_RETVAL_IF(!ldb_ctx, MAPISTORE_ERROR, NULL);
281 MAPISTORE_RETVAL_IF(!nameidp, MAPISTORE_ERROR, NULL);
282 MAPISTORE_RETVAL_IF(propID < 0x8000, MAPISTORE_ERROR, NULL);
284 if (!nameids_cache) {
285 nameids_cache = talloc_array(NULL, struct MAPINAMEID *, 0x8000);
286 memset(nameids_cache, 0, 0x8000 * sizeof (struct MAPINAMEID *));
289 mem_ctx = talloc_zero(NULL, TALLOC_CTX);
291 propidx = propID - 0x8000;
292 nameid = nameids_cache[propidx];
295 return MAPISTORE_SUCCESS;
298 ret = ldb_search(ldb_ctx, mem_ctx, &res, ldb_get_default_basedn(ldb_ctx),
299 LDB_SCOPE_SUBTREE, attrs, "(mappedId=%d)", propID);
300 MAPISTORE_RETVAL_IF(ret != LDB_SUCCESS || !res->count, MAPISTORE_ERROR, mem_ctx);
302 guid = ldb_msg_find_attr_as_string(res->msgs[0], "oleguid", 0);
303 MAPISTORE_RETVAL_IF(!guid, MAPISTORE_ERROR, mem_ctx);
305 cn = ldb_msg_find_attr_as_string(res->msgs[0], "cn", 0);
306 MAPISTORE_RETVAL_IF(!cn, MAPISTORE_ERROR, mem_ctx);
308 oClass = ldb_msg_find_attr_as_string(res->msgs[0], "objectClass", 0);
309 MAPISTORE_RETVAL_IF(!propID, MAPISTORE_ERROR, mem_ctx);
311 nameid = talloc_zero(nameids_cache, struct MAPINAMEID);
312 GUID_from_string(guid, &nameid->lpguid);
313 if (strcmp(oClass, "MNID_ID") == 0) {
314 nameid->ulKind = MNID_ID;
315 nameid->kind.lid = strtol(cn, NULL, 16);
317 else if (strcmp(oClass, "MNID_STRING") == 0) {
318 nameid->ulKind = MNID_STRING;
319 nameid->kind.lpwstr.NameSize = strlen(cn) * 2 + 2;
320 nameid->kind.lpwstr.Name = talloc_strdup(nameid, cn);
323 talloc_unlink(nameids_cache, nameid);
325 rc = MAPISTORE_ERROR;
329 nameids_cache[propidx] = nameid;
333 talloc_free(mem_ctx);