2 OpenChange Storage Abstraction Layer library
6 Copyright (C) Julien Kerihuel 2009-2011
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/>.
23 \file mapistore_interface.c
25 \brief MAPISTORE public user interface
27 This file contains general functions, primarily for
28 users of the store (rather than storage providers).
31 #define __STDC_FORMAT_MACROS 1
34 #include "mapistore_errors.h"
35 #include "mapistore.h"
36 #include "mapistore_private.h"
37 #include "mapistore_backend.h"
38 #include "mapistore_common.h"
39 #include <dlinklist.h>
40 #include "libmapi/libmapi_private.h"
44 /* FIXME: we can use backend_ctx->mapistore_indexing_list instead of
45 * initializing/uninitializing it each time. This also suppose we get
46 * finally ride of libmapistore/mapistore_indexing.c */
49 \details Initialize the mapistore context
51 \param mem_ctx pointer to the memory context
52 \param path the path to the location to load the backend providers from (NULL for default)
54 \return allocate mapistore context on success, otherwise NULL
56 _PUBLIC_ struct mapistore_context *mapistore_init(TALLOC_CTX *mem_ctx, const char *path)
58 enum MAPISTORE_ERROR retval;
59 struct mapistore_context *mstore_ctx;
61 mstore_ctx = talloc_zero(mem_ctx, struct mapistore_context);
66 mstore_ctx->processing_ctx = talloc_zero(mstore_ctx, struct processing_context);
68 retval = mapistore_init_mapping_context(mstore_ctx->processing_ctx);
69 if (retval != MAPISTORE_SUCCESS) {
70 MSTORE_DEBUG_ERROR(MSTORE_LEVEL_CRITICAL, "mapistore mapping context init failed: %s\n",
71 mapistore_errstr(retval));
72 talloc_free(mstore_ctx);
76 retval = mapistore_backend_init(mstore_ctx, path);
77 if (retval != MAPISTORE_SUCCESS) {
78 MSTORE_DEBUG_ERROR(MSTORE_LEVEL_CRITICAL, "mapistore backend init failed: %s\n", mapistore_errstr(retval));
79 talloc_free(mstore_ctx);
83 mstore_ctx->context_list = NULL;
86 mstore_ctx->indexing_list = talloc_zero(mstore_ctx, struct indexing_context_list);
90 mstore_ctx->mapistore_indexing_list = talloc_zero(mstore_ctx, struct mapistore_indexing_context_list);
92 mstore_ctx->mapistore_nprops_ctx = NULL;
93 retval = mapistore_namedprops_init(mstore_ctx, &(mstore_ctx->mapistore_nprops_ctx));
94 if (retval != MAPISTORE_SUCCESS) {
95 MSTORE_DEBUG_ERROR(MSTORE_LEVEL_CRITICAL,
96 "mapistore named properties database init failed: %s\n",
97 mapistore_errstr(retval));
98 talloc_free(mstore_ctx);
103 mstore_ctx->lp_ctx = loadparm_init(mstore_ctx);
104 lpcfg_load_default(mstore_ctx->lp_ctx);
111 \details Release the mapistore context and destroy any data
114 \param mstore_ctx pointer to the mapistore context
116 \note The function needs to rely on talloc destructors which is not
117 implemented in code yet.
119 \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
121 _PUBLIC_ enum MAPISTORE_ERROR mapistore_release(struct mapistore_context *mstore_ctx)
124 MAPISTORE_RETVAL_IF(!mstore_ctx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
126 talloc_free(mstore_ctx->mapistore_nprops_ctx);
127 talloc_free(mstore_ctx->processing_ctx);
128 talloc_free(mstore_ctx->context_list);
129 talloc_free(mstore_ctx);
131 return MAPISTORE_SUCCESS;
136 \details Set the mapistore debug level
138 \param mstore_ctx pointer to the mapistore context
139 \param level the debug level to set
141 \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
143 enum MAPISTORE_ERROR mapistore_set_debuglevel(struct mapistore_context *mstore_ctx, uint32_t level)
149 MAPISTORE_RETVAL_IF(!mstore_ctx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
150 MAPISTORE_RETVAL_IF(!mstore_ctx->lp_ctx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
152 debuglevel = talloc_asprintf(talloc_autofree_context(), "%u", level);
153 ret = lpcfg_set_cmdline(mstore_ctx->lp_ctx, "log level", debuglevel);
154 talloc_free(debuglevel);
156 return (ret == true) ? MAPISTORE_SUCCESS : MAPISTORE_ERR_INVALID_PARAMETER;
161 \details Add a new connection context to mapistore
163 \param mstore_ctx pointer to the mapistore context
164 \param login_user the username used for authentication
165 \param username the username we want to impersonate
166 \param uri the connection context URI
167 \param context_id pointer to the context identifier the function returns
169 \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
171 _PUBLIC_ enum MAPISTORE_ERROR mapistore_add_context(struct mapistore_context *mstore_ctx,
172 const char *login_user, const char *username,
173 const char *uri, uint32_t *context_id)
177 struct backend_context *backend_ctx;
178 struct backend_context_list *backend_list;
180 char *namespace_start;
183 /* Step 1. Perform Sanity Checks on URI */
184 MAPISTORE_RETVAL_IF(!uri || strlen(uri) < 4, MAPISTORE_ERR_INVALID_NAMESPACE, NULL);
186 mem_ctx = talloc_named(NULL, 0, "mapistore_add_context");
187 uri_namespace = talloc_strdup(mem_ctx, uri);
188 namespace_start = uri_namespace;
189 uri_namespace= strchr(uri_namespace, ':');
190 if (!uri_namespace) {
191 MSTORE_DEBUG_ERROR(MSTORE_LEVEL_CRITICAL, "Invalid namespace '%s'\n", namespace_start);
192 talloc_free(mem_ctx);
193 return MAPISTORE_ERR_INVALID_NAMESPACE;
196 if (uri_namespace[1] && uri_namespace[1] == '/' &&
197 uri_namespace[2] && uri_namespace[2] == '/' &&
199 backend_uri = talloc_strdup(mem_ctx, &uri_namespace[3]);
200 uri_namespace[3] = '\0';
201 backend_ctx = mapistore_backend_create_context((TALLOC_CTX *)mstore_ctx, login_user, username, namespace_start, backend_uri);
203 return MAPISTORE_ERR_CONTEXT_FAILED;
205 backend_ctx->username = talloc_strdup((TALLOC_CTX *)backend_ctx, username);
207 backend_list = talloc_zero((TALLOC_CTX *) mstore_ctx, struct backend_context_list);
208 talloc_steal(backend_list, backend_ctx);
209 backend_list->ctx = backend_ctx;
210 retval = mapistore_get_context_id(mstore_ctx->processing_ctx, &backend_list->ctx->context_id);
211 if (retval != MAPISTORE_SUCCESS) {
212 talloc_free(mem_ctx);
213 return MAPISTORE_ERR_CONTEXT_FAILED;
215 *context_id = backend_list->ctx->context_id;
216 DLIST_ADD_END(mstore_ctx->context_list, backend_list, struct backend_context_list *);
219 MSTORE_DEBUG_ERROR(MSTORE_LEVEL_CRITICAL, "Invalid URI '%s'\n", uri);
220 talloc_free(mem_ctx);
221 return MAPISTORE_ERR_INVALID_NAMESPACE;
224 talloc_free(mem_ctx);
225 return MAPISTORE_SUCCESS;
230 \details Increase the reference counter of an existing context
232 \param mstore_ctx pointer to the mapistore context
233 \param context_id the context identifier referencing the context to
236 \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
238 _PUBLIC_ enum MAPISTORE_ERROR mapistore_add_context_ref_count(struct mapistore_context *mstore_ctx,
241 struct backend_context *backend_ctx;
242 enum MAPISTORE_ERROR retval;
245 MAPISTORE_SANITY_CHECKS(mstore_ctx, NULL);
247 /* TODO: Fix context_id sign */
248 MAPISTORE_RETVAL_IF((int)context_id == -1, MAPISTORE_ERR_INVALID_CONTEXT, NULL);
250 /* Step 0. Ensure the context exists */
251 MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, "context to increment is %d\n", context_id);
252 backend_ctx = mapistore_backend_lookup(mstore_ctx->context_list, context_id);
253 MAPISTORE_RETVAL_IF(!backend_ctx, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
255 /* Step 1. Increment the ref count */
256 retval = mapistore_backend_add_ref_count(backend_ctx);
263 \details Search for an existing context given its uri
265 \param mstore_ctx pointer to the mapistore context
266 \param uri the URI to lookup
267 \param context_id pointer to the context identifier to return
269 \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
271 _PUBLIC_ enum MAPISTORE_ERROR mapistore_search_context_by_uri(struct mapistore_context *mstore_ctx,
273 uint32_t *context_id)
275 struct backend_context *backend_ctx;
278 MAPISTORE_SANITY_CHECKS(mstore_ctx, NULL);
279 MAPISTORE_RETVAL_IF(!uri, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
281 backend_ctx = mapistore_backend_lookup_by_uri(mstore_ctx->context_list, uri);
282 MAPISTORE_RETVAL_IF(!backend_ctx, MAPISTORE_ERR_NOT_FOUND, NULL);
284 *context_id = backend_ctx->context_id;
285 return MAPISTORE_SUCCESS;
290 \details Delete an existing connection context from mapistore
292 \param mstore_ctx pointer to the mapistore context
293 \param context_id the context identifier referencing the context to
296 \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
298 _PUBLIC_ enum MAPISTORE_ERROR mapistore_del_context(struct mapistore_context *mstore_ctx,
301 struct backend_context_list *backend_list;
302 struct backend_context *backend_ctx;
303 enum MAPISTORE_ERROR retval;
307 MAPISTORE_SANITY_CHECKS(mstore_ctx, NULL);
309 /* TODO: Fix context_id sign */
310 MAPISTORE_RETVAL_IF((int)context_id == -1, MAPISTORE_ERR_INVALID_CONTEXT, NULL);
312 /* Step 0. Ensure the context exists */
313 MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, "context_id to delete is %d\n", context_id);
314 backend_ctx = mapistore_backend_lookup(mstore_ctx->context_list, context_id);
315 MAPISTORE_RETVAL_IF(!backend_ctx, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
317 /* search the backend_list item */
318 for (backend_list = mstore_ctx->context_list; backend_list; backend_list = backend_list->next) {
319 if (backend_list->ctx->context_id == context_id) {
324 if (found == false) {
325 return MAPISTORE_ERROR;
328 /* Step 1. Delete the context within backend */
329 retval = mapistore_backend_delete_context(backend_ctx);
331 case MAPISTORE_ERR_REF_COUNT:
332 return MAPISTORE_SUCCESS;
333 case MAPISTORE_SUCCESS:
334 DLIST_REMOVE(mstore_ctx->context_list, backend_list);
335 /* Step 2. Add the free'd context id to the free list */
336 retval = mapistore_free_context_id(mstore_ctx->processing_ctx, context_id);
347 \details Create a root default/system folder within the mailbox and
348 return the folder identifier
350 This operation is only meant to be called at mailbox provisioning
353 \param mstore_ctx pointer to the mapistore context
354 \param context_id the context identifier referencing the backend
355 \param parent_index the parent default system/special folder index
356 \param index the default system/special folder index
357 \param folder_name the folder name to set
359 \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
361 _PUBLIC_ enum MAPISTORE_ERROR mapistore_create_root_folder(struct mapistore_context *mstore_ctx,
363 enum MAPISTORE_DFLT_FOLDERS parent_index,
364 enum MAPISTORE_DFLT_FOLDERS index,
365 const char *folder_name)
367 enum MAPISTORE_ERROR retval;
368 struct backend_context *backend_ctx;
375 MAPISTORE_SANITY_CHECKS(mstore_ctx, NULL);
377 /* Step 1. Search the context */
378 backend_ctx = mapistore_backend_lookup(mstore_ctx->context_list, context_id);
379 MAPISTORE_RETVAL_IF(!backend_ctx, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
381 /* Step 2. Ensure the parent folder exists and retrieve its FID */
382 retval = mapistore_create_uri(mstore_ctx, parent_index, backend_ctx->backend->uri_namespace,
383 backend_ctx->username, &parent_uri);
384 MAPISTORE_RETVAL_IF(retval, retval, NULL);
386 retval = mapistore_indexing_context_add(mstore_ctx, backend_ctx->username, &(mstore_ctx->mapistore_indexing_list));
387 MAPISTORE_RETVAL_IF(retval, retval, NULL);
389 retval = mapistore_indexing_record_search_uri(mstore_ctx->mapistore_indexing_list, parent_uri);
390 if (retval != MAPISTORE_ERR_EXIST) {
391 talloc_free(parent_uri);
395 retval = mapistore_indexing_get_record_fmid_by_uri(mstore_ctx->mapistore_indexing_list, parent_uri, &pfid);
396 talloc_free(parent_uri);
401 /* Step 3. Generate the URI */
402 retval = mapistore_create_uri(mstore_ctx, index, backend_ctx->backend->uri_namespace,
403 backend_ctx->username, &mapistore_uri);
404 if (retval) goto error;
406 /* Step 4. Call backend root_mkdir operation */
407 retval = mapistore_backend_root_mkdir(backend_ctx, index, mapistore_uri, folder_name);
409 talloc_free(mapistore_uri);
413 /* Step 5. Get a new FID for the folder */
414 retval = mapistore_get_new_fmid(mstore_ctx->processing_ctx, backend_ctx->username, &fid);
416 talloc_free(mapistore_uri);
420 /* Step 6. Register the folder within the indexing database */
421 retval = mapistore_indexing_add_fmid_record(mstore_ctx->mapistore_indexing_list, fid,
422 mapistore_uri, pfid, MAPISTORE_INDEXING_FOLDER);
423 talloc_free(mapistore_uri);
424 if (retval) goto error;
427 mapistore_indexing_context_del(mstore_ctx, backend_ctx->username);
429 /* Step 7. Very unlikely to happen ... but still delete the folder */
437 _PUBLIC_ enum MAPISTORE_ERROR mapistore_set_mapistore_uri(struct mapistore_context *mstore_ctx,
439 enum MAPISTORE_DFLT_FOLDERS index,
440 const char *mapistore_uri)
442 enum MAPISTORE_ERROR retval;
443 struct backend_context *backend_ctx;
448 MAPISTORE_SANITY_CHECKS(mstore_ctx, NULL);
449 MAPISTORE_RETVAL_IF(!mapistore_uri, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
451 /* Step 1. Search the context */
452 backend_ctx = mapistore_backend_lookup(mstore_ctx->context_list, context_id);
453 MAPISTORE_RETVAL_IF(!backend_ctx, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
455 /* Step 2. Retrieve the URI associated to this system/default folder */
456 retval = mapistore_create_uri(mstore_ctx, index, backend_ctx->backend->uri_namespace,
457 backend_ctx->username, &old_uri);
458 MAPISTORE_RETVAL_IF(retval, retval, NULL);
460 /* Step 3. Create the mapistore_indexing context */
461 retval = mapistore_indexing_context_add(mstore_ctx, backend_ctx->username, &(mstore_ctx->mapistore_indexing_list));
462 MAPISTORE_RETVAL_IF(retval, retval, NULL);
464 /* Step 4. Retrieve its FMID from the indexing database */
465 retval = mapistore_indexing_get_record_fmid_by_uri(mstore_ctx->mapistore_indexing_list, old_uri, &fmid);
466 if (retval) goto end;
468 /* Step 5. Update the URI within the indexing database */
469 retval = mapistore_indexing_update_mapistore_uri(mstore_ctx->mapistore_indexing_list, fmid, mapistore_uri);
470 if (retval) goto end;
473 /* Step 6. Delete the indexing context */
474 retval = mapistore_indexing_context_del(mstore_ctx, backend_ctx->username);
480 \details Retrieve the next backend available in the list
482 \param backend_name pointer to the backend name to return
483 \param backend_namespace pointer to the backend namespace to return
484 \param backend_description pointer to the backend description to
486 \param backend_index pointer to the backend index in the the
487 backend's list to return
489 \note backend_index must be initialized to 0 prior any calls to
490 mapistore_get_next_backend.
492 \return MAPISTORE_SUCCESS on success, MAPISTORE_ERR_NOT_FOUND if
493 the end of the list is reached, otherwise MAPISTORE error
495 enum MAPISTORE_ERROR mapistore_get_next_backend(const char **backend_name,
496 const char **backend_namespace,
497 const char **backend_description,
498 uint32_t *backend_index)
500 enum MAPISTORE_ERROR retval;
501 const char *_backend_name;
502 const char *_backend_namespace;
503 const char *_backend_description;
504 uint32_t _backend_index;
507 MAPISTORE_RETVAL_IF(!backend_name && !backend_namespace && !backend_description,
508 MAPISTORE_ERR_INVALID_PARAMETER, NULL);
509 MAPISTORE_RETVAL_IF(!backend_index, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
511 _backend_index = *backend_index;
512 retval = mapistore_backend_get_next_backend(&_backend_name,
514 &_backend_description,
516 MAPISTORE_RETVAL_IF(retval, retval, NULL);
519 *backend_name = _backend_name;
522 if (backend_namespace) {
523 *backend_namespace = _backend_namespace;
526 if (backend_description) {
527 *backend_description = _backend_description;
530 *backend_index = _backend_index;
532 return MAPISTORE_SUCCESS;
536 \details Retrieve the LDIF data associated to registered backends
537 by sequentially calling op_db_provision_namedprops operation.
539 \param mstore_ctx pointer to the mapistore context
540 \param backend_name pointer on pointer to the backend name to return
541 \param ldif pointer on pointer to the LDIF data to return
542 \param ntype pointer to the type of LDIF data to return
544 \note It is also up to the caller application to free memory
545 associated to ldif data.
547 \return MAPISTORE_SUCCESS on success, or MAPISTORE_ERR_NOT_FOUND if
548 there is no more available backends, otherwise MAPISTORE_ERROR
550 enum MAPISTORE_ERROR mapistore_get_backend_ldif(struct mapistore_context *mstore_ctx,
551 const char *backend_name,
553 enum MAPISTORE_NAMEDPROPS_PROVISION_TYPE *ntype)
555 enum MAPISTORE_ERROR retval;
556 enum MAPISTORE_NAMEDPROPS_PROVISION_TYPE _ntype;
560 MAPISTORE_RETVAL_IF(!mstore_ctx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
561 MAPISTORE_RETVAL_IF(!backend_name, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
562 MAPISTORE_RETVAL_IF(!ldif, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
563 MAPISTORE_RETVAL_IF(!ntype, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
565 retval = mapistore_backend_get_namedprops_ldif((TALLOC_CTX *) mstore_ctx, backend_name, &_ldif, &_ntype);
567 MAPISTORE_RETVAL_IF(retval, retval, NULL);
572 return MAPISTORE_SUCCESS;
577 \details Release private backend data associated a folder / message
578 opened within the mapistore backend
580 \param mstore_ctx pointer to the mapistore context
581 \param context_id the context identifier referencing the backend
582 \param fmid a folder or message identifier
583 \param type the type of fmid, either MAPISTORE_FOLDER or MAPISTORE_MESSAGE
585 \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE errors
587 _PUBLIC_ enum MAPISTORE_ERROR mapistore_release_record(struct mapistore_context *mstore_ctx,
592 enum MAPISTORE_ERROR retval;
593 struct backend_context *backend_ctx;
597 MAPISTORE_SANITY_CHECKS(mstore_ctx, NULL);
598 MAPISTORE_RETVAL_IF(!context_id, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
599 MAPISTORE_RETVAL_IF(!fmid, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
601 /* Step 1. Search the context */
602 backend_ctx = mapistore_backend_lookup(mstore_ctx->context_list, context_id);
603 MAPISTORE_RETVAL_IF(!backend_ctx, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
605 /* Step 2. Add an indexing context */
606 retval = mapistore_indexing_context_add(mstore_ctx, backend_ctx->username, &(mstore_ctx->mapistore_indexing_list));
607 MAPISTORE_RETVAL_IF(retval, retval, NULL);
609 /* Step 3. Search the URI matching the specified FMID within the username indexing database */
610 retval = mapistore_indexing_get_record_uri_by_fmid(mstore_ctx->mapistore_indexing_list, fmid, &uri);
612 MSTORE_DEBUG_ERROR(MSTORE_LEVEL_NORMAL,
613 "Failed to find URI matching the following FMID for user %s: 0x%.16"PRIx64"\n",
614 backend_ctx->username, fmid);
618 /* Step 4. Call backend release_record */
619 retval = mapistore_backend_release_record(backend_ctx, (const char *)uri, type);
622 /* Step 5. Delete indexing context */
623 mapistore_indexing_context_del(mstore_ctx, backend_ctx->username);
629 \details Associate an indexing context to a mapistore context
631 \param mstore_ctx pointer to the mapistore context
632 \param username account name referencing the indexing record
633 \param context_id the context identifier referencing the context to
636 \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
638 _PUBLIC_ enum MAPISTORE_ERROR mapistore_add_context_indexing(struct mapistore_context *mstore_ctx,
639 const char *username,
642 struct indexing_context_list *indexing_ctx;
643 struct backend_context *backend_ctx;
646 MAPISTORE_SANITY_CHECKS(mstore_ctx, NULL);
647 MAPISTORE_RETVAL_IF(!username, MAPISTORE_ERROR, NULL);
648 /* TODO: Fix context_id sign */
649 MAPISTORE_RETVAL_IF((int)context_id == -1, MAPISTORE_ERROR, NULL);
651 /* Step 0. Ensure the context exists */
652 backend_ctx = mapistore_backend_lookup(mstore_ctx->context_list, context_id);
653 MAPISTORE_RETVAL_IF(!backend_ctx, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
654 /* If the indexing pointer is already existing, return success */
655 MAPISTORE_RETVAL_IF(backend_ctx->indexing, MAPISTORE_SUCCESS, NULL);
657 /* Step 1. Search the indexing record */
658 indexing_ctx = mapistore_indexing_search(mstore_ctx, username);
659 MAPISTORE_RETVAL_IF(!indexing_ctx, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
661 /* Step 2. Reference the indexing record within backend context */
662 backend_ctx->indexing = indexing_ctx;
664 /* Step 3. Increment the indexing ref counter */
665 mapistore_indexing_add_ref_count(indexing_ctx);
667 MSTORE_DEBUG_SUCCESS(MSTORE_LEVEL_DEBUG, "Add content indexing for username: %s\n", backend_ctx->indexing->username);
668 return MAPISTORE_SUCCESS;
672 void mapistore_set_errno(int status)
679 \details return a string explaining what a mapistore error constant
682 \param mapistore_err the mapistore error constant
684 \return constant string
686 _PUBLIC_ const char *mapistore_errstr(enum MAPISTORE_ERROR mapistore_err)
688 switch (mapistore_err) {
689 case MAPISTORE_SUCCESS:
691 case MAPISTORE_ERROR:
692 return "Non-specific error";
693 case MAPISTORE_ERR_NO_MEMORY:
694 return "No memory available";
695 case MAPISTORE_ERR_ALREADY_INITIALIZED:
696 return "Already initialized";
697 case MAPISTORE_ERR_NOT_INITIALIZED:
698 return "Not initialized";
699 case MAPISTORE_ERR_CORRUPTED:
701 case MAPISTORE_ERR_INVALID_PARAMETER:
702 return "Invalid parameter";
703 case MAPISTORE_ERR_NO_DIRECTORY:
704 return "No such file or directory";
705 case MAPISTORE_ERR_DATABASE_INIT:
706 return "Database initialization failed";
707 case MAPISTORE_ERR_DATABASE_OPS:
708 return "Database operation failed";
709 case MAPISTORE_ERR_BACKEND_REGISTER:
710 return "Storage backend registration failed";
711 case MAPISTORE_ERR_BACKEND_INIT:
712 return "Storage backend initialization failed";
713 case MAPISTORE_ERR_CONTEXT_FAILED:
714 return "Context creation failed";
715 case MAPISTORE_ERR_INVALID_NAMESPACE:
716 return "Invalid namespace";
717 case MAPISTORE_ERR_NOT_FOUND:
718 return "Record or data not found";
719 case MAPISTORE_ERR_REF_COUNT:
720 return "Reference count still exists";
721 case MAPISTORE_ERR_EXIST:
722 return "Already exists";
723 case MAPISTORE_ERR_INVALID_OBJECT:
724 return "Invalid object";
725 case MAPISTORE_ERR_INVALID_CONTEXT:
726 return "Invalid mapistore context";
727 case MAPISTORE_ERR_INVALID_URI:
728 return "Invalid mapistore URI";
729 case MAPISTORE_ERR_NOT_IMPLEMENTED:
730 return "Not implemented";
731 case MAPISTORE_ERR_RESERVED:
732 return "Record or data reserved";
735 return "Unknown error";
739 _PUBLIC_ enum MAPISTORE_ERROR mapistore_create_uri(struct mapistore_context *mstore_ctx,
741 const char *namespace_uri,
742 const char *username,
745 enum MAPISTORE_ERROR ret;
751 MAPISTORE_RETVAL_IF((!namespace_uri || strlen(namespace_uri) < 4), MAPISTORE_ERR_INVALID_NAMESPACE, NULL);
753 ref_str = (char *)namespace_uri;
754 ns = strchr(namespace_uri, ':');
756 MSTORE_DEBUG_ERROR(MSTORE_LEVEL_CRITICAL, "Invalid namespace '%s'\n", ref_str);
757 return MAPISTORE_ERR_INVALID_NAMESPACE;
760 if (ns[1] && ns[1] == '/' && ns[2] && ns[2] == '/') {
764 ret = mapistore_backend_create_uri((TALLOC_CTX *)mstore_ctx, index, ref_str, username, &uri);
765 if (ret == MAPISTORE_SUCCESS) {
771 return MAPISTORE_ERR_NOT_FOUND;
775 \details Return the URI for a default folder within a given context
777 \param mstore_ctx pointer to the mapistore context
778 \param context_id the context identifier
779 \param index the mapistore default folder to search
780 \param _uri pointer on pointer to the mapistore URI to return
782 \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
784 enum MAPISTORE_ERROR mapistore_create_context_uri(struct mapistore_context *mstore_ctx,
786 enum MAPISTORE_DFLT_FOLDERS index,
789 enum MAPISTORE_ERROR retval;
790 struct backend_context *backend_ctx;
794 MAPISTORE_SANITY_CHECKS(mstore_ctx, NULL);
795 MAPISTORE_RETVAL_IF(!context_id, MAPISTORE_ERR_INVALID_CONTEXT, NULL);
796 MAPISTORE_RETVAL_IF(!index, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
797 MAPISTORE_RETVAL_IF(!_uri, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
799 /* Step 1. Search the context */
800 backend_ctx = mapistore_backend_lookup(mstore_ctx->context_list, context_id);
801 MAPISTORE_RETVAL_IF(!backend_ctx, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
803 retval = mapistore_create_uri(mstore_ctx, index, backend_ctx->backend->uri_namespace, backend_ctx->username, &uri);
804 MAPISTORE_RETVAL_IF(retval, retval, NULL);
808 return MAPISTORE_SUCCESS;
812 \details Return the folder identifier associated to a mapistore URI
813 relative to a context identifier.
815 \param mstore_ctx pointer to the mapistore context
816 \param context_id the mapistore context identifier
817 \param uri the mapistore URI to lookup
818 \param folderID pointer to the folder identifier to return
820 \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
822 enum MAPISTORE_ERROR mapistore_get_folder_identifier_from_uri(struct mapistore_context *mstore_ctx,
827 enum MAPISTORE_ERROR retval;
828 struct backend_context *backend_ctx;
832 MAPISTORE_SANITY_CHECKS(mstore_ctx, NULL);
833 MAPISTORE_RETVAL_IF(!context_id, MAPISTORE_ERR_INVALID_CONTEXT, NULL);
834 MAPISTORE_RETVAL_IF(!uri, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
835 MAPISTORE_RETVAL_IF(!folderID, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
837 /* Step 1. Ensure the context exists */
838 backend_ctx = mapistore_backend_lookup(mstore_ctx->context_list, context_id);
839 MAPISTORE_RETVAL_IF(!backend_ctx, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
841 /* Step 2. Add an indexing context */
842 retval = mapistore_indexing_context_add(mstore_ctx, backend_ctx->username, &(mstore_ctx->mapistore_indexing_list));
843 MAPISTORE_RETVAL_IF(retval, retval, NULL);
845 /* Step 3. Search for the FID matching the specified URI within the username indexing database */
846 retval = mapistore_indexing_get_record_fmid_by_uri(mstore_ctx->mapistore_indexing_list, uri, &fid);
848 MSTORE_DEBUG_ERROR(MSTORE_LEVEL_NORMAL, "Failed to find FID matcthing the following URI for user %s: %s\n",
849 backend_ctx->username, uri);
853 /* Step 4. Copy parameter */
857 /* Step 5. Delete indexing context */
858 mapistore_indexing_context_del(mstore_ctx, backend_ctx->username);
864 \details Open a directory in mapistore
866 \param mstore_ctx pointer to the mapistore context
867 \param context_id the context identifier referencing the backend
868 where the directory will be opened
869 \param parent_fid the parent folder identifier
870 \param fid folder identifier to open
872 \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE errors
874 _PUBLIC_ enum MAPISTORE_ERROR mapistore_opendir(struct mapistore_context *mstore_ctx,
879 enum MAPISTORE_ERROR retval;
880 struct backend_context *backend_ctx;
885 MAPISTORE_SANITY_CHECKS(mstore_ctx, NULL);
887 /* Step 1. Search the context */
888 backend_ctx = mapistore_backend_lookup(mstore_ctx->context_list, context_id);
889 MAPISTORE_RETVAL_IF(!backend_ctx, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
891 /* Step 2. Create an indexing context */
892 retval = mapistore_indexing_context_add(mstore_ctx, backend_ctx->username, &(mstore_ctx->mapistore_indexing_list));
893 MAPISTORE_RETVAL_IF(retval, retval, NULL);
895 /* Step 2. Turn parent folder identifier into URI */
896 retval = mapistore_indexing_get_record_uri_by_fmid(mstore_ctx->mapistore_indexing_list, parent_fid, &parent_uri);
897 if (retval) goto error;
899 /* Step 3. Turn folder identifier into URI */
900 retval = mapistore_indexing_get_record_uri_by_fmid(mstore_ctx->mapistore_indexing_list, fid, &folder_uri);
901 if (retval) goto error;
903 /* Step 4. Call backend opendir */
904 retval = mapistore_backend_opendir(backend_ctx, parent_uri, folder_uri);
906 /* Add a reference count? */
909 mapistore_indexing_context_del(mstore_ctx, backend_ctx->username);
910 return !retval ? MAPISTORE_SUCCESS : MAPISTORE_ERROR;
915 \details Close a directory in mapistore
917 \param mstore_ctx pointer to the mapistore context
918 \param context_id the context identifier referencing the backend
919 where the directory has to be closed/released
920 \param fid the folder identifier referencing the folder to close
922 \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE errors
924 _PUBLIC_ enum MAPISTORE_ERROR mapistore_closedir(struct mapistore_context *mstore_ctx,
928 struct backend_context *backend_ctx;
931 MAPISTORE_SANITY_CHECKS(mstore_ctx, NULL);
933 /* Step 0. Search the context */
934 backend_ctx = mapistore_backend_lookup(mstore_ctx->context_list, context_id);
935 MAPISTORE_RETVAL_IF(!backend_ctx, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
937 /* mapistore_backend_closedir() */
939 return MAPISTORE_SUCCESS;
944 \details Create a directory in mapistore
946 \param mstore_ctx pointer to the mapistore context
947 \param context_id the context identifier referencing the backend
948 where the directory will be created
949 \param parent_fid the parent folder identifier
950 \param folder_name the name for the new folder, must not be null
951 \param folder_desc the description (comment) for the new folder, can be null
952 \param folder_type the type of folder (FOLDER_GENERIC or FOLDER_SEARCH)
953 \param fid the folder ID for the folder that has been created (return value)
955 Note that fid is only valid on success
957 \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE errors
959 _PUBLIC_ enum MAPISTORE_ERROR mapistore_mkdir(struct mapistore_context *mstore_ctx,
962 const char *folder_name,
963 const char *folder_desc,
964 enum FOLDER_TYPE folder_type,
967 struct backend_context *backend_ctx = NULL;
968 enum MAPISTORE_ERROR retval;
969 char *parent_uri = NULL;
970 uint64_t folder_fid = 0;
971 char *folder_uri = NULL;
974 MAPISTORE_SANITY_CHECKS(mstore_ctx, NULL);
975 MAPISTORE_RETVAL_IF(!folder_name, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
976 MAPISTORE_RETVAL_IF(!fid, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
977 MAPISTORE_RETVAL_IF(folder_type != FOLDER_GENERIC && folder_type != FOLDER_SEARCH,
978 MAPISTORE_ERR_INVALID_PARAMETER, NULL);
980 /* Find the backend context to work within */
981 backend_ctx = mapistore_backend_lookup(mstore_ctx->context_list, context_id);
982 MAPISTORE_RETVAL_IF(!backend_ctx, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
984 /* Create an indexing context */
985 retval = mapistore_indexing_context_add(mstore_ctx, backend_ctx->username, &(mstore_ctx->mapistore_indexing_list));
986 MAPISTORE_RETVAL_IF(retval, retval, NULL);
988 /* Turn parent folder identifier into URI */
989 retval = mapistore_indexing_get_record_uri_by_fmid(mstore_ctx->mapistore_indexing_list, parent_fid, &parent_uri);
990 if (retval) goto cleanup;
992 /* Call backend mkdir */
993 retval = mapistore_backend_mkdir(backend_ctx, parent_uri, folder_name, folder_desc, folder_type, &folder_uri);
994 if (retval) goto cleanup;
996 /* Get a new FID for the folder */
997 retval = mapistore_get_new_fmid(mstore_ctx->processing_ctx, backend_ctx->username, &folder_fid);
998 if (retval) goto cleanup;
1000 /* Register the folder within the indexing database */
1001 retval = mapistore_indexing_add_fmid_record(mstore_ctx->mapistore_indexing_list, folder_fid,
1002 folder_uri, parent_fid, MAPISTORE_INDEXING_FOLDER);
1004 /* Return that folder ID to the caller for future use */
1008 mapistore_indexing_context_del(mstore_ctx, backend_ctx->username);
1011 MSTORE_DEBUG_INFO(MSTORE_LEVEL_INFO, "folder_uri = %s\n", folder_uri);
1012 talloc_free(folder_uri);
1020 \details Remove a directory in mapistore
1022 \param mstore_ctx pointer to the mapistore context
1023 \param context_id the context identifier referencing the backend
1024 \param parent_fid the parent folder identifier
1025 \param fid the folder identifier representing the folder to delete
1026 \param flags flags that control the behaviour of the operation
1028 \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE errors
1030 _PUBLIC_ enum MAPISTORE_ERROR mapistore_rmdir(struct mapistore_context *mstore_ctx,
1031 uint32_t context_id,
1032 uint64_t parent_fid,
1036 struct backend_context *backend_ctx;
1037 enum MAPISTORE_ERROR retval;
1042 MAPISTORE_SANITY_CHECKS(mstore_ctx, NULL);
1044 /* Step 1. Find the backend context */
1045 backend_ctx = mapistore_backend_lookup(mstore_ctx->context_list, context_id);
1046 MAPISTORE_RETVAL_IF(!backend_ctx, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
1048 /* Step 2. Create the mapistore_indexing context */
1049 retval = mapistore_indexing_context_add(mstore_ctx, backend_ctx->username, &(mstore_ctx->mapistore_indexing_list));
1050 MAPISTORE_RETVAL_IF(retval, retval, NULL);
1052 /* Retrieve URI associated to parent and folder ID */
1053 retval = mapistore_indexing_get_record_uri_by_fmid(mstore_ctx->mapistore_indexing_list, parent_fid, &parent_uri);
1054 if (retval) goto error;
1056 retval = mapistore_indexing_get_record_uri_by_fmid(mstore_ctx->mapistore_indexing_list, fid, &folder_uri);
1057 if (retval) goto error;
1059 /* Step 2. Handle deletion of child folders / messages */
1060 if (flags | DEL_FOLDERS) {
1061 uint64_t *childFolders;
1062 uint32_t childFolderCount;
1066 /* Get subfolders list */
1067 retval = mapistore_get_child_fids(mstore_ctx, context_id, fid,
1068 &childFolders, &childFolderCount);
1070 retval = MAPISTORE_ERR_NOT_FOUND;
1074 /* Delete each subfolder in mapistore */
1075 for (i = 0; i < childFolderCount; ++i) {
1076 retval = mapistore_rmdir(mstore_ctx, context_id, fid, childFolders[i], flags);
1078 talloc_free(childFolders);
1079 retval = MAPISTORE_ERR_NOT_FOUND;
1086 /* Step 3. Call backend rmdir */
1087 retval = mapistore_backend_rmdir(backend_ctx, parent_uri, folder_uri);
1090 mapistore_indexing_context_del(mstore_ctx, backend_ctx->username);
1097 \details Retrieve the number of child folders within a mapistore
1100 \param mstore_ctx pointer to the mapistore context
1101 \param context_id the context identifier referencing the backend
1102 \param fid the folder identifier
1103 \param RowCount pointer to the count result to return
1105 \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE errors
1107 _PUBLIC_ enum MAPISTORE_ERROR mapistore_get_folder_count(struct mapistore_context *mstore_ctx,
1108 uint32_t context_id,
1112 struct backend_context *backend_ctx;
1113 enum MAPISTORE_ERROR retval;
1117 MAPISTORE_SANITY_CHECKS(mstore_ctx, NULL);
1118 MAPISTORE_RETVAL_IF(!RowCount, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
1120 /* Step 1. Ensure the context exists */
1121 backend_ctx = mapistore_backend_lookup(mstore_ctx->context_list, context_id);
1122 MAPISTORE_RETVAL_IF(!backend_ctx, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
1124 /* Step 2. Create the mapistore_indexing context */
1125 retval = mapistore_indexing_context_add(mstore_ctx, backend_ctx->username, &(mstore_ctx->mapistore_indexing_list));
1126 MAPISTORE_RETVAL_IF(retval, retval, NULL);
1128 /* Step 3. Retrieve the folder URI from the indexing database */
1129 retval = mapistore_indexing_get_record_uri_by_fmid(mstore_ctx->mapistore_indexing_list, fid, &folder_uri);
1130 if (retval) goto error;
1132 /* Step 4. Call backend readdir */
1133 retval = mapistore_backend_readdir_count(backend_ctx, (const char *)folder_uri, MAPISTORE_FOLDER_TABLE, RowCount);
1136 mapistore_indexing_context_del(mstore_ctx, backend_ctx->username);
1143 \details Retrieve the number of child messages within a mapistore folder
1145 \param mstore_ctx pointer to the mapistore context
1146 \param context_id the context identifier referencing the backend
1147 \param fid the folder identifier
1148 \param RowCount pointer to the count result to return
1150 \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE errors
1152 _PUBLIC_ enum MAPISTORE_ERROR mapistore_get_message_count(struct mapistore_context *mstore_ctx,
1153 uint32_t context_id,
1157 struct backend_context *backend_ctx;
1158 enum MAPISTORE_ERROR retval;
1162 MAPISTORE_SANITY_CHECKS(mstore_ctx, NULL);
1163 MAPISTORE_RETVAL_IF(!RowCount, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
1165 /* Step 1. Ensure the context exists */
1166 backend_ctx = mapistore_backend_lookup(mstore_ctx->context_list, context_id);
1167 MAPISTORE_RETVAL_IF(!backend_ctx, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
1169 /* Step 2. Create the mapistore_indexing context */
1170 retval = mapistore_indexing_context_add(mstore_ctx, backend_ctx->username, &(mstore_ctx->mapistore_indexing_list));
1171 MAPISTORE_RETVAL_IF(retval, retval, NULL);
1173 /* Step 3. Retrieve the folder URI from the indexing database */
1174 retval = mapistore_indexing_get_record_uri_by_fmid(mstore_ctx->mapistore_indexing_list, fid, &folder_uri);
1175 if (retval) goto error;
1177 /* Step 2. Call backend readdir_count */
1178 retval = mapistore_backend_readdir_count(backend_ctx, (const char *)folder_uri, MAPISTORE_MESSAGE_TABLE, RowCount);
1181 mapistore_indexing_context_del(mstore_ctx, backend_ctx->username);
1188 \details Retrieve a MAPI property from a table
1190 \param mstore_ctx pointer to the mapistore context
1191 \param context_id the context identifier referencing the backend
1192 \param table_type the type of table (folders or messges)
1193 \param fid the folder identifier where the search takes place
1194 \param proptag the MAPI property tag to retrieve value for
1195 \param pos the record position in search results
1196 \param data pointer on pointer to the data the function returns
1198 \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE errors
1200 _PUBLIC_ enum MAPISTORE_ERROR mapistore_get_table_property(struct mapistore_context *mstore_ctx,
1201 uint32_t context_id,
1202 enum MAPISTORE_TABLE_TYPE table_type,
1204 enum MAPITAGS proptag,
1208 struct backend_context *backend_ctx;
1209 enum MAPISTORE_ERROR retval;
1213 MAPISTORE_SANITY_CHECKS(mstore_ctx, NULL);
1214 MAPISTORE_RETVAL_IF(!data, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
1216 /* Step 1. Ensure the context exists */
1217 backend_ctx = mapistore_backend_lookup(mstore_ctx->context_list, context_id);
1218 MAPISTORE_RETVAL_IF(!backend_ctx, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
1220 /* Step 2. Create the mapistore_indexing context */
1221 retval = mapistore_indexing_context_add(mstore_ctx, backend_ctx->username, &(mstore_ctx->mapistore_indexing_list));
1222 MAPISTORE_RETVAL_IF(retval, retval, NULL);
1224 /* Step 3. Retrieve the URI for the folder */
1225 retval = mapistore_indexing_get_record_uri_by_fmid(mstore_ctx->mapistore_indexing_list, fid, &folder_uri);
1226 if (retval) goto error;
1228 /* Step 2. Call backend readdir */
1229 retval = mapistore_backend_get_table_property(backend_ctx, (const char *)folder_uri, table_type, pos, proptag, data);
1232 mapistore_indexing_context_del(mstore_ctx, backend_ctx->username);
1239 \details Open a message in mapistore
1241 \param mstore_ctx pointer to the mapistore context
1242 \param context_id the context identifier referencing the backend
1243 where the directory will be opened
1244 \param parent_fid the parent folder identifier
1245 \param mid the message identifier to open
1246 \param msg pointer to the mapistore_message structure (result)
1248 \return MAPISTORE SUCCESS on success, otherwise MAPISTORE errors
1250 _PUBLIC_ enum MAPISTORE_ERROR mapistore_openmessage(struct mapistore_context *mstore_ctx,
1251 uint32_t context_id,
1252 uint64_t parent_fid,
1254 struct mapistore_message *msg)
1256 enum MAPISTORE_ERROR retval;
1257 struct backend_context *backend_ctx;
1262 MAPISTORE_SANITY_CHECKS(mstore_ctx, NULL);
1263 MAPISTORE_RETVAL_IF(!msg, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
1265 /* Step 1. Search the context */
1266 backend_ctx = mapistore_backend_lookup(mstore_ctx->context_list, context_id);
1267 MAPISTORE_RETVAL_IF(!backend_ctx, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
1269 /* Step 2. Create the mapistore_indexing context */
1270 retval = mapistore_indexing_context_add(mstore_ctx, backend_ctx->username, &(mstore_ctx->mapistore_indexing_list));
1271 MAPISTORE_RETVAL_IF(retval, retval, NULL);
1273 /* Step 3. Retrieve the URI for parent folder and message */
1274 retval = mapistore_indexing_get_record_uri_by_fmid(mstore_ctx->mapistore_indexing_list, parent_fid, &parent_uri);
1275 if (retval) goto error;
1277 retval = mapistore_indexing_get_record_uri_by_fmid(mstore_ctx->mapistore_indexing_list, mid, &message_uri);
1278 if (retval) goto error;
1280 /* Step 4. Call backend openmessage */
1281 retval = mapistore_backend_openmessage(backend_ctx, parent_uri, message_uri, msg);
1284 mapistore_indexing_context_del(mstore_ctx, backend_ctx->username);
1291 \details Create a message in mapistore
1293 \param mstore_ctx pointer to the mapistore context
1294 \param context_id the context identifier referencing the backend
1295 where the message will be created
1296 \param parent_fid the parent folder identifier
1298 \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE errors
1300 _PUBLIC_ enum MAPISTORE_ERROR mapistore_createmessage(struct mapistore_context *mstore_ctx,
1301 uint32_t context_id,
1302 uint64_t parent_fid)
1304 enum MAPISTORE_ERROR retval;
1305 struct backend_context *backend_ctx;
1307 char *message_uri = NULL;
1308 bool uri_register = false;
1311 MAPISTORE_SANITY_CHECKS(mstore_ctx, NULL);
1313 /* Step 1. Search the context */
1314 backend_ctx = mapistore_backend_lookup(mstore_ctx->context_list, context_id);
1315 MAPISTORE_RETVAL_IF(!backend_ctx, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
1317 /* Step 2. Create the mapistore_indexing context */
1318 retval = mapistore_indexing_context_add(mstore_ctx, backend_ctx->username, &(mstore_ctx->mapistore_indexing_list));
1319 MAPISTORE_RETVAL_IF(retval, retval, NULL);
1321 /* Step 3. Retrieve the URI for parent folder */
1322 retval = mapistore_indexing_get_record_uri_by_fmid(mstore_ctx->mapistore_indexing_list, parent_fid, &parent_uri);
1323 if (retval) goto error;
1325 /* Step 4. Call backend createmessage */
1326 retval = mapistore_backend_createmessage(backend_ctx, parent_uri, &message_uri, &uri_register);
1327 if (retval) goto error;
1329 /* Step 5. FIXME: Do appropriate mapistore work depending on uri_register value */
1332 mapistore_indexing_context_del(mstore_ctx, backend_ctx->username);
1339 \details Commit the changes made to a message in mapistore
1341 \param mstore_ctx pointer to the mapistore context
1342 \param context_id the context identifier referencing the backend
1343 where the message's changes will be saved
1344 \param mid the message identifier to return or save
1345 \param flags flags associated to the commit operation
1347 \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE errors
1349 _PUBLIC_ enum MAPISTORE_ERROR mapistore_savechangesmessage(struct mapistore_context *mstore_ctx,
1350 uint32_t context_id,
1354 enum MAPISTORE_ERROR retval;
1355 struct backend_context *backend_ctx;
1359 MAPISTORE_SANITY_CHECKS(mstore_ctx, NULL);
1361 /* Step 1. Search the context */
1362 backend_ctx = mapistore_backend_lookup(mstore_ctx->context_list, context_id);
1363 MAPISTORE_RETVAL_IF(!backend_ctx, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
1365 /* FIXME: It's either a temporary (not committed mid) or an
1366 * existing message. Take appropriate action depending on
1369 /* Step 2. Create the mapistore_indexing context */
1370 retval = mapistore_indexing_context_add(mstore_ctx, backend_ctx->username, &(mstore_ctx->mapistore_indexing_list));
1371 MAPISTORE_RETVAL_IF(retval, retval, NULL);
1373 /* Step 3. Retrieve the URI for parent folder */
1374 retval = mapistore_indexing_get_record_uri_by_fmid(mstore_ctx->mapistore_indexing_list, *mid, &message_uri);
1375 if (retval) goto error;
1377 /* Step 4. Call backend savechangesmessage */
1378 retval = mapistore_backend_savechangesmessage(backend_ctx, message_uri, flags);
1381 mapistore_indexing_context_del(mstore_ctx, backend_ctx->username);
1388 \details Submits a message for sending.
1390 \param mstore_ctx pointer to the mapistore context
1391 \param context_id the context identifier referencing the backend
1392 where the message will be submitted
1393 \param mid the message identifier representing the message to submit
1394 \param flags flags associated to the submit operation
1396 \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE errors
1398 _PUBLIC_ enum MAPISTORE_ERROR mapistore_submitmessage(struct mapistore_context *mstore_ctx,
1399 uint32_t context_id,
1403 enum MAPISTORE_ERROR retval;
1404 struct backend_context *backend_ctx;
1408 MAPISTORE_SANITY_CHECKS(mstore_ctx, NULL);
1410 /* Step 1. Search the context */
1411 backend_ctx = mapistore_backend_lookup(mstore_ctx->context_list, context_id);
1412 MAPISTORE_RETVAL_IF(!backend_ctx, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
1414 /* FIXME: It's either a temporary (not committed mid) or an
1415 * existing message. Take appropriate action depending on
1418 /* Step 2. Create the mapistore_indexing context */
1419 retval = mapistore_indexing_context_add(mstore_ctx, backend_ctx->username, &(mstore_ctx->mapistore_indexing_list));
1420 MAPISTORE_RETVAL_IF(retval, retval, NULL);
1422 /* Step 3. Retrieve the URI for the message */
1423 retval = mapistore_indexing_get_record_uri_by_fmid(mstore_ctx->mapistore_indexing_list, *mid, &message_uri);
1424 if (retval) goto error;
1426 /* Step 2. Call backend submitmessage */
1427 retval = mapistore_backend_submitmessage(backend_ctx, message_uri, flags);
1430 mapistore_indexing_context_del(mstore_ctx, backend_ctx->username);
1437 \details Get properties of a message/folder in mapistore
1439 \param mstore_ctx pointer to the mapistore context
1440 \param context_id the context identifier referencing the backend
1441 where properties will be fetched
1442 \param fmid the identifier referencing the message/folder
1443 \param type the object type (folder or message)
1444 \param properties pointer to the list of properties to fetch
1445 \param aRow pointer to the SRow structure
1447 \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE errors
1449 _PUBLIC_ enum MAPISTORE_ERROR mapistore_getprops(struct mapistore_context *mstore_ctx,
1450 uint32_t context_id,
1453 struct SPropTagArray *properties,
1456 enum MAPISTORE_ERROR retval;
1457 struct backend_context *backend_ctx;
1461 MAPISTORE_SANITY_CHECKS(mstore_ctx, NULL);
1463 /* Step 1. Search the context */
1464 backend_ctx = mapistore_backend_lookup(mstore_ctx->context_list, context_id);
1465 MAPISTORE_RETVAL_IF(!backend_ctx, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
1467 /* Step 2. Create the mapistore_indexing context */
1468 retval = mapistore_indexing_context_add(mstore_ctx, backend_ctx->username, &(mstore_ctx->mapistore_indexing_list));
1469 MAPISTORE_RETVAL_IF(retval, retval, NULL);
1471 /* Step 3. Retrieve the uri for the fmid from the indexing database */
1472 retval = mapistore_indexing_get_record_uri_by_fmid(mstore_ctx->mapistore_indexing_list, fmid, &uri);
1473 if (retval) goto error;
1475 /* Step 4. Call backend getprops */
1476 retval = mapistore_backend_getprops(backend_ctx, uri, type, properties, aRow);
1479 mapistore_indexing_context_del(mstore_ctx, backend_ctx->username);
1485 \details Search for a folder ID by name
1487 \param mstore_ctx pointer to the mapistore context
1488 \param context_id the context identifier referencing the backend
1489 where the folder will be searched for
1490 \param parent_fid the parent folder identifier
1491 \param name the name of the folder to search for
1492 \param fid the fid (result)
1494 \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE errors
1496 _PUBLIC_ enum MAPISTORE_ERROR mapistore_get_fid_by_name(struct mapistore_context *mstore_ctx,
1497 uint32_t context_id,
1498 uint64_t parent_fid,
1502 enum MAPISTORE_ERROR retval;
1503 struct backend_context *backend_ctx;
1507 MAPISTORE_SANITY_CHECKS(mstore_ctx, NULL);
1508 MAPISTORE_RETVAL_IF(!name, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
1509 MAPISTORE_RETVAL_IF(!fid, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
1511 /* Step 1. Search the context */
1512 backend_ctx = mapistore_backend_lookup(mstore_ctx->context_list, context_id);
1513 MAPISTORE_RETVAL_IF(!backend_ctx, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
1515 /* Step 2. Create the mapistore_indexing context */
1516 retval = mapistore_indexing_context_add(mstore_ctx, backend_ctx->username, &(mstore_ctx->mapistore_indexing_list));
1517 MAPISTORE_RETVAL_IF(retval, retval, NULL);
1519 /* Step 3. Retrieve the folder URI from the indexing database */
1520 retval = mapistore_indexing_get_record_uri_by_fmid(mstore_ctx->mapistore_indexing_list, parent_fid, &parent_uri);
1521 if (retval) goto error;
1523 /* Step 2. Call backend getprops */
1524 retval = mapistore_backend_get_fid_by_name(backend_ctx, parent_uri, name, &uri);
1525 if (retval) goto error;
1527 /* Step 3. Retrieve the FID associated to this uri*/
1528 retval = mapistore_indexing_get_record_fmid_by_uri(mstore_ctx->mapistore_indexing_list, uri, fid);
1531 mapistore_indexing_context_del(mstore_ctx, backend_ctx->username);
1537 \details Set properties of a message/folder in mapistore
1539 \param mstore_ctx pointer to the mapistore context
1540 \param context_id the context identifier referencing the backend
1541 where properties will be stored
1542 \param fmid the identifier referencing the message/folder
1543 \param type the object type (folder or message)
1544 \param aRow pointer to the SRow structure
1546 \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE errors
1548 _PUBLIC_ enum MAPISTORE_ERROR mapistore_setprops(struct mapistore_context *mstore_ctx,
1549 uint32_t context_id,
1554 enum MAPISTORE_ERROR retval;
1555 struct backend_context *backend_ctx;
1559 MAPISTORE_SANITY_CHECKS(mstore_ctx, NULL);
1561 /* Step 1. Search the context */
1562 backend_ctx = mapistore_backend_lookup(mstore_ctx->context_list, context_id);
1563 MAPISTORE_RETVAL_IF(!backend_ctx, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
1565 /* Step 2. Create mapistore_indexing context */
1566 retval = mapistore_indexing_context_add(mstore_ctx, backend_ctx->username, &(mstore_ctx->mapistore_indexing_list));
1567 MAPISTORE_RETVAL_IF(retval, retval, NULL);
1569 /* Step 3. Retrieve the uri for the fmid from the indexing database */
1570 retval = mapistore_indexing_get_record_uri_by_fmid(mstore_ctx->mapistore_indexing_list, fmid, &uri);
1571 if (retval) goto error;
1573 /* Step 4. Call backend setprops */
1574 retval = mapistore_backend_setprops(backend_ctx, uri, type, aRow);
1577 mapistore_indexing_context_del(mstore_ctx, backend_ctx->username);
1584 \details Retrieve the folder IDs of child folders within a mapistore
1587 \param mstore_ctx pointer to the mapistore context
1588 \param context_id the context identifier referencing the backend
1589 \param fid the folder identifier (for the parent folder)
1590 \param child_fids pointer to where to return the array of child fids
1591 \param child_fid_count pointer to the count result to return
1593 \note The caller is responsible for freeing the \p child_fids array
1594 when it is no longer required.
1596 \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE errors
1598 _PUBLIC_ enum MAPISTORE_ERROR mapistore_get_child_fids(struct mapistore_context *mstore_ctx,
1599 uint32_t context_id,
1601 uint64_t *child_fids[],
1602 uint32_t *child_fid_count)
1604 enum MAPISTORE_ERROR retval;
1605 struct backend_context *backend_ctx;
1611 MAPISTORE_SANITY_CHECKS(mstore_ctx, NULL);
1613 /* Step 1. Ensure the context exists */
1614 backend_ctx = mapistore_backend_lookup(mstore_ctx->context_list, context_id);
1615 MAPISTORE_RETVAL_IF(!backend_ctx, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
1617 /* Step 2. Create the mapistore_indexing context */
1618 retval = mapistore_indexing_context_add(mstore_ctx, backend_ctx->username, &(mstore_ctx->mapistore_indexing_list));
1619 MAPISTORE_RETVAL_IF(retval, retval, NULL);
1621 /* Step 3. Retrieve the folder URI from the indexing database */
1622 retval = mapistore_indexing_get_record_uri_by_fmid(mstore_ctx->mapistore_indexing_list, fid, &folder_uri);
1624 mapistore_indexing_context_del(mstore_ctx, backend_ctx->username);
1628 /* Step 1. Call backend readdir to get the folder count */
1629 retval = mapistore_backend_readdir_count(backend_ctx, folder_uri, MAPISTORE_FOLDER_TABLE, child_fid_count);
1631 mapistore_indexing_context_del(mstore_ctx, backend_ctx->username);
1635 retval = mapistore_indexing_context_del(mstore_ctx, backend_ctx->username);
1636 MAPISTORE_RETVAL_IF(retval, retval, NULL);
1638 /* Step 2. Create a suitable sized array for the fids */
1639 *child_fids = talloc_zero_array((TALLOC_CTX *)mstore_ctx, uint64_t, *child_fid_count);
1640 MAPISTORE_RETVAL_IF(!*child_fids, MAPISTORE_ERR_NO_MEMORY, NULL);
1642 /* Step 3. Fill the array */
1643 for (i = 0; i < *child_fid_count; ++i) {
1644 // TODO: add error checking for this call
1645 retval = mapistore_get_table_property(mstore_ctx, context_id, MAPISTORE_FOLDER_TABLE,
1646 fid, PR_FID, i, &data);
1647 MAPISTORE_RETVAL_IF(retval, retval, *child_fids);
1648 (*child_fids)[i] = *((uint64_t*)(data));
1655 \details Delete a message from mapistore
1657 \param mstore_ctx pointer to the mapistore context
1658 \param context_id the context identifier referencing the backend
1659 where the message's to be located is stored
1660 \param mid the message identifier of the folder to delete
1661 \param deletion_type the type of deletion (MAPISTORE_SOFT_DELETE or MAPISTORE_PERMANENT_DELETE)
1663 \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE errors
1665 _PUBLIC_ enum MAPISTORE_ERROR mapistore_deletemessage(struct mapistore_context *mstore_ctx,
1666 uint32_t context_id,
1668 enum MAPISTORE_DELETION_TYPE deletion_type)
1670 enum MAPISTORE_ERROR retval;
1671 struct backend_context *backend_ctx;
1675 MAPISTORE_SANITY_CHECKS(mstore_ctx, NULL);
1677 /* Step 1. Search the context */
1678 backend_ctx = mapistore_backend_lookup(mstore_ctx->context_list, context_id);
1679 MAPISTORE_RETVAL_IF(!backend_ctx, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
1681 /* Step 2. Create the mapistore_indexing context */
1682 retval = mapistore_indexing_context_add(mstore_ctx, backend_ctx->username, &(mstore_ctx->mapistore_indexing_list));
1683 MAPISTORE_RETVAL_IF(retval, retval, NULL);
1685 /* Step 3. Retrieve the message URI from the indexing database */
1686 retval = mapistore_indexing_get_record_uri_by_fmid(mstore_ctx->mapistore_indexing_list, mid, &message_uri);
1687 if (retval) goto error;
1689 /* Step 4. Call backend operation */
1690 retval = mapistore_backend_deletemessage(backend_ctx, message_uri, deletion_type);
1693 mapistore_indexing_context_del(mstore_ctx, backend_ctx->username);