Tries to mimic backend's object oriented model.
OpenChange Server can now perform following calls using openchangedb:
- OpenMessage
- GetProps on messages
- GetContentsTable
- FindRow with RES_PROPERTY restriction
Note that mapi_SRestriction support is highly limited for now.
mapiproxy/libmapiproxy/dcesrv_mapiproxy_server.po \
mapiproxy/libmapiproxy/dcesrv_mapiproxy_session.po \
mapiproxy/libmapiproxy/openchangedb.po \
+ mapiproxy/libmapiproxy/openchangedb_table.po \
+ mapiproxy/libmapiproxy/openchangedb_message.po \
mapiproxy/libmapiproxy/openchangedb_property.po \
mapiproxy/libmapiproxy/mapi_handles.po \
mapiproxy/libmapiproxy/entryid.po \
struct mapi_handles *handles;
};
+struct openchangedb_table {
+ uint64_t folderID;
+ uint8_t table_type;
+ struct SSortOrderSet *lpSortCriteria;
+ struct mapi_SRestriction *restrictions;
+ struct ldb_result *res;
+};
+
+struct openchangedb_message {
+ uint64_t messageID;
+ uint64_t folderID;
+ struct ldb_result *res;
+};
+
#define MAPI_HANDLES_RESERVED 0xFFFFFFFF
#define MAPI_HANDLES_ROOT "root"
enum MAPISTATUS openchangedb_set_folder_properties(void *, uint64_t, struct SRow *);
enum MAPISTATUS openchangedb_get_folder_property(TALLOC_CTX *, void *, char *, uint32_t, uint64_t, void **);
enum MAPISTATUS openchangedb_get_folder_count(void *, uint64_t, uint32_t *);
+enum MAPISTATUS openchangedb_get_message_count(void *, uint64_t, uint32_t *);
enum MAPISTATUS openchangedb_get_table_property(TALLOC_CTX *, void *, char *, char *, uint32_t, uint32_t, void **);
enum MAPISTATUS openchangedb_get_fid_by_name(void *, uint64_t, const char*, uint64_t *);
enum MAPISTATUS openchangedb_set_ReceiveFolder(TALLOC_CTX *, void *, const char *, const char *, uint64_t);
enum MAPISTATUS openchangedb_create_message(TALLOC_CTX *, void *, uint64_t, uint64_t, struct ldb_message **);
enum MAPISTATUS openchangedb_set_message_properties(TALLOC_CTX *, void *, struct ldb_message *, struct SRow *);
enum MAPISTATUS openchangedb_save_message(void *, struct ldb_message *);
+void *openchangedb_get_special_property(TALLOC_CTX *, void *, char *, struct ldb_result *, uint32_t, const char *);
+void *openchangedb_get_property_data(TALLOC_CTX *, struct ldb_result *, uint32_t, uint32_t, const char *);
+
+/* definitions from openchangedb_table.c */
+enum MAPISTATUS openchangedb_table_init(TALLOC_CTX *, uint8_t, uint64_t, void **);
+enum MAPISTATUS openchangedb_table_set_sort_order(void *, struct SSortOrderSet *);
+enum MAPISTATUS openchangedb_table_set_restrictions(void *, struct mapi_SRestriction *);
+enum MAPISTATUS openchangedb_table_get_property(TALLOC_CTX *, void *, void *, char *, uint32_t, uint32_t, void **);
+
+/* definitions from openchangedb_message.c */
+enum MAPISTATUS openchangedb_message_open(TALLOC_CTX *, void *, uint64_t, uint64_t, void **, void **);
+enum MAPISTATUS openchangedb_message_get_property(TALLOC_CTX *, void *, uint32_t, void **);
/* definitions from auto-generated openchangedb_property.c */
const char *openchangedb_property_get_attribute(uint32_t);
\return pointer to valid data on success, otherwise NULL
*/
-static void *openchangedb_get_folder_special_property(TALLOC_CTX *mem_ctx,
- void *ldb_ctx,
- char *recipient,
- struct ldb_result *res,
- uint32_t proptag,
- const char *PidTagAttr)
+void *openchangedb_get_special_property(TALLOC_CTX *mem_ctx,
+ void *ldb_ctx,
+ char *recipient,
+ struct ldb_result *res,
+ uint32_t proptag,
+ const char *PidTagAttr)
{
uint32_t *l;
\return valid data pointer on success, otherwise NULL
*/
-static void *openchangedb_get_folder_property_data(TALLOC_CTX *mem_ctx,
- struct ldb_result *res,
- uint32_t pos,
- uint32_t proptag,
- const char *PidTagAttr)
+void *openchangedb_get_property_data(TALLOC_CTX *mem_ctx,
+ struct ldb_result *res,
+ uint32_t pos,
+ uint32_t proptag,
+ const char *PidTagAttr)
{
void *data;
const char *str;
OPENCHANGE_RETVAL_IF(!ldb_msg_find_element(res->msgs[0], PidTagAttr), MAPI_E_NOT_FOUND, mem_ctx);
/* Step 4. Check if this is a "special property" */
- *data = openchangedb_get_folder_special_property(parent_ctx, ldb_ctx, recipient, res, proptag, PidTagAttr);
+ *data = openchangedb_get_special_property(parent_ctx, ldb_ctx, recipient, res, proptag, PidTagAttr);
OPENCHANGE_RETVAL_IF(*data != NULL, MAPI_E_SUCCESS, mem_ctx);
/* Step 5. If this is not a "special property" */
- *data = openchangedb_get_folder_property_data(parent_ctx, res, 0, proptag, PidTagAttr);
+ *data = openchangedb_get_property_data(parent_ctx, res, 0, proptag, PidTagAttr);
OPENCHANGE_RETVAL_IF(*data != NULL, MAPI_E_SUCCESS, mem_ctx);
talloc_free(mem_ctx);
OPENCHANGE_RETVAL_IF(!ldb_msg_find_element(res->msgs[pos], PidTagAttr), MAPI_E_NOT_FOUND, mem_ctx);
/* Step 5. Check if this is a "special property" */
- *data = openchangedb_get_folder_special_property(parent_ctx, ldb_ctx, recipient, res, proptag, PidTagAttr);
+ *data = openchangedb_get_special_property(parent_ctx, ldb_ctx, recipient, res, proptag, PidTagAttr);
OPENCHANGE_RETVAL_IF(*data != NULL, MAPI_E_SUCCESS, mem_ctx);
/* Step 6. Check if this is not a "special property" */
- *data = openchangedb_get_folder_property_data(parent_ctx, res, pos, proptag, PidTagAttr);
+ *data = openchangedb_get_property_data(parent_ctx, res, pos, proptag, PidTagAttr);
OPENCHANGE_RETVAL_IF(*data != NULL, MAPI_E_SUCCESS, mem_ctx);
talloc_free(mem_ctx);
uint64_t fid)
{
TALLOC_CTX *mem_ctx;
+ enum MAPISTATUS retval;
struct ldb_result *res = NULL;
struct ldb_dn *dn;
char *dnstr;
/* Step 3. Delete the old entry if applicable */
if (res->count) {
/* we already have an entry for this message class, so delete it before creating the new one */
- enum MAPISTATUS retval;
char *distinguishedName;
struct ldb_message *msg;
/* Step 4. Create the new entry if applicable */
if (fid != 0x0) {
- enum MAPISTATUS retval;
char *distinguishedName;
struct ldb_message *msg;
}
+/**
+ \details Retrieve the number of messages within the specified folder
+
+ \param ldb_ctx pointer to the openchange LDB context
+ \param fid the folder identifier to use for the search
+ \param RowCount pointer to the returned number of results
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI_E_NOT_FOUND
+ */
+_PUBLIC_ enum MAPISTATUS openchangedb_get_message_count(void *ldb_ctx,
+ uint64_t fid,
+ uint32_t *RowCount)
+{
+ TALLOC_CTX *mem_ctx;
+ struct ldb_result *res;
+ const char * const attrs[] = { "*", NULL };
+ int ret;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!ldb_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!RowCount, MAPI_E_INVALID_PARAMETER, NULL);
+
+ mem_ctx = talloc_named(NULL, 0, "get_message_count");
+ *RowCount = 0;
+
+ ret = ldb_search(ldb_ctx, mem_ctx, &res, ldb_get_default_basedn(ldb_ctx),
+ LDB_SCOPE_SUBTREE, attrs,
+ "PidTagParentFolderId=%"PRIu64")(PidTagMessageId=*)", fid);
+ printf("ldb error: %s\n", ldb_errstring(ldb_ctx));
+ OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS, MAPI_E_NOT_FOUND, mem_ctx);
+
+ *RowCount = res->count;
+
+ talloc_free(mem_ctx);
+
+ return MAPI_E_SUCCESS;
+}
+
+
/**
\details Create a message for openchangedb. The message is not
saved in LDB until the save function is called.
--- /dev/null
+/*
+ OpenChange Server implementation
+
+ EMSMDBP: EMSMDB Provider implementation
+
+ Copyright (C) Julien Kerihuel 2011
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ \file openchangedb_message.c
+
+ \brief OpenChange Dispatcher database message routines
+ */
+
+#include <inttypes.h>
+
+#include "mapiproxy/dcesrv_mapiproxy.h"
+#include "mapiproxy/libmapistore/mapistore.h"
+#include "libmapiproxy.h"
+#include "libmapi/libmapi.h"
+#include "libmapi/libmapi_private.h"
+
+/**
+ /details Initialize an openchangedb table
+
+ \param mem_ctx pointer to the memory context to use for allocation
+ \param table_type the type of table this object represents
+ \param folderID the identifier of the folder this table represents
+ \param table_object pointer on pointer to the table object to return
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPISTORE error
+ */
+_PUBLIC_ enum MAPISTATUS openchangedb_message_open(TALLOC_CTX *mem_ctx, void *ldb_ctx,
+ uint64_t messageID, uint64_t folderID,
+ void **message_object, void **msgp)
+{
+ struct mapistore_message *mmsg;
+ struct openchangedb_message *msg;
+ const char * const attrs[] = { "*", NULL };
+ int ret;
+ char *ldb_filter;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!ldb_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!message_object, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!msgp, MAPI_E_NOT_INITIALIZED, NULL);
+
+ msg = talloc_zero(mem_ctx, struct openchangedb_message);
+ if (!msg) {
+ return MAPI_E_NOT_ENOUGH_MEMORY;
+ }
+ printf("openchangedb_message_open: folderID=%"PRIu64" messageID=%"PRIu64"\n", folderID, messageID);
+ msg->folderID = folderID;
+ msg->messageID = messageID;
+
+ /* Open the message and load results */
+ ldb_filter = talloc_asprintf(mem_ctx, "(&(PidTagParentFolderId=%"PRIu64")(PidTagMessageId=%"PRIu64"))", folderID, messageID);
+ ret = ldb_search(ldb_ctx, (TALLOC_CTX *)msg, &msg->res, ldb_get_default_basedn(ldb_ctx),
+ LDB_SCOPE_SUBTREE, attrs, ldb_filter, NULL);
+ printf("We have found: %d messages for ldb_filter = %s\n", msg->res->count, ldb_filter);
+ talloc_free(ldb_filter);
+ OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS || !msg->res->count, MAPI_E_NOT_FOUND, msg);
+
+ mmsg = talloc_zero(mem_ctx, struct mapistore_message);
+ mmsg->subject_prefix = NULL;
+ mmsg->normalized_subject = ldb_msg_find_attr_as_string(msg->res->msgs[0], "PidTagNormalizedSubject", NULL);
+ mmsg->columns = NULL;
+ mmsg->recipients_count = 0;
+ mmsg->recipients = NULL;
+
+ *message_object = (void *)msg;
+ *msgp = (void *)mmsg;
+
+ return MAPI_E_SUCCESS;
+}
+
+
+_PUBLIC_ enum MAPISTATUS openchangedb_message_get_property(TALLOC_CTX *mem_ctx, void *message_object,
+ uint32_t proptag, void **data)
+{
+ struct openchangedb_message *msg;
+ const char *PidTagAttr = NULL;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!message_object, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!data, MAPI_E_NOT_INITIALIZED, NULL);
+
+ msg = (struct openchangedb_message *)message_object;
+ OPENCHANGE_RETVAL_IF(!msg->res, MAPI_E_NOT_INITIALIZED, NULL);
+
+ /* Turn property into PidTagAttr */
+ PidTagAttr = (char *) openchangedb_property_get_attribute(proptag);
+
+ /* Ensure the element exists */
+ OPENCHANGE_RETVAL_IF(!ldb_msg_find_element(msg->res->msgs[0], PidTagAttr), MAPI_E_NOT_FOUND, NULL);
+
+ /* Retrieve data */
+ *data = openchangedb_get_property_data(mem_ctx, msg->res, 0, proptag, PidTagAttr);
+ OPENCHANGE_RETVAL_IF(*data != NULL, MAPI_E_SUCCESS, NULL);
+
+ return MAPI_E_NOT_FOUND;
+}
--- /dev/null
+/*
+ OpenChange Server implementation
+
+ EMSMDBP: EMSMDB Provider implementation
+
+ Copyright (C) Julien Kerihuel 2011
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ \file openchangedb_table.c
+
+ \brief OpenChange Dispatcher database table routines
+ */
+
+#include <inttypes.h>
+
+#include "mapiproxy/dcesrv_mapiproxy.h"
+#include "libmapiproxy.h"
+#include "libmapi/libmapi.h"
+#include "libmapi/libmapi_private.h"
+
+/**
+ /details Initialize an openchangedb table
+
+ \param mem_ctx pointer to the memory context to use for allocation
+ \param table_type the type of table this object represents
+ \param folderID the identifier of the folder this table represents
+ \param table_object pointer on pointer to the table object to return
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPISTORE error
+ */
+_PUBLIC_ enum MAPISTATUS openchangedb_table_init(TALLOC_CTX *mem_ctx, uint8_t table_type,
+ uint64_t folderID, void **table_object)
+{
+ struct openchangedb_table *table;
+
+ /* Sanity checks */
+ MAPI_RETVAL_IF(!table_object, MAPI_E_NOT_INITIALIZED, NULL);
+
+ table = talloc_zero(mem_ctx, struct openchangedb_table);
+ if (!table) {
+ return MAPI_E_NOT_ENOUGH_MEMORY;
+ }
+ printf("openchangedb_table_init: folderID=%"PRIu64"\n", folderID);
+ table->folderID = folderID;
+ table->table_type = table_type;
+ table->lpSortCriteria = NULL;
+ table->restrictions = NULL;
+ table->res = NULL;
+
+ *table_object = (void *)table;
+
+ return MAPI_E_SUCCESS;
+}
+
+
+/**
+ \details Set sort order to specified openchangedb table object
+
+ \param table_object pointer to the table object
+ \param lpSortCriteria pointer to the sort order to save
+
+ \return MAPI_E_SUCCESS on success, otherwise MAPI error
+ */
+_PUBLIC_ enum MAPISTATUS openchangedb_table_set_sort_order(void *table_object,
+ struct SSortOrderSet *lpSortCriteria)
+{
+ struct openchangedb_table *table;
+ int i;
+
+ /* Sanity checks */
+ MAPI_RETVAL_IF(!table_object, MAPI_E_NOT_INITIALIZED, NULL);
+ MAPI_RETVAL_IF(!lpSortCriteria, MAPI_E_INVALID_PARAMETER, NULL);
+
+ table = (struct openchangedb_table *) table_object;
+
+ if (table->res) {
+ talloc_free(table->res);
+ }
+
+ if (table->lpSortCriteria) {
+ talloc_free(table->lpSortCriteria);
+ }
+
+ table->lpSortCriteria = talloc_zero((TALLOC_CTX *)table, struct SSortOrderSet);
+ if (!table->lpSortCriteria) {
+ return MAPI_E_NOT_ENOUGH_MEMORY;
+ }
+
+ table->lpSortCriteria->cSorts = lpSortCriteria->cSorts;
+ table->lpSortCriteria->cCategories = lpSortCriteria->cCategories;
+ table->lpSortCriteria->cExpanded = lpSortCriteria->cExpanded;
+ table->lpSortCriteria->aSort = talloc_array((TALLOC_CTX *)table->lpSortCriteria,
+ struct SSortOrder, table->lpSortCriteria->cSorts);
+
+ for (i = 0; i < table->lpSortCriteria->cSorts; i++) {
+ table->lpSortCriteria->aSort[i].ulPropTag = lpSortCriteria->aSort[i].ulPropTag;
+ table->lpSortCriteria->aSort[i].ulOrder = lpSortCriteria->aSort[i].ulOrder;
+ }
+
+ return MAPI_E_SUCCESS;
+}
+
+
+_PUBLIC_ enum MAPISTATUS openchangedb_table_set_restrictions(void *table_object,
+ struct mapi_SRestriction *res)
+{
+ struct openchangedb_table *table;
+
+ /* Sanity checks */
+ MAPI_RETVAL_IF(!table_object, MAPI_E_NOT_INITIALIZED, NULL);
+ MAPI_RETVAL_IF(!res, MAPI_E_INVALID_PARAMETER, NULL);
+
+ table = (struct openchangedb_table *) table_object;
+
+ if (table->res) {
+ talloc_free(table->res);
+ }
+
+ if (table->restrictions) {
+ talloc_free(table->restrictions);
+ }
+
+ table->restrictions = talloc_zero((TALLOC_CTX *)table_object, struct mapi_SRestriction);
+
+ switch (res->rt) {
+ case RES_PROPERTY:
+ table->restrictions->rt = res->rt;
+ table->restrictions->res.resProperty.relop = res->res.resProperty.relop;
+ table->restrictions->res.resProperty.ulPropTag = res->res.resProperty.ulPropTag;
+ table->restrictions->res.resProperty.lpProp.ulPropTag = res->res.resProperty.lpProp.ulPropTag;
+
+ switch (table->restrictions->res.resProperty.lpProp.ulPropTag & 0xFFFF) {
+ case PT_STRING8:
+ table->restrictions->res.resProperty.lpProp.value.lpszA = talloc_strdup((TALLOC_CTX *)table->restrictions, res->res.resProperty.lpProp.value.lpszA);
+ break;
+ case PT_UNICODE:
+ table->restrictions->res.resProperty.lpProp.value.lpszW = talloc_strdup((TALLOC_CTX *)table->restrictions, res->res.resProperty.lpProp.value.lpszW);
+ break;
+ default:
+ DEBUG(0, ("Unsupported property type for RES_PROPERTY restriction\n"));
+ break;
+ }
+ break;
+ default:
+ DEBUG(0, ("Unsupported restriction type: 0x%x\n", res->rt));
+ }
+
+ return MAPI_E_SUCCESS;
+}
+
+static char *openchangedb_table_build_filter(TALLOC_CTX *mem_ctx, struct openchangedb_table *table)
+{
+ char *filter = NULL;
+ const char *PidTagAttr = NULL;
+
+ switch (table->table_type) {
+ case 0x2 /* EMSMDBP_TABLE_MESSAGE_TYPE */:
+ filter = talloc_asprintf(mem_ctx, "(&(PidTagParentFolderId=%"PRIu64")(PidTagMessageId=*)", table->folderID);
+ break;
+ case 0x1 /* EMSMDBP_TABLE_FOLDER_TYPE */:
+ filter = talloc_asprintf(mem_ctx, "(&(PidTagParentFolderId=%"PRIu64")(PidTagFolderId=*)", table->folderID);
+ break;
+ }
+
+ if (table->restrictions) {
+ switch (table->restrictions->rt) {
+ case RES_PROPERTY:
+ /* Retrieve PidTagName */
+ PidTagAttr = openchangedb_property_get_attribute(table->restrictions->res.resProperty.ulPropTag);
+ if (!PidTagAttr) {
+ talloc_free(filter);
+ return NULL;
+ }
+ filter = talloc_asprintf_append(filter, "(%s=", PidTagAttr);
+ switch (table->restrictions->res.resProperty.ulPropTag & 0xFFFF) {
+ case PT_STRING8:
+ filter = talloc_asprintf_append(filter, "%s)", table->restrictions->res.resProperty.lpProp.value.lpszA);
+ break;
+ case PT_UNICODE:
+ filter = talloc_asprintf_append(filter, "%s)", table->restrictions->res.resProperty.lpProp.value.lpszW);
+ break;
+ default:
+ DEBUG(0, ("Unsupported RES_PROPERTY property type: 0x%.4x\n", (table->restrictions->res.resProperty.ulPropTag & 0xFFFF)));
+ talloc_free(filter);
+ return NULL;
+ }
+ }
+ }
+
+ /* Close filter */
+ filter = talloc_asprintf_append(filter, ")");
+
+ return filter;
+}
+
+_PUBLIC_ enum MAPISTATUS openchangedb_table_get_property(TALLOC_CTX *mem_ctx,
+ void *table_object,
+ void *ldb_ctx,
+ char *recipient,
+ uint32_t proptag,
+ uint32_t pos,
+ void **data)
+{
+ struct openchangedb_table *table;
+ struct ldb_result *res = NULL;
+ char *ldb_filter = NULL;
+ const char * const attrs[] = { "*", NULL };
+ const char *PidTagAttr = NULL;
+ int ret;
+
+ /* Sanity checks */
+ OPENCHANGE_RETVAL_IF(!table_object, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!ldb_ctx, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!recipient, MAPI_E_NOT_INITIALIZED, NULL);
+ OPENCHANGE_RETVAL_IF(!data, MAPI_E_NOT_INITIALIZED, NULL);
+
+ table = (struct openchangedb_table *)table_object;
+
+ /* Build ldb filter */
+ ldb_filter = openchangedb_table_build_filter(mem_ctx, table);
+ OPENCHANGE_RETVAL_IF(!ldb_filter, MAPI_E_TOO_COMPLEX, NULL);
+ DEBUG(0, ("ldb_filter = %s\n", ldb_filter));
+
+ /* Fetch results */
+ if (table->res) {
+ res = table->res;
+ printf("cached res->count = %d\n", res->count);
+ } else {
+ ret = ldb_search(ldb_ctx, (TALLOC_CTX *)table_object, &res,
+ ldb_get_default_basedn(ldb_ctx), LDB_SCOPE_SUBTREE,
+ attrs, ldb_filter, NULL);
+ talloc_free(ldb_filter);
+ DEBUG(0, ("res->count = %d\n", res->count));
+ OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS || !res->count, MAPI_E_INVALID_PARAMETER, NULL);
+ table->res = res;
+ }
+
+ /* Ensure position is within search results range */
+ OPENCHANGE_RETVAL_IF(pos >= res->count, MAPI_E_INVALID_OBJECT, NULL);
+
+ /* Convert proptag into PidTag attribute */
+ if ((table->table_type == 0x2) && proptag == PR_FID) {
+ proptag = PR_PARENT_FID;
+ }
+ PidTagAttr = openchangedb_property_get_attribute(proptag);
+ OPENCHANGE_RETVAL_IF(!PidTagAttr, MAPI_E_NOT_FOUND, NULL);
+
+ /* Ensure the element exists */
+ OPENCHANGE_RETVAL_IF(!ldb_msg_find_element(res->msgs[pos], PidTagAttr), MAPI_E_NOT_FOUND, NULL);
+
+ /* Check if this is a "special property" */
+ *data = openchangedb_get_special_property(mem_ctx, ldb_ctx, recipient, res, proptag, PidTagAttr);
+ OPENCHANGE_RETVAL_IF(*data != NULL, MAPI_E_SUCCESS, NULL);
+
+ /* Check if this is NOT a "special property" */
+ *data = openchangedb_get_property_data(mem_ctx, res, pos, proptag, PidTagAttr);
+ OPENCHANGE_RETVAL_IF(*data != NULL, MAPI_E_SUCCESS, NULL);
+
+ return MAPI_E_NOT_FOUND;
+}
DEBUG(5, ("unsupported object type\n"));
return MAPISTORE_ERROR;
}
+ printf("emsmdbp_folder_get_folder_count: folderID = %"PRIu64"\n", folderID);
retval = openchangedb_get_folder_count(emsmdbp_ctx->oc_ctx, folderID, row_countp);
}
return retval;
}
-_PUBLIC_ struct emsmdbp_object *emsmdbp_folder_open_table(TALLOC_CTX *mem_ctx, struct emsmdbp_object *parent_object, uint32_t table_type, uint32_t handle_id)
+_PUBLIC_ struct emsmdbp_object *emsmdbp_folder_open_table(TALLOC_CTX *mem_ctx,
+ struct emsmdbp_object *parent_object,
+ uint32_t table_type, uint32_t handle_id)
{
struct emsmdbp_object *table_object;
+ uint64_t folderID;
uint8_t mstore_type;
int ret;
}
else {
if (table_type == EMSMDBP_TABLE_FOLDER_TYPE) {
+ /* this gets data both for openchangedb and mapistore: needs improvement */
emsmdbp_folder_get_folder_count(parent_object->emsmdbp_ctx, parent_object, &table_object->object.table->denominator);
}
else {
- /* Non-mapistore message tables are always empty */
- table_object->object.table->denominator = 0;
+ /* Retrieve folder ID */
+ switch (parent_object->type) {
+ case EMSMDBP_OBJECT_FOLDER:
+ folderID = parent_object->object.folder->folderID;
+ break;
+ case EMSMDBP_OBJECT_MAILBOX:
+ folderID = parent_object->object.mailbox->folderID;
+ break;
+ default:
+ DEBUG(5, ("Unsupported object type"));
+ table_object->object.table->denominator = 0;
+ return table_object;
+ }
+
+ /* Non-mapistore message tables */
+ switch (table_type) {
+ case EMSMDBP_TABLE_MESSAGE_TYPE:
+ openchangedb_get_message_count(parent_object->emsmdbp_ctx->oc_ctx,
+ folderID,
+ &table_object->object.table->denominator);
+ break;
+ default:
+ DEBUG(0, ("Unhandled openchangedb table type for folders: %d\n", table_type));
+ table_object->object.table->denominator = 0;
+ abort();
+ }
+ }
+ if (!emsmdbp_is_mapistore(parent_object)) {
+ /* Retrieve folder ID */
+ switch (parent_object->type) {
+ case EMSMDBP_OBJECT_FOLDER:
+ folderID = parent_object->object.folder->folderID;
+ break;
+ case EMSMDBP_OBJECT_MAILBOX:
+ folderID = parent_object->object.mailbox->folderID;
+ break;
+ default:
+ DEBUG(5, ("Unsupported object type"));
+ table_object->object.table->denominator = 0;
+ return table_object;
+ }
+ DEBUG(0, ("Initializaing openchangedb table\n"));
+ openchangedb_table_init((TALLOC_CTX *)table_object, table_type, folderID, &table_object->backend_object);
}
}
}
talloc_free(data_pointers);
return NULL;
}
- }
- else {
+ } else {
if (table_object->parent_object->type == EMSMDBP_OBJECT_FOLDER) {
folderID = table_object->parent_object->object.folder->folderID;
}
odb_ctx = talloc_zero(NULL, void);
- table_filter = talloc_asprintf(odb_ctx, "(&(PidTagParentFolderId=%"PRIu64")(PidTagFolderId=*))", folderID);
- retval = openchangedb_get_table_property(odb_ctx, emsmdbp_ctx->oc_ctx, emsmdbp_ctx->username,
- table_filter, PR_FID, row_id, (void **) &rowFolderID);
+ /* Setup table_filter for openchangedb */
+ /* switch (table_object->object.table->ulType) { */
+ /* case EMSMDBP_TABLE_MESSAGE_TYPE: */
+ /* table_filter = talloc_asprintf(odb_ctx, "(&(PidTagParentFolderId=%"PRIu64")(PidTagMessageId=*))", folderID); */
+ /* break; */
+ /* case EMSMDBP_TABLE_FOLDER_TYPE: */
+ /* table_filter = talloc_asprintf(odb_ctx, "(&(PidTagParentFolderId=%"PRIu64")(PidTagFolderId=*))", folderID); */
+ /* break; */
+ /* default: */
+ /* DEBUG(5, ("[%s:%d]: Unsupported table type for openchangedb: %d\n", __FUNCTION__, __LINE__, */
+ /* table_object->object.table->ulType)); */
+ /* talloc_free(retvals); */
+ /* talloc_free(data_pointers); */
+ /* return NULL; */
+ /* } */
+
+ retval = openchangedb_table_get_property(odb_ctx, table_object->backend_object, emsmdbp_ctx->oc_ctx, emsmdbp_ctx->username,
+ PR_FID, row_id, (void **) &rowFolderID);
+ /* retval = openchangedb_get_table_property(odb_ctx, emsmdbp_ctx->oc_ctx, emsmdbp_ctx->username, */
+ /* table_filter, PR_FID, row_id, (void **) &rowFolderID); */
+ printf("openchangedb_table_get_property retval = 0x%.8x\n", retval);
if (retval == MAPI_E_INVALID_OBJECT) {
talloc_free(retvals);
talloc_free(data_pointers);
retval = MAPI_E_SUCCESS;
}
else {
- retval = openchangedb_get_table_property(data_pointers, emsmdbp_ctx->oc_ctx,
- emsmdbp_ctx->username,
- table_filter, table->properties[i],
+ retval = openchangedb_table_get_property(data_pointers, table_object->backend_object,
+ emsmdbp_ctx->oc_ctx, emsmdbp_ctx->username,
+ table->properties[i],
row_id, data_pointers + i);
+ /* retval = openchangedb_get_table_property(data_pointers, emsmdbp_ctx->oc_ctx, */
+ /* emsmdbp_ctx->username, */
+ /* table_filter, table->properties[i], */
+ /* row_id, data_pointers + i); */
}
/* DEBUG(5, (" %.8x: %d", table->properties[j], retval)); */
if (retval == MAPI_E_INVALID_OBJECT) {
switch (mapistore) {
case false:
/* system/special folder */
- DEBUG(0, ("[%s] not implemented yet - shouldn't occur\n", __location__));
+ message_object = emsmdbp_object_message_init(mem_ctx, emsmdbp_ctx, messageID, folder_object);
+ /* openchangedb_open_message(); */
+ if (openchangedb_message_open(mem_ctx, emsmdbp_ctx->oc_ctx, messageID, folderID, &message_object->backend_object, (void **)msgp) != MAPI_E_SUCCESS) {
+ printf("Invalid openchangedb message\n");
+ talloc_free(message_object);
+ message_object = NULL;
+ }
break;
case true:
/* mapistore implementation goes here */
return MAPISTORE_SUCCESS;
}
+static int emsmdbp_object_get_properties_message(TALLOC_CTX *mem_ctx, struct emsmdbp_context *emsmdbp_ctx,
+ struct emsmdbp_object *object, struct SPropTagArray *properties,
+ void **data_pointers, enum MAPISTATUS *retvals)
+{
+ enum MAPISTATUS retval;
+ int i;
+ struct Binary_r *binr;
+
+ /* Look over properties */
+ for (i = 0; i < properties->cValues; i++) {
+ if (properties->aulPropTag[i] == PR_SOURCE_KEY) {
+ emsmdbp_source_key_from_fmid(data_pointers, emsmdbp_ctx, object->object.message->folderID,
+ &binr);
+ data_pointers[i] = binr;
+ retval = MAPI_E_SUCCESS;
+ } else {
+ retval = openchangedb_message_get_property(data_pointers, object->backend_object, properties->aulPropTag[i], data_pointers + i);
+ }
+ retvals[i] = retval;
+ }
+
+ return MAPI_E_SUCCESS;
+}
+
static int emsmdbp_object_get_properties_mapistore_root(TALLOC_CTX *mem_ctx, struct emsmdbp_context *emsmdbp_ctx, struct emsmdbp_object *object, struct SPropTagArray *properties, void **data_pointers, enum MAPISTATUS *retvals)
{
enum MAPISTATUS retval = MAPI_E_SUCCESS;
case EMSMDBP_OBJECT_FOLDER:
retval = emsmdbp_object_get_properties_systemspecialfolder(mem_ctx, emsmdbp_ctx, object, properties, data_pointers, retvals);
break;
+ case EMSMDBP_OBJECT_MESSAGE:
+ retval = emsmdbp_object_get_properties_message(mem_ctx, emsmdbp_ctx, object, properties, data_pointers, retvals);
+ break;
default:
retval = MAPISTORE_ERROR;
break;
if (emsmdbp_is_mapistore(table_object)) {
mapistore_table_set_columns(emsmdbp_ctx->mstore_ctx, emsmdbp_get_contextID(table_object), table_object->backend_object, properties->cValues, properties->aulPropTag);
mapistore_table_get_row_count(emsmdbp_ctx->mstore_ctx, emsmdbp_get_contextID(table_object), table_object->backend_object, MAPISTORE_PREFILTERED_QUERY, &table_object->object.table->denominator);
+ } else {
+ /* FIXME: openchangedb case */
+ /* set columns */
+ /* get row count */
+ table_object->object.table->denominator = 0;
}
for (i = 0; i < table_object->object.table->denominator; i++) {
/* source key */
eid = *(uint64_t *) data_pointers[sync_data->prop_index.eid];
+
if (eid == 0x7fffffffffffffffLL) {
DEBUG(0, ("message without a valid eid\n"));
talloc_free(header_data_pointers);
DEBUG(5, ("[%s] object: %p, backend_object: %p\n", __FUNCTION__, object, object->backend_object));
mapistore_table_set_columns(emsmdbp_ctx->mstore_ctx, emsmdbp_get_contextID(object),
object->backend_object, request.prop_count, request.properties);
- }
+ } else {
+ /* openchangedb case */
+ DEBUG(5, ("[%s] object: Setting Columns on openchangedb table\n"));
+ }
}
}
end:
mapi_repl->u.mapi_SortTable.TableStatus = status;
} else {
/* Parent folder doesn't have any mapistore context associated */
- DEBUG(0, ("non-mapistore SortTable not implemented yet\n"));
- goto end;
+ status = TBLSTAT_COMPLETE;
+ mapi_repl->u.mapi_SortTable.TableStatus = status;
+ retval = openchangedb_table_set_sort_order(object->backend_object, &request.lpSortCriteria);
+ if (retval) {
+ mapi_repl->error_code = retval;
+ goto end;
+ }
}
end:
break;
case false:
+ DEBUG(0, ("FindRow for openchangedb\n"));
+ /* Restrict rows to be fetched */
+ retval = openchangedb_table_set_restrictions(object->backend_object, &request.res);
+ /* Then fetch rows */
+ /* Lookup the properties and check if we need to flag the PropertyRow blob */
+ while (!found && table->numerator < table->denominator) {
+ flagged = 0;
+
+ data_pointers = emsmdbp_object_table_get_row_props(NULL, emsmdbp_ctx, object, table->numerator, &retvals);
+ if (data_pointers) {
+ found = true;
+ for (i = 0; i < table->prop_count; i++) {
+ if (retvals[i] != MAPI_E_SUCCESS) {
+ flagged = 1;
+ }
+ }
+
+ if (flagged) {
+ libmapiserver_push_property(mem_ctx,
+ 0x0000000b, (const void *)&flagged,
+ &row, 0, 0, 0);
+ }
+ else {
+ libmapiserver_push_property(mem_ctx,
+ 0x00000000, (const void *)&flagged,
+ &row, 0, 1, 0);
+ }
+
+ /* Push the properties */
+ for (i = 0; i < table->prop_count; i++) {
+ property = table->properties[i];
+ retval = retvals[i];
+ if (retval == MAPI_E_NOT_FOUND) {
+ property = (property & 0xFFFF0000) + PT_ERROR;
+ data = &retval;
+ }
+ else {
+ data = data_pointers[i];
+ }
+
+ libmapiserver_push_property(mem_ctx,
+ property, data, &row,
+ flagged?PT_ERROR:0, flagged, 0);
+ }
+ talloc_free(retvals);
+ talloc_free(data_pointers);
+ }
+ else {
+ table->numerator++;
+ }
+ }
+ /* Adjust parameters */
+ if (found) {
+ mapi_repl->u.mapi_FindRow.HasRowData = 1;
+ }
+ else {
+ mapi_repl->error_code = MAPI_E_NOT_FOUND;
+ }
+
+ mapi_repl->u.mapi_FindRow.row.length = row.length;
+ mapi_repl->u.mapi_FindRow.row.data = row.data;
break;
}