Add preliminary support for table and message in openchangedb.
authorJulien Kerihuel <j.kerihuel@openchange.org>
Tue, 25 Oct 2011 11:46:56 +0000 (11:46 +0000)
committerJulien Kerihuel <j.kerihuel@openchange.org>
Tue, 25 Oct 2011 11:46:56 +0000 (11:46 +0000)
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.

Makefile
mapiproxy/libmapiproxy/libmapiproxy.h
mapiproxy/libmapiproxy/openchangedb.c
mapiproxy/libmapiproxy/openchangedb_message.c [new file with mode: 0644]
mapiproxy/libmapiproxy/openchangedb_table.c [new file with mode: 0644]
mapiproxy/servers/default/emsmdb/emsmdbp_object.c
mapiproxy/servers/default/emsmdb/oxcfxics.c
mapiproxy/servers/default/emsmdb/oxctabl.c

index d4e4fbba04dc5441f5fd5e87b5dd3d684cfb8467..cb8e4992f65e23b95e9731f7a15d7ed2562d6af4 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -764,6 +764,8 @@ mapiproxy/libmapiproxy.$(SHLIBEXT).$(PACKAGE_VERSION):      mapiproxy/libmapiproxy/dc
                                                        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                       \
index 182b9b42b98144871473ec6d188bb0c892cb764b..9b2277813d20328d58371d157e097d56ee035a17 100644 (file)
@@ -127,6 +127,20 @@ struct mapi_handles_context {
        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"
@@ -216,6 +230,7 @@ enum MAPISTATUS openchangedb_lookup_folder_property(void *, uint32_t, uint64_t);
 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);
@@ -225,6 +240,18 @@ enum MAPISTATUS openchangedb_create_folder(void *, uint64_t, uint64_t, const cha
 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);
index 89593dac9c77c848d49f621593d5de7da57624b5..b024cc91752ac87bb9f5d4eff22ad740ce61de8a 100644 (file)
@@ -726,12 +726,12 @@ _PUBLIC_ enum MAPISTATUS openchangedb_lookup_folder_property(void *ldb_ctx,
 
    \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;
 
@@ -803,11 +803,11 @@ static struct BinaryArray_r *decode_mv_binary(TALLOC_CTX *mem_ctx, const char *s
 
    \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;
@@ -1102,11 +1102,11 @@ _PUBLIC_ enum MAPISTATUS openchangedb_get_folder_property(TALLOC_CTX *parent_ctx
        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);
@@ -1244,11 +1244,11 @@ _PUBLIC_ enum MAPISTATUS openchangedb_get_table_property(TALLOC_CTX *parent_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);
@@ -1320,6 +1320,7 @@ _PUBLIC_ enum MAPISTATUS openchangedb_set_ReceiveFolder(TALLOC_CTX *parent_ctx,
                                                        uint64_t fid)
 {
        TALLOC_CTX                      *mem_ctx;
+       enum MAPISTATUS                 retval;
        struct ldb_result               *res = NULL;
        struct ldb_dn                   *dn;
        char                            *dnstr;
@@ -1359,7 +1360,6 @@ _PUBLIC_ enum MAPISTATUS openchangedb_set_ReceiveFolder(TALLOC_CTX *parent_ctx,
        /* 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;
 
@@ -1386,7 +1386,6 @@ _PUBLIC_ enum MAPISTATUS openchangedb_set_ReceiveFolder(TALLOC_CTX *parent_ctx,
        
        /* Step 4. Create the new entry if applicable */
        if (fid != 0x0) {
-               enum MAPISTATUS         retval;
                char                    *distinguishedName;
                struct ldb_message      *msg;
 
@@ -1641,6 +1640,45 @@ _PUBLIC_ enum MAPISTATUS openchangedb_set_message_properties(TALLOC_CTX *mem_ctx
 }
 
 
+/**
+   \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.
diff --git a/mapiproxy/libmapiproxy/openchangedb_message.c b/mapiproxy/libmapiproxy/openchangedb_message.c
new file mode 100644 (file)
index 0000000..c87e22e
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+   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;
+}
diff --git a/mapiproxy/libmapiproxy/openchangedb_table.c b/mapiproxy/libmapiproxy/openchangedb_table.c
new file mode 100644 (file)
index 0000000..ce3222d
--- /dev/null
@@ -0,0 +1,274 @@
+/*
+   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;
+}
index c34e3b5ab99d710bae471925d54220d7ae615ac4..31a0c77278129b2b94f793a50216e27d0f800660 100644 (file)
@@ -701,15 +701,19 @@ int emsmdbp_folder_get_folder_count(struct emsmdbp_context *emsmdbp_ctx, struct
                        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;
 
@@ -749,11 +753,53 @@ _PUBLIC_ struct emsmdbp_object *emsmdbp_folder_open_table(TALLOC_CTX *mem_ctx, s
                }
                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);
                        }
                }
        }
@@ -922,8 +968,7 @@ _PUBLIC_ void **emsmdbp_object_table_get_row_props(TALLOC_CTX *mem_ctx, struct e
                        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;
                }
@@ -939,9 +984,27 @@ _PUBLIC_ void **emsmdbp_object_table_get_row_props(TALLOC_CTX *mem_ctx, struct e
 
                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);
@@ -990,10 +1053,14 @@ _PUBLIC_ void **emsmdbp_object_table_get_row_props(TALLOC_CTX *mem_ctx, struct e
                                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) {
@@ -1125,7 +1192,13 @@ _PUBLIC_ struct emsmdbp_object *emsmdbp_object_message_open(TALLOC_CTX *mem_ctx,
        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 */
@@ -1372,6 +1445,30 @@ static int emsmdbp_object_get_properties_systemspecialfolder(TALLOC_CTX *mem_ctx
        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;
@@ -1584,6 +1681,9 @@ _PUBLIC_ void **emsmdbp_object_get_properties(TALLOC_CTX *mem_ctx, struct emsmdb
                        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;
index a32bc5793d1243d980f22cda830ecebcc8147d2c..3396f33a9e5c6211b26d12597aeeb9cdddd7f808 100644 (file)
@@ -608,6 +608,11 @@ static void oxcfxics_push_messageChange(TALLOC_CTX *mem_ctx, struct emsmdbp_cont
        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++) {
@@ -626,6 +631,7 @@ static void oxcfxics_push_messageChange(TALLOC_CTX *mem_ctx, struct emsmdbp_cont
 
                        /* 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);
index 355bf0b56587d2f708ab1bade51a6df0f6f79fee..88ce85c954f65c2d6afdce8254db0c7d39f16a7e 100644 (file)
@@ -108,7 +108,10 @@ _PUBLIC_ enum MAPISTATUS EcDoRpc_RopSetColumns(TALLOC_CTX *mem_ctx,
                                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:
@@ -219,8 +222,13 @@ _PUBLIC_ enum MAPISTATUS EcDoRpc_RopSortTable(TALLOC_CTX *mem_ctx,
                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:
@@ -817,6 +825,67 @@ _PUBLIC_ enum MAPISTATUS EcDoRpc_RopFindRow(TALLOC_CTX *mem_ctx,
 
                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;
        }