~ubuntu-branches/debian/sid/openchange/sid

« back to all changes in this revision

Viewing changes to mapiproxy/libmapiproxy/openchangedb.c

  • Committer: Package Import Robot
  • Author(s): Jelmer Vernooij
  • Date: 2012-04-12 20:07:57 UTC
  • mfrom: (11 sid)
  • mto: This revision was merged to the branch mainline in revision 12.
  • Revision ID: package-import@ubuntu.com-20120412200757-k933d9trljmxj1l4
Tags: 1:1.0-4
* openchangeserver: Add dependency on openchangeproxy.
* Rebuild against newer version of Samba 4.
* Use dpkg-buildflags.
* Migrate to Git, update Vcs-Git header.
* Switch to debhelper 9.

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
   \brief OpenChange Dispatcher database routines
26
26
 */
27
27
 
28
 
#define __STDC_FORMAT_MACROS    1
29
28
#include <inttypes.h>
30
29
 
31
30
#include "mapiproxy/dcesrv_mapiproxy.h"
33
32
#include "libmapi/libmapi.h"
34
33
#include "libmapi/libmapi_private.h"
35
34
 
 
35
extern struct ldb_val ldb_binary_decode(TALLOC_CTX *, const char *);
 
36
 
36
37
/**
37
38
   \details Retrieve the mailbox FolderID for given recipient from
38
39
   openchange dispatcher database
39
40
 
40
 
   \param _ldb_ctx pointer to the OpenChange LDB context
 
41
   \param ldb_ctx pointer to the OpenChange LDB context
41
42
   \param recipient the mailbox username
42
43
   \param SystemIdx the system folder index
43
44
   \param FolderId pointer to the folder identifier the function returns
44
45
 
45
46
   \return MAPI_E_SUCCESS on success, otherwise MAPI error
46
47
 */
47
 
_PUBLIC_ enum MAPISTATUS openchangedb_get_SystemFolderID(void *_ldb_ctx,
48
 
                                                         char *recipient, uint32_t SystemIdx,
 
48
_PUBLIC_ enum MAPISTATUS openchangedb_get_SystemFolderID(struct ldb_context *ldb_ctx,
 
49
                                                         const char *recipient, uint32_t SystemIdx,
49
50
                                                         uint64_t *FolderId)
50
51
{
51
52
        TALLOC_CTX                      *mem_ctx;
52
 
        struct ldb_context              *ldb_ctx = (struct ldb_context *)_ldb_ctx;
53
53
        struct ldb_result               *res = NULL;
54
54
        const char * const              attrs[] = { "*", NULL };
55
55
        int                             ret;
71
71
 
72
72
        /* Step 2. If Mailbox root folder, check for FolderID within current record */
73
73
        if (SystemIdx == 0x1) {
74
 
                *FolderId = ldb_msg_find_attr_as_int64(res->msgs[0], "PidTagFolderId", 0);
 
74
                *FolderId = ldb_msg_find_attr_as_uint64(res->msgs[0], "PidTagFolderId", 0);
75
75
                OPENCHANGE_RETVAL_IF(!*FolderId, MAPI_E_CORRUPT_STORE, mem_ctx);
76
76
 
77
77
                talloc_free(mem_ctx);
84
84
        /* Step 3. Search FolderID */
85
85
        ldb_dn = ldb_dn_new(mem_ctx, ldb_ctx, dn);
86
86
        OPENCHANGE_RETVAL_IF(!ldb_dn, MAPI_E_CORRUPT_STORE, mem_ctx);
87
 
        talloc_free(res);
88
87
 
89
88
        ret = ldb_search(ldb_ctx, mem_ctx, &res, ldb_dn, LDB_SCOPE_SUBTREE, attrs, 
90
89
                         "(&(objectClass=systemfolder)(SystemIdx=%d))", SystemIdx);
91
90
 
92
91
        OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS || !res->count, MAPI_E_NOT_FOUND, mem_ctx);
93
92
 
94
 
        *FolderId = ldb_msg_find_attr_as_int64(res->msgs[0], "PidTagFolderId", 0);
 
93
        *FolderId = ldb_msg_find_attr_as_uint64(res->msgs[0], "PidTagFolderId", 0);
95
94
        OPENCHANGE_RETVAL_IF(!*FolderId, MAPI_E_CORRUPT_STORE, mem_ctx);
96
95
 
97
96
        talloc_free(mem_ctx);
102
101
/**
103
102
   \details Retrieve the public folder FolderID (fid) for a given folder type
104
103
 
105
 
   \param _ldb_ctx pointer to the OpenChange LDB context
 
104
   \param ldb_ctx pointer to the OpenChange LDB context
106
105
   \param SystemIdx the system folder index
107
106
   \param FolderId pointer to the folder identifier the function returns
108
107
 
109
108
   \return MAPI_E_SUCCESS on success, otherwise MAPI error
110
109
 */
111
 
_PUBLIC_ enum MAPISTATUS openchangedb_get_PublicFolderID(void *_ldb_ctx,
 
110
_PUBLIC_ enum MAPISTATUS openchangedb_get_PublicFolderID(struct ldb_context *ldb_ctx,
112
111
                                                         uint32_t SystemIdx,
113
112
                                                         uint64_t *FolderId)
114
113
{
115
114
        TALLOC_CTX                      *mem_ctx;
116
 
        struct ldb_context              *ldb_ctx = (struct ldb_context *)_ldb_ctx;
117
115
        struct ldb_result               *res = NULL;
118
116
        const char * const              attrs[] = { "*", NULL };
119
117
        int                             ret;
131
129
        OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS, MAPI_E_NOT_FOUND, mem_ctx);
132
130
        OPENCHANGE_RETVAL_IF(res->count != 1, MAPI_E_NOT_FOUND, mem_ctx);
133
131
 
134
 
        *FolderId = ldb_msg_find_attr_as_int64(res->msgs[0], "PidTagFolderId", 0);
 
132
        *FolderId = ldb_msg_find_attr_as_uint64(res->msgs[0], "PidTagFolderId", 0);
135
133
        OPENCHANGE_RETVAL_IF(!*FolderId, MAPI_E_CORRUPT_STORE, mem_ctx);
136
134
 
137
135
        talloc_free(mem_ctx);
144
142
   system folder.
145
143
 
146
144
   \param parent_ctx pointer to the parent memory context
147
 
   \param _ldb_ctx pointer to the openchange LDB context
 
145
   \param ldb_ctx pointer to the openchange LDB context
148
146
   \param fid the Folder identifier to search for
149
147
   \param distinguishedName pointer on pointer to the
150
148
   distinguishedName string the function returns
152
150
   \return MAPI_E_SUCCESS on success, otherwise MAPI_E_NOT_FOUND
153
151
 */
154
152
_PUBLIC_ enum MAPISTATUS openchangedb_get_distinguishedName(TALLOC_CTX *parent_ctx, 
155
 
                                                            void *_ldb_ctx, 
 
153
                                                            struct ldb_context *ldb_ctx, 
156
154
                                                            uint64_t fid, 
157
155
                                                            char **distinguishedName)
158
156
{
159
157
        TALLOC_CTX              *mem_ctx;
160
 
        struct ldb_context      *ldb_ctx = (struct ldb_context *)_ldb_ctx;
161
158
        struct ldb_result       *res = NULL;
162
159
        const char * const      attrs[] = { "*", NULL };
163
160
        int                     ret;
165
162
        mem_ctx = talloc_named(NULL, 0, "get_distinguishedName");
166
163
 
167
164
        ret = ldb_search(ldb_ctx, mem_ctx, &res, ldb_get_default_basedn(ldb_ctx),
168
 
                         LDB_SCOPE_SUBTREE, attrs, "(PidTagFolderId=0x%.16"PRIx64")", fid);
 
165
                         LDB_SCOPE_SUBTREE, attrs, "(PidTagFolderId=%"PRIu64")", fid);
169
166
 
170
167
        OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS || !res->count, MAPI_E_NOT_FOUND, mem_ctx);
171
168
 
178
175
 
179
176
 
180
177
/**
 
178
   \details Retrieve the mailboxDN associated to a mailbox system
 
179
   folder.
 
180
 
 
181
   \param parent_ctx pointer to the parent memory context
 
182
   \param ldb_ctx pointer to the openchange LDB context
 
183
   \param fid the folder identifier to search for
 
184
   \param mailboxDN pointer on pointer to the mailboxDN string the
 
185
   function returns
 
186
 
 
187
   \return MAPI_E_SUCCESS on success, otherwise MAPI_E_NOT_FOUND
 
188
 */
 
189
_PUBLIC_ enum MAPISTATUS openchangedb_get_mailboxDN(TALLOC_CTX *parent_ctx, 
 
190
                                                    struct ldb_context *ldb_ctx, 
 
191
                                                    uint64_t fid, 
 
192
                                                    char **mailboxDN)
 
193
{
 
194
        TALLOC_CTX              *mem_ctx;
 
195
        struct ldb_result       *res = NULL;
 
196
        const char * const      attrs[] = { "*", NULL };
 
197
        int                     ret;
 
198
 
 
199
        mem_ctx = talloc_named(NULL, 0, "get_mailboxDN");
 
200
 
 
201
        ret = ldb_search(ldb_ctx, mem_ctx, &res, ldb_get_default_basedn(ldb_ctx),
 
202
                         LDB_SCOPE_SUBTREE, attrs, "(PidTagFolderId=%"PRIu64")", fid);
 
203
 
 
204
        OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS || !res->count, MAPI_E_NOT_FOUND, mem_ctx);
 
205
 
 
206
        *mailboxDN = talloc_strdup(parent_ctx, ldb_msg_find_attr_as_string(res->msgs[0], "mailboxDN", NULL));
 
207
 
 
208
        talloc_free(mem_ctx);
 
209
 
 
210
        return MAPI_E_SUCCESS;
 
211
}
 
212
 
 
213
 
 
214
/**
181
215
   \details Retrieve the mailbox GUID for given recipient from
182
216
   openchange dispatcher database
183
217
 
184
 
   \param _ldb_ctx pointer to the OpenChange LDB context
 
218
   \param ldb_ctx pointer to the OpenChange LDB context
185
219
   \param recipient the mailbox username
186
220
   \param MailboxGUID pointer to the mailbox GUID the function returns
187
221
 
188
222
   \return MAPI_E_SUCCESS on success, otherwise MAPI error
189
223
 */
190
 
_PUBLIC_ enum MAPISTATUS openchangedb_get_MailboxGuid(void *_ldb_ctx,
191
 
                                                      char *recipient,
 
224
_PUBLIC_ enum MAPISTATUS openchangedb_get_MailboxGuid(struct ldb_context *ldb_ctx,
 
225
                                                      const char *recipient,
192
226
                                                      struct GUID *MailboxGUID)
193
227
{
194
228
        TALLOC_CTX                      *mem_ctx;
195
 
        struct ldb_context              *ldb_ctx = (struct ldb_context *)_ldb_ctx;
196
229
        struct ldb_result               *res = NULL;
197
230
        const char                      *guid;
198
231
        const char * const              attrs[] = { "*", NULL };
226
259
   \details Retrieve the mailbox replica identifier and GUID for given
227
260
   recipient from openchange dispatcher database
228
261
 
229
 
   \param _ldb_ctx pointer to the OpenChange LDB context
 
262
   \param ldb_ctx pointer to the OpenChange LDB context
230
263
   \param recipient the mailbox username
231
264
   \param ReplID pointer to the replica identifier the function returns
232
265
   \param ReplGUID pointer to the replica GUID the function returns
233
266
 
234
267
   \return MAPI_E_SUCCESS on success, otherwise MAPI error
235
268
 */
236
 
_PUBLIC_ enum MAPISTATUS openchangedb_get_MailboxReplica(void *_ldb_ctx,
237
 
                                                         char *recipient, uint16_t *ReplID,
 
269
_PUBLIC_ enum MAPISTATUS openchangedb_get_MailboxReplica(struct ldb_context *ldb_ctx,
 
270
                                                         const char *recipient, uint16_t *ReplID,
238
271
                                                         struct GUID *ReplGUID)
239
272
{
240
273
        TALLOC_CTX                      *mem_ctx;
241
 
        struct ldb_context              *ldb_ctx = (struct ldb_context *)_ldb_ctx;
242
274
        struct ldb_result               *res = NULL;
243
275
        const char                      *guid;
244
276
        const char * const              attrs[] = { "*", NULL };
247
279
        /* Sanity checks */
248
280
        OPENCHANGE_RETVAL_IF(!ldb_ctx, MAPI_E_NOT_INITIALIZED, NULL);
249
281
        OPENCHANGE_RETVAL_IF(!recipient, MAPI_E_INVALID_PARAMETER, NULL);
250
 
        OPENCHANGE_RETVAL_IF(!ReplID, MAPI_E_INVALID_PARAMETER, NULL);
251
 
        OPENCHANGE_RETVAL_IF(!ReplGUID, MAPI_E_INVALID_PARAMETER, NULL);
252
282
 
253
283
        mem_ctx = talloc_named(NULL, 0, "get_MailboxReplica");
254
284
 
259
289
        OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS || !res->count, MAPI_E_NOT_FOUND, mem_ctx);
260
290
 
261
291
        /* Step 2. Retrieve ReplicaID attribute's value */
262
 
        *ReplID = ldb_msg_find_attr_as_int(res->msgs[0], "ReplicaID", 0);
 
292
        if (ReplID) {
 
293
                *ReplID = ldb_msg_find_attr_as_int(res->msgs[0], "ReplicaID", 0);
 
294
        }
263
295
 
264
296
        /* Step 3/ Retrieve ReplicaGUID attribute's value */
265
 
        guid = ldb_msg_find_attr_as_string(res->msgs[0], "ReplicaGUID", 0);
266
 
        OPENCHANGE_RETVAL_IF(!guid, MAPI_E_CORRUPT_STORE, mem_ctx);
267
 
 
268
 
        GUID_from_string(guid, ReplGUID);
 
297
        if (ReplGUID) {
 
298
                guid = ldb_msg_find_attr_as_string(res->msgs[0], "ReplicaGUID", 0);
 
299
                OPENCHANGE_RETVAL_IF(!guid, MAPI_E_CORRUPT_STORE, mem_ctx);
 
300
                GUID_from_string(guid, ReplGUID);
 
301
        }
269
302
 
270
303
        talloc_free(mem_ctx);
271
304
 
276
309
   \details Retrieve the public folder replica identifier and GUID
277
310
   from the openchange dispatcher database
278
311
 
279
 
   \param _ldb_ctx pointer to the OpenChange LDB context
 
312
   \param ldb_ctx pointer to the OpenChange LDB context
280
313
   \param ReplID pointer to the replica identifier the function returns
281
314
   \param ReplGUID pointer to the replica GUID the function returns
282
315
 
283
316
   \return MAPI_E_SUCCESS on success, otherwise MAPI error
284
317
 */
285
 
_PUBLIC_ enum MAPISTATUS openchangedb_get_PublicFolderReplica(void *_ldb_ctx,
 
318
_PUBLIC_ enum MAPISTATUS openchangedb_get_PublicFolderReplica(struct ldb_context *ldb_ctx,
286
319
                                                              uint16_t *ReplID,
287
320
                                                              struct GUID *ReplGUID)
288
321
{
289
322
        TALLOC_CTX                      *mem_ctx;
290
 
        struct ldb_context              *ldb_ctx = (struct ldb_context *)_ldb_ctx;
291
323
        struct ldb_result               *res = NULL;
292
324
        const char                      *guid;
293
325
        const char * const              attrs[] = { "*", NULL };
295
327
 
296
328
        /* Sanity checks */
297
329
        OPENCHANGE_RETVAL_IF(!ldb_ctx, MAPI_E_NOT_INITIALIZED, NULL);
298
 
        OPENCHANGE_RETVAL_IF(!ReplID, MAPI_E_INVALID_PARAMETER, NULL);
299
 
        OPENCHANGE_RETVAL_IF(!ReplGUID, MAPI_E_INVALID_PARAMETER, NULL);
300
330
 
301
331
        mem_ctx = talloc_named(NULL, 0, "get_PublicFolderReplica");
302
332
 
307
337
        OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS || !res->count, MAPI_E_NOT_FOUND, mem_ctx);
308
338
 
309
339
        /* Step 2. Retrieve ReplicaID attribute's value */
310
 
        *ReplID = ldb_msg_find_attr_as_int(res->msgs[0], "ReplicaID", 0);
 
340
        if (ReplID != NULL) {
 
341
                *ReplID = ldb_msg_find_attr_as_int(res->msgs[0], "ReplicaID", 0);
 
342
        }
311
343
 
312
344
        /* Step 3. Retrieve ReplicaGUID attribute's value */
313
 
        guid = ldb_msg_find_attr_as_string(res->msgs[0], "StoreGUID", 0);
314
 
        OPENCHANGE_RETVAL_IF(!guid, MAPI_E_CORRUPT_STORE, mem_ctx);
315
 
 
316
 
        GUID_from_string(guid, ReplGUID);
 
345
        if (ReplGUID != NULL) {
 
346
                guid = ldb_msg_find_attr_as_string(res->msgs[0], "StoreGUID", 0);
 
347
                OPENCHANGE_RETVAL_IF(!guid, MAPI_E_CORRUPT_STORE, mem_ctx);
 
348
                GUID_from_string(guid, ReplGUID);
 
349
        }
317
350
 
318
351
        talloc_free(mem_ctx);
319
352
 
326
359
   folder.
327
360
 
328
361
   \param parent_ctx pointer to the memory context
329
 
   \param _ldb_ctx pointer to the openchange LDB context
 
362
   \param ldb_ctx pointer to the openchange LDB context
330
363
   \param fid the Folder identifier to search for
331
364
   \param mapistoreURL pointer on pointer to the mapistore URI the
332
365
   function returns
 
366
   \param owner pointer on pointer to the owner of the parent mailbox
333
367
   \param mailboxstore boolean value which defines whether the record
334
368
   has to be searched within Public folders hierarchy or not
335
369
 
336
370
   \return MAPI_E_SUCCESS on success, otherwise MAPI_E_NOT_FOUND
337
371
 */
338
372
_PUBLIC_ enum MAPISTATUS openchangedb_get_mapistoreURI(TALLOC_CTX *parent_ctx,
339
 
                                                       void *_ldb_ctx,
 
373
                                                       struct ldb_context *ldb_ctx,
340
374
                                                       uint64_t fid,
341
375
                                                       char **mapistoreURL,
342
376
                                                       bool mailboxstore)
343
377
{
344
378
        TALLOC_CTX              *mem_ctx;
345
 
        struct ldb_context      *ldb_ctx = (struct ldb_context *)_ldb_ctx;
346
379
        struct ldb_result       *res = NULL;
347
380
        const char * const      attrs[] = { "*", NULL };
348
381
        int                     ret;
351
384
 
352
385
        if (mailboxstore == true) {
353
386
                ret = ldb_search(ldb_ctx, mem_ctx, &res, ldb_get_default_basedn(ldb_ctx),
354
 
                                 LDB_SCOPE_SUBTREE, attrs, "(PidTagFolderId=0x%.16"PRIx64")", fid);
355
 
        } else {
356
 
                ret = ldb_search(ldb_ctx, mem_ctx, &res, ldb_get_root_basedn(ldb_ctx),
357
 
                                 LDB_SCOPE_SUBTREE, attrs, "(PidTagFolderId=0x%.16"PRIx64")", fid);
358
 
        }
359
 
 
360
 
        OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS || !res->count, MAPI_E_NOT_FOUND, mem_ctx);
361
 
 
362
 
        *mapistoreURL = talloc_strdup(parent_ctx, ldb_msg_find_attr_as_string(res->msgs[0], "mapistore_uri", NULL));
363
 
 
364
 
        talloc_free(mem_ctx);
365
 
 
366
 
        return MAPI_E_SUCCESS;
367
 
}
368
 
 
 
387
                                 LDB_SCOPE_SUBTREE, attrs, "(PidTagFolderId=%"PRIu64")", fid);
 
388
        } else {
 
389
                ret = ldb_search(ldb_ctx, mem_ctx, &res, ldb_get_root_basedn(ldb_ctx),
 
390
                                 LDB_SCOPE_SUBTREE, attrs, "(PidTagFolderId=%"PRIu64")", fid);
 
391
        }
 
392
 
 
393
        OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS || !res->count, MAPI_E_NOT_FOUND, mem_ctx);
 
394
 
 
395
        *mapistoreURL = talloc_strdup(parent_ctx, ldb_msg_find_attr_as_string(res->msgs[0], "MAPIStoreURI", NULL));
 
396
 
 
397
        talloc_free(mem_ctx);
 
398
 
 
399
        return MAPI_E_SUCCESS;
 
400
}
 
401
 
 
402
/**
 
403
   \details Retrieve the parent fid associated to a mailbox system
 
404
   folder.
 
405
 
 
406
   \param ldb_ctx pointer to the openchange LDB context
 
407
   \param fid the Folder identifier to search for
 
408
   \param parent_fidp pointer to the parent_fid the function returns
 
409
   \param mailboxstore boolean value which defines whether the record
 
410
   has to be searched within Public folders hierarchy or not
 
411
 
 
412
   \return MAPI_E_SUCCESS on success, otherwise MAPI_E_NOT_FOUND
 
413
 */
 
414
_PUBLIC_ enum MAPISTATUS openchangedb_get_parent_fid(struct ldb_context *ldb_ctx,
 
415
                                                     uint64_t fid,
 
416
                                                     uint64_t *parent_fidp,
 
417
                                                     bool mailboxstore)
 
418
{
 
419
        TALLOC_CTX              *mem_ctx;
 
420
        struct ldb_result       *res = NULL;
 
421
        const char * const      attrs[] = { "*", NULL };
 
422
        int                     ret;
 
423
 
 
424
        mem_ctx = talloc_named(NULL, 0, "get_parent_fid");
 
425
 
 
426
        if (mailboxstore == true) {
 
427
                ret = ldb_search(ldb_ctx, mem_ctx, &res, ldb_get_default_basedn(ldb_ctx),
 
428
                                 LDB_SCOPE_SUBTREE, attrs, "(PidTagFolderId=%"PRIu64")", fid);
 
429
        } else {
 
430
                ret = ldb_search(ldb_ctx, mem_ctx, &res, ldb_get_root_basedn(ldb_ctx),
 
431
                                 LDB_SCOPE_SUBTREE, attrs, "(PidTagFolderId=%"PRIu64")", fid);
 
432
        }
 
433
        OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS || !res->count, MAPI_E_NOT_FOUND, mem_ctx);
 
434
        *parent_fidp = ldb_msg_find_attr_as_uint64(res->msgs[0], "PidTagParentFolderId", 0x0);
 
435
 
 
436
        talloc_free(mem_ctx);
 
437
 
 
438
        return MAPI_E_SUCCESS;
 
439
}
 
440
 
 
441
/**
 
442
   \details Retrieve the fid associated with a mapistore URI.
 
443
 
 
444
   \param ldb_ctx pointer to the openchange LDB context
 
445
   \param fid the Folder identifier to search for
 
446
   \param mapistoreURL pointer on pointer to the mapistore URI the
 
447
   function returns
 
448
   \param mailboxstore boolean value which defines whether the record
 
449
   has to be searched within Public folders hierarchy or not
 
450
 
 
451
   \return MAPI_E_SUCCESS on success, otherwise MAPI_E_NOT_FOUND
 
452
 */
 
453
_PUBLIC_ enum MAPISTATUS openchangedb_get_fid(struct ldb_context *ldb_ctx, const char *mapistoreURL, uint64_t *fidp)
 
454
{
 
455
        TALLOC_CTX              *mem_ctx;
 
456
        struct ldb_result       *res = NULL;
 
457
        const char * const      attrs[] = { "*", NULL };
 
458
        char                    *slashLessURL;
 
459
        size_t                  len;
 
460
        int                     ret;
 
461
 
 
462
        mem_ctx = talloc_named(NULL, 0, "openchangedb_get_fid");
 
463
 
 
464
        ret = ldb_search(ldb_ctx, mem_ctx, &res, ldb_get_default_basedn(ldb_ctx),
 
465
                         LDB_SCOPE_SUBTREE, attrs, "(MAPIStoreURI=%s)", mapistoreURL);
 
466
        if (ret != LDB_SUCCESS || !res->count) {
 
467
                len = strlen(mapistoreURL);
 
468
                if (mapistoreURL[len-1] == '/') {
 
469
                        slashLessURL = talloc_strdup(mem_ctx, mapistoreURL);
 
470
                        slashLessURL[len-1] = 0;
 
471
                        ret = ldb_search(ldb_ctx, mem_ctx, &res, ldb_get_default_basedn(ldb_ctx), LDB_SCOPE_SUBTREE, attrs, "(MAPIStoreURI=%s)", slashLessURL);
 
472
                }
 
473
                OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS || !res->count, MAPI_E_NOT_FOUND, mem_ctx);
 
474
        }
 
475
        *fidp = ldb_msg_find_attr_as_uint64(res->msgs[0], "PidTagFolderId", 0x0);
 
476
 
 
477
        talloc_free(mem_ctx);
 
478
 
 
479
        return MAPI_E_SUCCESS;
 
480
}
 
481
 
 
482
/**
 
483
   \details Retrieve a list of mapistore URI in use for a certain user
 
484
 
 
485
   \param ldb_ctx pointer to the openchange LDB context
 
486
   \param fid the Folder identifier to search for
 
487
   \param mapistoreURL pointer on pointer to the mapistore URI the
 
488
   function returns
 
489
   \param mailboxstore boolean value which defines whether the record
 
490
   has to be searched within Public folders hierarchy or not
 
491
 
 
492
   \return MAPI_E_SUCCESS on success, otherwise MAPI_E_NOT_FOUND
 
493
 */
 
494
_PUBLIC_ enum MAPISTATUS openchangedb_get_MAPIStoreURIs(struct ldb_context *ldb_ctx, const char *username, TALLOC_CTX *mem_ctx, struct StringArrayW_r **urisP)
 
495
{
 
496
        TALLOC_CTX              *local_mem_ctx;
 
497
        struct ldb_result       *res = NULL;
 
498
        struct ldb_dn           *dn;
 
499
        const char * const      attrs[] = { "*", NULL };
 
500
        char                    *dnstr;
 
501
        int                     i, elements, ret;
 
502
        struct StringArrayW_r   *uris;
 
503
 
 
504
        local_mem_ctx = talloc_named(NULL, 0, "openchangedb_get_fid");
 
505
 
 
506
        /* fetch mailbox DN */
 
507
        ret = ldb_search(ldb_ctx, local_mem_ctx, &res, ldb_get_default_basedn(ldb_ctx),
 
508
                         LDB_SCOPE_SUBTREE, attrs, "(&(cn=%s)(MailboxGUID=*))", username);
 
509
        OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS || !res->count, MAPI_E_NOT_FOUND, local_mem_ctx);
 
510
 
 
511
        dnstr = talloc_strdup(local_mem_ctx, ldb_msg_find_attr_as_string(res->msgs[0], "distinguishedName", NULL));
 
512
        OPENCHANGE_RETVAL_IF(!dnstr, MAPI_E_NOT_FOUND, local_mem_ctx);
 
513
        dn = ldb_dn_new(local_mem_ctx, ldb_ctx, dnstr);
 
514
 
 
515
        uris = talloc_zero(mem_ctx, struct StringArrayW_r);
 
516
        uris->lppszW = talloc_zero(uris, const char *);
 
517
        *urisP = uris;
 
518
 
 
519
        elements = 0;
 
520
 
 
521
        /* search subfolders which have a non-null mapistore uri */
 
522
        ret = ldb_search(ldb_ctx, local_mem_ctx, &res, dn, LDB_SCOPE_SUBTREE, attrs, "(MAPIStoreURI=*)");
 
523
        if (ret == LDB_SUCCESS) {
 
524
                for (i = 0; i < res->count; i++) {
 
525
                        if ((uris->cValues + 1) > elements) {
 
526
                                elements = uris->cValues + 16;
 
527
                                uris->lppszW = talloc_realloc(uris, uris->lppszW, const char *, elements);
 
528
                        }
 
529
                        uris->lppszW[uris->cValues] = talloc_strdup(uris, ldb_msg_find_attr_as_string(res->msgs[i], "MAPIStoreURI", NULL));
 
530
                        uris->cValues++;
 
531
                }
 
532
        }
 
533
 
 
534
        talloc_free(local_mem_ctx);
 
535
 
 
536
        return MAPI_E_SUCCESS;
 
537
}
369
538
 
370
539
/**
371
540
   \details Retrieve the Explicit message class and Folder identifier
372
541
   associated to the MessageClass search pattern.
373
542
 
374
543
   \param parent_ctx pointer to the memory context
375
 
   \param _ldb_ctx pointer to the openchange LDB context
 
544
   \param ldb_ctx pointer to the openchange LDB context
376
545
   \param recipient pointer to the mailbox's username
377
546
   \param MessageClass substring to search for
378
547
   \param fid pointer to the folder identifier the function returns
382
551
   \return MAPI_E_SUCCESS on success, otherwise MAPI_E_NOT_FOUND
383
552
 */
384
553
_PUBLIC_ enum MAPISTATUS openchangedb_get_ReceiveFolder(TALLOC_CTX *parent_ctx,
385
 
                                                        void *_ldb_ctx,
 
554
                                                        struct ldb_context *ldb_ctx,
386
555
                                                        const char *recipient,
387
556
                                                        const char *MessageClass,
388
557
                                                        uint64_t *fid,
389
558
                                                        const char **ExplicitMessageClass)
390
559
{
391
560
        TALLOC_CTX                      *mem_ctx;
392
 
        struct ldb_context              *ldb_ctx = (struct ldb_context *)_ldb_ctx;
393
561
        struct ldb_result               *res = NULL;
394
562
        struct ldb_dn                   *dn;
395
563
        struct ldb_message_element      *ldb_element;
410
578
        OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS || !res->count, MAPI_E_NOT_FOUND, mem_ctx);
411
579
 
412
580
        dnstr = talloc_strdup(mem_ctx, ldb_msg_find_attr_as_string(res->msgs[0], "distinguishedName", NULL));
413
 
        DEBUG(5, ("openchangedb_get_ReceiveFolder, dnstr: %s\n", dnstr));
414
 
 
415
581
        OPENCHANGE_RETVAL_IF(!dnstr, MAPI_E_NOT_FOUND, mem_ctx);
416
582
 
417
583
        talloc_free(res);
425
591
        OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS || (res->count != 1), MAPI_E_NOT_FOUND, mem_ctx);
426
592
        *fid = ldb_msg_find_attr_as_uint64(res->msgs[0], "PidTagFolderId", 0x0);
427
593
        *ExplicitMessageClass = "";
428
 
        DEBUG(5, ("openchangedb_get_ReceiveFolder (All target), class: %s, fid: 0x%016"PRIx64"\n",
 
594
        DEBUG(5, ("openchangedb_get_ReceiveFolder (All target), class: %s, fid: %.16"PRIx64"\n",
429
595
                  *ExplicitMessageClass, *fid));
430
596
        if (strcmp(MessageClass, "All") == 0) {
431
597
                /* we're done here */
436
602
        /* Step 2B. Search for all MessageClasses within user's mailbox */
437
603
        ret = ldb_search(ldb_ctx, mem_ctx, &res, dn, LDB_SCOPE_SUBTREE, attrs, 
438
604
                         "(PidTagMessageClass=*)");
439
 
        DEBUG(5, ("openchangedb_get_ReceiveFolder, res->count: %i\n", res->count));
440
 
 
441
605
        OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS || !res->count, MAPI_E_NOT_FOUND, mem_ctx);
442
606
 
443
607
        /* Step 3. Find the message class that has the longest matching string entry */
444
608
        for (j = 0; j < res->count; ++j) {
445
609
                ldb_element = ldb_msg_find_element(res->msgs[j], "PidTagMessageClass");
446
 
                DEBUG(6, ("openchangedb_get_ReceiveFolder, checking fid: 0x%016"PRIx64"\n",
 
610
                DEBUG(6, ("openchangedb_get_ReceiveFolder, checking fid: %.16"PRIx64"\n",
447
611
                          ldb_msg_find_attr_as_uint64(res->msgs[j], "PidTagFolderId", 0x0)));
448
612
                for (i = 0, length = 0; i < ldb_element[j].num_values; i++) {
449
613
                        DEBUG(6, ("openchangedb_get_ReceiveFolder, element %i, data: %s\n", i, (char *)ldb_element->values[i].data));
466
630
                }
467
631
        }
468
632
        OPENCHANGE_RETVAL_IF(!*ExplicitMessageClass, MAPI_E_NOT_FOUND, mem_ctx);
469
 
        DEBUG(5, ("openchangedb_get_ReceiveFolder, fid: 0x%016"PRIx64"\n", *fid));
470
 
 
471
 
        talloc_free(mem_ctx);
472
 
 
473
 
        return MAPI_E_SUCCESS;
474
 
}
475
 
 
 
633
        DEBUG(5, ("openchangedb_get_ReceiveFolder, fid: %.16"PRIx64"\n", *fid));
 
634
 
 
635
        talloc_free(mem_ctx);
 
636
 
 
637
        return MAPI_E_SUCCESS;
 
638
}
 
639
 
 
640
 
 
641
/**
 
642
   \details Retrieve the Transport Folder FolderID for given recipient from openchange dispatcher database
 
643
 
 
644
   \param ldb_ctx pointer to the OpenChange LDB context
 
645
   \param recipient the mailbox username
 
646
   \param FolderId pointer to the folder identifier the function returns
 
647
 
 
648
   \return MAPI_E_SUCCESS on success, otherwise MAPI error
 
649
 */
 
650
_PUBLIC_ enum MAPISTATUS openchangedb_get_TransportFolder(struct ldb_context *ldb_ctx, const char *recipient, uint64_t *FolderId)
 
651
{
 
652
        TALLOC_CTX                      *mem_ctx;
 
653
        struct ldb_result               *res = NULL;
 
654
        const char * const              attrs[] = { "*", NULL };
 
655
        int                             ret;
 
656
        char                            *dnstr;
 
657
        struct ldb_dn                   *ldb_dn = NULL;
 
658
 
 
659
        /* Sanity checks */
 
660
        OPENCHANGE_RETVAL_IF(!ldb_ctx, MAPI_E_NOT_INITIALIZED, NULL);
 
661
        OPENCHANGE_RETVAL_IF(!recipient, MAPI_E_INVALID_PARAMETER, NULL);
 
662
        OPENCHANGE_RETVAL_IF(!FolderId, MAPI_E_INVALID_PARAMETER, NULL);
 
663
        
 
664
        mem_ctx = talloc_named(NULL, 0, "get_TransportFolder");
 
665
 
 
666
        /* Step 1. Find mailbox DN for the recipient */
 
667
        ret = ldb_search(ldb_ctx, mem_ctx, &res, ldb_get_default_basedn(ldb_ctx),
 
668
                         LDB_SCOPE_SUBTREE, attrs, "CN=%s", recipient);
 
669
        OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS || !res->count, MAPI_E_NOT_FOUND, mem_ctx);
 
670
 
 
671
        dnstr = talloc_strdup(mem_ctx, ldb_msg_find_attr_as_string(res->msgs[0], "distinguishedName", NULL));
 
672
        OPENCHANGE_RETVAL_IF(!dnstr, MAPI_E_NOT_FOUND, mem_ctx);
 
673
 
 
674
        talloc_free(res);
 
675
 
 
676
        /* Step 2. Find "Outbox" in user mailbox */
 
677
        ldb_dn = ldb_dn_new(mem_ctx, ldb_ctx, dnstr);
 
678
        talloc_free(dnstr);
 
679
 
 
680
        ret = ldb_search(ldb_ctx, mem_ctx, &res, ldb_dn, LDB_SCOPE_SUBTREE, attrs, "(PidTagDisplayName=%s)", "Outbox");
 
681
        OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS || !res->count, MAPI_E_NOT_FOUND, mem_ctx);
 
682
 
 
683
        /* Step 2. If Mailbox root folder, check for FolderID within current record */
 
684
        *FolderId = ldb_msg_find_attr_as_uint64(res->msgs[0], "PidTagFolderId", 0);
 
685
        OPENCHANGE_RETVAL_IF(!*FolderId, MAPI_E_CORRUPT_STORE, mem_ctx);
 
686
 
 
687
        talloc_free(mem_ctx);
 
688
 
 
689
        return MAPI_E_SUCCESS;
 
690
}
476
691
 
477
692
/**
478
693
   \details Retrieve the number of sub folders for a given fid
479
694
 
480
 
   \param _ldb_ctx pointer to the openchange LDB context
 
695
   \param ldb_ctx pointer to the openchange LDB context
481
696
   \param fid the folder identifier to use for the search
482
697
   \param RowCount pointer to the returned number of results
483
698
 
484
699
   \return MAPI_E_SUCCESS on success, otherwise MAPI_E_NOT_FOUND
485
700
 */
486
 
_PUBLIC_ enum MAPISTATUS openchangedb_get_folder_count(void *_ldb_ctx,
487
 
                                                       uint64_t fid,
488
 
                                                       uint32_t *RowCount)
 
701
_PUBLIC_ enum MAPISTATUS openchangedb_get_folder_count(struct ldb_context *ldb_ctx, uint64_t fid, uint32_t *RowCount)
489
702
{
490
703
        TALLOC_CTX              *mem_ctx;
491
 
        struct ldb_context      *ldb_ctx = (struct ldb_context *)_ldb_ctx;
492
704
        struct ldb_result       *res;
493
705
        const char * const      attrs[] = { "*", NULL };
494
706
        int                     ret;
495
707
 
 
708
        /* Sanity checks */
 
709
        OPENCHANGE_RETVAL_IF(!ldb_ctx, MAPI_E_NOT_INITIALIZED, NULL);
 
710
        OPENCHANGE_RETVAL_IF(!RowCount, MAPI_E_INVALID_PARAMETER, NULL);
 
711
 
496
712
        mem_ctx = talloc_named(NULL, 0, "get_folder_count");
497
713
        *RowCount = 0;
498
714
 
499
715
        ret = ldb_search(ldb_ctx, mem_ctx, &res, ldb_get_default_basedn(ldb_ctx),
500
716
                         LDB_SCOPE_SUBTREE, attrs, 
501
 
                         "(PidTagParentFolderId=0x%.16"PRIx64")(PidTagFolderId=*)", fid);
502
 
 
 
717
                         "(PidTagParentFolderId=%"PRIu64")(PidTagFolderId=*)", fid);
503
718
        OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS, MAPI_E_NOT_FOUND, mem_ctx);
504
719
 
505
720
        *RowCount = res->count;
514
729
   \details Check if a property exists within an openchange dispatcher
515
730
   database record
516
731
 
517
 
   \param _ldb_ctx pointer to the openchange LDB context
 
732
   \param ldb_ctx pointer to the openchange LDB context
518
733
   \param proptag the MAPI property tag to lookup
519
734
   \param fid the record folder identifier
520
735
 
521
736
   \return MAPI_E_SUCCESS on success, otherwise MAPI_E_NOT_FOUND
522
737
 */
523
 
_PUBLIC_ enum MAPISTATUS openchangedb_lookup_folder_property(void *_ldb_ctx, 
 
738
_PUBLIC_ enum MAPISTATUS openchangedb_lookup_folder_property(struct ldb_context *ldb_ctx, 
524
739
                                                             uint32_t proptag, 
525
740
                                                             uint64_t fid)
526
741
{
527
742
        TALLOC_CTX              *mem_ctx;
528
 
        struct ldb_context      *ldb_ctx = (struct ldb_context *)_ldb_ctx;
529
743
        struct ldb_result       *res = NULL;
530
744
        const char * const      attrs[] = { "*", NULL };
531
745
        const char              *PidTagAttr = NULL;
535
749
 
536
750
        /* Step 1. Find PidTagFolderId record */
537
751
        ret = ldb_search(ldb_ctx, mem_ctx, &res, ldb_get_default_basedn(ldb_ctx),
538
 
                         LDB_SCOPE_SUBTREE, attrs, "(PidTagFolderId=0x%.16"PRIx64")", fid);
 
752
                         LDB_SCOPE_SUBTREE, attrs, "(PidTagFolderId=%"PRIu64")", fid);
539
753
        OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS || !res->count, MAPI_E_NOT_FOUND, mem_ctx);
540
754
 
541
755
        /* Step 2. Convert proptag into PidTag attribute */
552
766
 
553
767
 
554
768
/**
555
 
   \details Retrieve a special MAPI property from a folder record
 
769
   \details Retrieve a special MAPI property from an openchangedb record
556
770
 
557
771
   \param mem_ctx pointer to the memory context
558
772
   \param ldb_ctx pointer to the OpenChange LDB context
559
 
   \param recipient the mailbox username
560
773
   \param res pointer to the LDB result
561
774
   \param proptag the MAPI property tag to lookup
562
775
   \param PidTagAttr the mapped MAPI property name
563
776
 
564
777
   \return pointer to valid data on success, otherwise NULL
565
778
 */
566
 
static void *openchangedb_get_folder_special_property(TALLOC_CTX *mem_ctx,
567
 
                                                      void *ldb_ctx,
568
 
                                                      char *recipient,
569
 
                                                      struct ldb_result *res,
570
 
                                                      uint32_t proptag,
571
 
                                                      const char *PidTagAttr)
 
779
void *openchangedb_get_special_property(TALLOC_CTX *mem_ctx,
 
780
                                        struct ldb_context *ldb_ctx,
 
781
                                        struct ldb_result *res,
 
782
                                        uint32_t proptag,
 
783
                                        const char *PidTagAttr)
572
784
{
573
 
        enum MAPISTATUS         retval;
574
 
        struct GUID             MailboxGUID;
575
 
        struct GUID             ReplGUID;
576
 
        uint16_t                ReplID;
577
 
        struct Binary_r         *bin;
578
 
        uint16_t                FolderType;
579
 
        uint64_t                FolderId;
580
 
        const char              *tmp;
581
785
        uint32_t                *l;
582
786
 
583
787
        switch (proptag) {
584
 
        case PR_IPM_APPOINTMENT_ENTRYID:
585
 
        case PR_IPM_CONTACT_ENTRYID:
586
 
        case PR_IPM_JOURNAL_ENTRYID:
587
 
        case PR_IPM_NOTE_ENTRYID:
588
 
        case PR_IPM_TASK_ENTRYID:
589
 
        case PR_REMINDERS_ONLINE_ENTRYID:
590
 
        case PR_IPM_DRAFTS_ENTRYID:
591
 
                retval = openchangedb_get_MailboxGuid(ldb_ctx, recipient, &MailboxGUID);
592
 
                retval = openchangedb_get_MailboxReplica(ldb_ctx, recipient, &ReplID, &ReplGUID);
593
 
                FolderType = (uint16_t) ldb_msg_find_attr_as_int(res->msgs[0], "FolderType", 0x1);
594
 
 
595
 
                tmp = ldb_msg_find_attr_as_string(res->msgs[0], PidTagAttr, NULL);
596
 
                FolderId = strtoul(tmp, NULL, 16);
597
 
                retval = entryid_set_folder_EntryID(mem_ctx, &MailboxGUID, &ReplGUID, FolderType, FolderId, &bin);
598
 
                return (void *)bin;
599
 
                break;
600
788
        case PR_DEPTH:
601
789
                l = talloc_zero(mem_ctx, uint32_t);
602
790
                *l = 0;
606
794
        return NULL;
607
795
}
608
796
 
 
797
static struct BinaryArray_r *decode_mv_binary(TALLOC_CTX *mem_ctx, const char *str)
 
798
{
 
799
        const char *start;
 
800
        char *tmp;
 
801
        size_t i, current, len;
 
802
        uint32_t j;
 
803
        struct BinaryArray_r *bin_array;
 
804
 
 
805
        bin_array = talloc_zero(mem_ctx, struct BinaryArray_r);
 
806
 
 
807
        start = str;
 
808
        len = strlen(str);
 
809
        i = 0;
 
810
        while (i < len && start[i] != ';') {
 
811
                i++;
 
812
        }
 
813
        if (i < len) {
 
814
                tmp = talloc_memdup(NULL, start, i + 1);
 
815
                tmp[i] = 0;
 
816
                bin_array->cValues = strtol(tmp, NULL, 16);
 
817
                bin_array->lpbin = talloc_array(bin_array, struct Binary_r, bin_array->cValues);
 
818
                talloc_free(tmp);
 
819
 
 
820
                i++;
 
821
                for (j = 0; j < bin_array->cValues; j++) {
 
822
                        current = i;
 
823
                        while (i < len && start[i] != ';') {
 
824
                                i++;
 
825
                        }
 
826
 
 
827
                        tmp = talloc_memdup(bin_array, start + current, i - current + 1);
 
828
                        tmp[i - current] = 0;
 
829
                        i++;
 
830
 
 
831
                        bin_array->lpbin[j].lpb = (uint8_t *) tmp;
 
832
                        if (*tmp) {
 
833
                                bin_array->lpbin[j].cb = ldb_base64_decode((char *) bin_array->lpbin[j].lpb);
 
834
                        }
 
835
                        else {
 
836
                                bin_array->lpbin[j].cb = 0;
 
837
                        }
 
838
                }
 
839
        }
 
840
 
 
841
        return bin_array;
 
842
}
 
843
 
 
844
static struct LongArray_r *decode_mv_long(TALLOC_CTX *mem_ctx, const char *str)
 
845
{
 
846
        const char *start;
 
847
        char *tmp;
 
848
        size_t i, current, len;
 
849
        uint32_t j;
 
850
        struct LongArray_r *long_array;
 
851
 
 
852
        long_array = talloc_zero(mem_ctx, struct LongArray_r);
 
853
 
 
854
        start = str;
 
855
        len = strlen(str);
 
856
        i = 0;
 
857
        while (i < len && start[i] != ';') {
 
858
                i++;
 
859
        }
 
860
        if (i < len) {
 
861
                tmp = talloc_memdup(NULL, start, i + 1);
 
862
                tmp[i] = 0;
 
863
                long_array->cValues = strtol(tmp, NULL, 16);
 
864
                long_array->lpl = talloc_array(long_array, uint32_t, long_array->cValues);
 
865
                talloc_free(tmp);
 
866
 
 
867
                i++;
 
868
                for (j = 0; j < long_array->cValues; j++) {
 
869
                        current = i;
 
870
                        while (i < len && start[i] != ';') {
 
871
                                i++;
 
872
                        }
 
873
 
 
874
                        tmp = talloc_memdup(long_array, start + current, i - current + 1);
 
875
                        tmp[i - current] = 0;
 
876
                        i++;
 
877
 
 
878
                        long_array->lpl[j] = strtol(tmp, NULL, 16);
 
879
                        talloc_free(tmp);
 
880
                }
 
881
        }
 
882
 
 
883
        return long_array;
 
884
}
609
885
 
610
886
/**
611
 
   \details Retrieve a MAPI property from a OpenChange LDB message
 
887
   \details Retrieve a MAPI property from a OpenChange LDB result set
612
888
 
613
889
   \param mem_ctx pointer to the memory context
614
890
   \param res pointer to the LDB results
618
894
 
619
895
   \return valid data pointer on success, otherwise NULL
620
896
 */
621
 
static void *openchangedb_get_folder_property_data(TALLOC_CTX *mem_ctx,
622
 
                                                   struct ldb_result *res,
623
 
                                                   uint32_t pos,
624
 
                                                   uint32_t proptag,
625
 
                                                   const char *PidTagAttr)
 
897
void *openchangedb_get_property_data(TALLOC_CTX *mem_ctx,
 
898
                                     struct ldb_result *res,
 
899
                                     uint32_t pos,
 
900
                                     uint32_t proptag,
 
901
                                     const char *PidTagAttr)
 
902
{
 
903
        return openchangedb_get_property_data_message(mem_ctx, res->msgs[pos], 
 
904
                                                      proptag, PidTagAttr);
 
905
}
 
906
 
 
907
/**
 
908
   \details Retrieve a MAPI property from an OpenChange LDB message
 
909
 
 
910
   \param mem_ctx pointer to the memory context
 
911
   \param msg pointer to the LDB message
 
912
   \param proptag the MAPI property tag to lookup
 
913
   \param PidTagAttr the mapped MAPI property name
 
914
 
 
915
   \return valid data pointer on success, otherwise NULL
 
916
 */
 
917
void *openchangedb_get_property_data_message(TALLOC_CTX *mem_ctx,
 
918
                                             struct ldb_message *msg,
 
919
                                             uint32_t proptag,
 
920
                                             const char *PidTagAttr)
626
921
{
627
922
        void                    *data;
628
923
        const char              *str;
629
 
        uint64_t                *d;
 
924
        uint64_t                *ll;
630
925
        uint32_t                *l;
631
926
        int                     *b;
 
927
        struct FILETIME         *ft;
 
928
        struct Binary_r         *bin;
 
929
        struct BinaryArray_r    *bin_array;
 
930
        struct LongArray_r      *long_array;
 
931
        struct ldb_val          val;
 
932
        TALLOC_CTX              *local_mem_ctx;
632
933
 
633
934
        switch (proptag & 0xFFFF) {
634
935
        case PT_BOOLEAN:
635
936
                b = talloc_zero(mem_ctx, int);
636
 
                *b = ldb_msg_find_attr_as_bool(res->msgs[pos], PidTagAttr, 0x0);
 
937
                *b = ldb_msg_find_attr_as_bool(msg, PidTagAttr, 0x0);
637
938
                data = (void *)b;
638
939
                break;
639
940
        case PT_LONG:
640
941
                l = talloc_zero(mem_ctx, uint32_t);
641
 
                *l = ldb_msg_find_attr_as_int(res->msgs[pos], PidTagAttr, 0x0);
 
942
                *l = ldb_msg_find_attr_as_uint(msg, PidTagAttr, 0x0);
642
943
                data = (void *)l;
643
944
                break;
644
945
        case PT_I8:
645
 
                str = ldb_msg_find_attr_as_string(res->msgs[pos], PidTagAttr, 0x0);
646
 
                d = talloc_zero(mem_ctx, uint64_t);
647
 
                *d = strtoull(str, NULL, 16);
648
 
                data = (void *)d;
 
946
                ll = talloc_zero(mem_ctx, uint64_t);
 
947
                *ll = ldb_msg_find_attr_as_uint64(msg, PidTagAttr, 0x0);
 
948
                data = (void *)ll;
649
949
                break;
650
950
        case PT_STRING8:
651
951
        case PT_UNICODE:
652
 
                str = ldb_msg_find_attr_as_string(res->msgs[pos], PidTagAttr, NULL);
653
 
                data = (char *) talloc_strdup(mem_ctx, str);
 
952
                str = ldb_msg_find_attr_as_string(msg, PidTagAttr, NULL);
 
953
                local_mem_ctx = talloc_zero(NULL, TALLOC_CTX);
 
954
                val = ldb_binary_decode(local_mem_ctx, str);
 
955
                data = (char *) talloc_strndup(mem_ctx, (char *) val.data, val.length);
 
956
                talloc_free(local_mem_ctx);
 
957
                break;
 
958
        case PT_SYSTIME:
 
959
                ft = talloc_zero(mem_ctx, struct FILETIME);
 
960
                ll = talloc_zero(mem_ctx, uint64_t);
 
961
                *ll = ldb_msg_find_attr_as_uint64(msg, PidTagAttr, 0x0);
 
962
                ft->dwLowDateTime = (*ll & 0xffffffff);
 
963
                ft->dwHighDateTime = *ll >> 32;
 
964
                data = (void *)ft;
 
965
                talloc_free(ll);
 
966
                break;
 
967
        case PT_BINARY:
 
968
                str = ldb_msg_find_attr_as_string(msg, PidTagAttr, 0x0);
 
969
                bin = talloc_zero(mem_ctx, struct Binary_r);
 
970
                bin->lpb = (uint8_t *) talloc_strdup(mem_ctx, str);
 
971
                bin->cb = ldb_base64_decode((char *) bin->lpb);
 
972
                data = (void *)bin;
 
973
                break;
 
974
        case PT_MV_BINARY:
 
975
                str = ldb_msg_find_attr_as_string(msg, PidTagAttr, NULL);
 
976
                bin_array = decode_mv_binary(mem_ctx, str);
 
977
                data = (void *)bin_array;
 
978
                break;
 
979
        case PT_MV_LONG:
 
980
                str = ldb_msg_find_attr_as_string(msg, PidTagAttr, NULL);
 
981
                long_array = decode_mv_long(mem_ctx, str);
 
982
                data = (void *)long_array;
654
983
                break;
655
984
        default:
656
 
                talloc_free(mem_ctx);
657
985
                DEBUG(0, ("[%s:%d] Property Type 0x%.4x not supported\n", __FUNCTION__, __LINE__, (proptag & 0xFFFF)));
 
986
                abort();
658
987
                return NULL;
659
988
        }
660
989
 
661
990
        return data;
662
991
}
663
992
 
664
 
 
665
 
/**
666
 
   \details Return the next available FolderID
667
 
   
668
 
   \param _ldb_ctx pointer to the openchange LDB context
669
 
   \param fid pointer to the fid value the function returns
670
 
 
671
 
   \return MAPI_E_SUCCESS on success, otherwise MAPI error
672
 
 */
673
 
_PUBLIC_ enum MAPISTATUS openchangedb_get_new_folderID(void *_ldb_ctx,
674
 
                                                       uint64_t *fid)
675
 
{
676
 
        TALLOC_CTX              *mem_ctx;
677
 
        int                     ret;
678
 
        struct ldb_context      *ldb_ctx = (struct ldb_context *)_ldb_ctx;
679
 
        struct ldb_result       *res = NULL;
680
 
        struct ldb_message      *msg;
681
 
        const char * const      attrs[] = { "*", NULL };
682
 
 
683
 
        *fid = 0;
684
 
 
685
 
        mem_ctx = talloc_named(NULL, 0, "get_new_folderID");
 
993
/**
 
994
   \details Build a MAPI property suitable for a OpenChange LDB message
 
995
 
 
996
   \param mem_ctx pointer to the memory context
 
997
   \param value the MAPI property
 
998
 
 
999
   \return valid string pointer on success, otherwise NULL
 
1000
 */
 
1001
_PUBLIC_ char *openchangedb_set_folder_property_data(TALLOC_CTX *mem_ctx, 
 
1002
                                                     struct SPropValue *value)
 
1003
{
 
1004
        char                    *data, *subdata;
 
1005
        struct SPropValue       *subvalue;
 
1006
        NTTIME                  nt_time;
 
1007
        uint32_t                i;
 
1008
        size_t                  data_len, subdata_len;
 
1009
        struct BinaryArray_r    *bin_array;
 
1010
 
 
1011
        switch (value->ulPropTag & 0xFFFF) {
 
1012
        case PT_BOOLEAN:
 
1013
                data = talloc_strdup(mem_ctx, value->value.b ? "TRUE" : "FALSE");
 
1014
                break;
 
1015
        case PT_LONG:
 
1016
                data = talloc_asprintf(mem_ctx, "%d", value->value.l);
 
1017
                break;
 
1018
        case PT_I8:
 
1019
                data = talloc_asprintf(mem_ctx, "%"PRIu64, value->value.d);
 
1020
                break;
 
1021
        case PT_STRING8:
 
1022
                data = talloc_strdup(mem_ctx, value->value.lpszA);
 
1023
                break;
 
1024
        case PT_UNICODE:
 
1025
                data = talloc_strdup(mem_ctx, value->value.lpszW);
 
1026
                break;
 
1027
        case PT_SYSTIME:
 
1028
                nt_time = ((uint64_t) value->value.ft.dwHighDateTime << 32) | value->value.ft.dwLowDateTime;
 
1029
                data = talloc_asprintf(mem_ctx, "%"PRIu64, nt_time);
 
1030
                break;
 
1031
        case PT_BINARY:
 
1032
                data = ldb_base64_encode(mem_ctx, (char *) value->value.bin.lpb, value->value.bin.cb);
 
1033
                break;
 
1034
        case PT_MV_BINARY:
 
1035
                bin_array = &value->value.MVbin;
 
1036
                data = talloc_asprintf(mem_ctx, "0x%.8x", bin_array->cValues);
 
1037
                data_len = strlen(data);
 
1038
                for (i = 0; i < bin_array->cValues; i++) {
 
1039
                        subvalue = talloc_zero(NULL, struct SPropValue);
 
1040
                        subvalue->ulPropTag = (value->ulPropTag & 0xffff0fff);
 
1041
                        subvalue->value.bin = bin_array->lpbin[i];
 
1042
                        subdata = openchangedb_set_folder_property_data(subvalue, subvalue);
 
1043
                        subdata_len = strlen(subdata);
 
1044
                        data = talloc_realloc(mem_ctx, data, char, data_len + subdata_len + 2);
 
1045
                        *(data + data_len) = ';';
 
1046
                        memcpy(data + data_len + 1, subdata, subdata_len);
 
1047
                        data_len += subdata_len + 1;
 
1048
                        talloc_free(subvalue);
 
1049
                }
 
1050
                *(data + data_len) = 0;
 
1051
                break;
 
1052
        default:
 
1053
                DEBUG(0, ("[%s:%d] Property Type 0x%.4x not supported\n", __FUNCTION__, __LINE__, (value->ulPropTag & 0xFFFF)));
 
1054
                data = NULL;
 
1055
        }
 
1056
 
 
1057
        return data;
 
1058
}
 
1059
 
 
1060
/**
 
1061
   \details Allocates a new FolderID and returns it
 
1062
   
 
1063
   \param ldb_ctx pointer to the openchange LDB context
 
1064
   \param fid pointer to the fid value the function returns
 
1065
 
 
1066
   \return MAPI_E_SUCCESS on success, otherwise MAPI error
 
1067
 */
 
1068
_PUBLIC_ enum MAPISTATUS openchangedb_get_new_folderID(struct ldb_context *ldb_ctx, uint64_t *fid)
 
1069
{
 
1070
        TALLOC_CTX              *mem_ctx;
 
1071
        int                     ret;
 
1072
        struct ldb_result       *res;
 
1073
        struct ldb_message      *msg;
 
1074
        const char * const      attrs[] = { "*", NULL };
 
1075
 
 
1076
        /* Get the current GlobalCount */
 
1077
        mem_ctx = talloc_named(NULL, 0, "get_next_folderID");
 
1078
        ret = ldb_search(ldb_ctx, mem_ctx, &res, ldb_get_root_basedn(ldb_ctx),
 
1079
                         LDB_SCOPE_SUBTREE, attrs, "(objectClass=server)");
 
1080
        OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS || !res->count, MAPI_E_NOT_FOUND, mem_ctx);
 
1081
 
 
1082
        *fid = ldb_msg_find_attr_as_uint64(res->msgs[0], "GlobalCount", 0);
 
1083
 
 
1084
        /* Update GlobalCount value */
 
1085
        msg = ldb_msg_new(mem_ctx);
 
1086
        msg->dn = ldb_dn_copy(msg, ldb_msg_find_attr_as_dn(ldb_ctx, mem_ctx, res->msgs[0], "distinguishedName"));
 
1087
        ldb_msg_add_fmt(msg, "GlobalCount", "%"PRIu64, ((*fid) + 1));
 
1088
        msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
 
1089
        ret = ldb_modify(ldb_ctx, msg);
 
1090
        OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS, MAPI_E_NO_SUPPORT, mem_ctx);
 
1091
 
 
1092
        talloc_free(mem_ctx);
 
1093
 
 
1094
        *fid = (exchange_globcnt(*fid) << 16) | 0x0001;
 
1095
 
 
1096
        return MAPI_E_SUCCESS;
 
1097
}
 
1098
 
 
1099
/**
 
1100
   \details Allocates a new change number and returns it
 
1101
   
 
1102
   \param ldb_ctx pointer to the openchange LDB context
 
1103
   \param cn pointer to the cn value the function returns
 
1104
 
 
1105
   \return MAPI_E_SUCCESS on success, otherwise MAPI error
 
1106
 */
 
1107
_PUBLIC_ enum MAPISTATUS openchangedb_get_new_changeNumber(struct ldb_context *ldb_ctx, uint64_t *cn)
 
1108
{
 
1109
        TALLOC_CTX              *mem_ctx;
 
1110
        int                     ret;
 
1111
        struct ldb_result       *res;
 
1112
        struct ldb_message      *msg;
 
1113
        const char * const      attrs[] = { "*", NULL };
 
1114
 
 
1115
        /* Get the current GlobalCount */
 
1116
        mem_ctx = talloc_named(NULL, 0, "get_next_changeNumber");
 
1117
        ret = ldb_search(ldb_ctx, mem_ctx, &res, ldb_get_root_basedn(ldb_ctx),
 
1118
                         LDB_SCOPE_SUBTREE, attrs, "(objectClass=server)");
 
1119
        OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS || !res->count, MAPI_E_NOT_FOUND, mem_ctx);
 
1120
 
 
1121
        *cn = ldb_msg_find_attr_as_uint64(res->msgs[0], "ChangeNumber", 1);
 
1122
 
 
1123
        /* Update GlobalCount value */
 
1124
        msg = ldb_msg_new(mem_ctx);
 
1125
        msg->dn = ldb_dn_copy(msg, ldb_msg_find_attr_as_dn(ldb_ctx, mem_ctx, res->msgs[0], "distinguishedName"));
 
1126
        ldb_msg_add_fmt(msg, "ChangeNumber", "%"PRIu64, ((*cn) + 1));
 
1127
        msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
 
1128
        ret = ldb_modify(ldb_ctx, msg);
 
1129
        OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS, MAPI_E_NO_SUPPORT, mem_ctx);
 
1130
 
 
1131
        talloc_free(mem_ctx);
 
1132
 
 
1133
        *cn = (exchange_globcnt(*cn) << 16) | 0x0001;
 
1134
 
 
1135
        return MAPI_E_SUCCESS;
 
1136
}
 
1137
 
 
1138
/**
 
1139
   \details Reserve a range of FMID
 
1140
   
 
1141
   \param ldb_ctx pointer to the openchange LDB context
 
1142
   \param fid pointer to the fid value the function returns
 
1143
 
 
1144
   \return MAPI_E_SUCCESS on success, otherwise MAPI error
 
1145
 */
 
1146
_PUBLIC_ enum MAPISTATUS openchangedb_reserve_fmid_range(struct ldb_context *ldb_ctx,
 
1147
                                                         uint64_t range_len,
 
1148
                                                         uint64_t *first_fmidp)
 
1149
{
 
1150
        TALLOC_CTX              *mem_ctx;
 
1151
        int                     ret;
 
1152
        struct ldb_result       *res;
 
1153
        struct ldb_message      *msg;
 
1154
        uint64_t                fmid;
 
1155
        const char * const      attrs[] = { "*", NULL };
686
1156
 
687
1157
        /* Step 1. Get the current GlobalCount */
 
1158
        mem_ctx = talloc_named(NULL, 0, "get_next_folderID");
688
1159
        ret = ldb_search(ldb_ctx, mem_ctx, &res, ldb_get_root_basedn(ldb_ctx),
689
1160
                         LDB_SCOPE_SUBTREE, attrs, "(objectClass=server)");
690
1161
        OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS || !res->count, MAPI_E_NOT_FOUND, mem_ctx);
691
1162
 
692
 
        *fid = ldb_msg_find_attr_as_uint64(res->msgs[0], "GlobalCount", 0);
 
1163
        fmid = ldb_msg_find_attr_as_uint64(res->msgs[0], "GlobalCount", 0);
693
1164
 
694
1165
        /* Step 2. Update GlobalCount value */
 
1166
        mem_ctx = talloc_zero(NULL, void);
 
1167
 
695
1168
        msg = ldb_msg_new(mem_ctx);
696
1169
        msg->dn = ldb_dn_copy(msg, ldb_msg_find_attr_as_dn(ldb_ctx, mem_ctx, res->msgs[0], "distinguishedName"));
697
 
        ldb_msg_add_fmt(msg, "GlobalCount", "0x%"PRIx64, ((*fid) + 1));
 
1170
        ldb_msg_add_fmt(msg, "GlobalCount", "%"PRIu64, (fmid + range_len));
698
1171
        msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
699
1172
        ret = ldb_modify(ldb_ctx, msg);
700
1173
        OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS, MAPI_E_NO_SUPPORT, mem_ctx);
701
1174
 
702
1175
        talloc_free(mem_ctx);
703
1176
 
704
 
        *fid = (*fid << 16) + 1;
 
1177
        *first_fmidp = (exchange_globcnt(fmid) << 16) | 0x0001;
705
1178
 
706
1179
        return MAPI_E_SUCCESS;
707
1180
}
708
1181
 
709
 
 
710
1182
/**
711
1183
   \details Retrieve a MAPI property value from a folder record
712
1184
 
713
1185
   \param parent_ctx pointer to the memory context
714
 
   \param _ldb_ctx pointer to the openchange LDB context
715
 
   \param recipient the mailbox username
 
1186
   \param ldb_ctx pointer to the openchange LDB context
716
1187
   \param proptag the MAPI property tag to retrieve value for
717
1188
   \param fid the record folder identifier
718
1189
   \param data pointer on pointer to the data the function returns
720
1191
   \return MAPI_E_SUCCESS on success, otherwise MAPI_E_NOT_FOUND
721
1192
 */
722
1193
_PUBLIC_ enum MAPISTATUS openchangedb_get_folder_property(TALLOC_CTX *parent_ctx, 
723
 
                                                          void *_ldb_ctx,
724
 
                                                          char *recipient,
 
1194
                                                          struct ldb_context *ldb_ctx,
725
1195
                                                          uint32_t proptag,
726
1196
                                                          uint64_t fid,
727
1197
                                                          void **data)
728
1198
{
729
1199
        TALLOC_CTX              *mem_ctx;
730
 
        struct ldb_context      *ldb_ctx = (struct ldb_context *)_ldb_ctx;
731
1200
        struct ldb_result       *res = NULL;
732
1201
        const char * const      attrs[] = { "*", NULL };
733
1202
        const char              *PidTagAttr = NULL;
737
1206
 
738
1207
        /* Step 1. Find PidTagFolderId record */
739
1208
        ret = ldb_search(ldb_ctx, mem_ctx, &res, ldb_get_default_basedn(ldb_ctx),
740
 
                         LDB_SCOPE_SUBTREE, attrs, "(PidTagFolderId=0x%.16"PRIx64")", fid);
 
1209
                         LDB_SCOPE_SUBTREE, attrs, "(PidTagFolderId=%"PRIu64")", fid);
741
1210
        OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS || !res->count, MAPI_E_NOT_FOUND, mem_ctx);
742
1211
 
743
1212
        /* Step 2. Convert proptag into PidTag attribute */
748
1217
        OPENCHANGE_RETVAL_IF(!ldb_msg_find_element(res->msgs[0], PidTagAttr), MAPI_E_NOT_FOUND, mem_ctx);
749
1218
 
750
1219
        /* Step 4. Check if this is a "special property" */
751
 
        *data = openchangedb_get_folder_special_property(parent_ctx, ldb_ctx, recipient, res, proptag, PidTagAttr);
 
1220
        *data = openchangedb_get_special_property(parent_ctx, ldb_ctx, res, proptag, PidTagAttr);
752
1221
        OPENCHANGE_RETVAL_IF(*data != NULL, MAPI_E_SUCCESS, mem_ctx);
753
1222
 
754
1223
        /* Step 5. If this is not a "special property" */
755
 
        *data = openchangedb_get_folder_property_data(parent_ctx, res, 0, proptag, PidTagAttr);
 
1224
        *data = openchangedb_get_property_data(parent_ctx, res, 0, proptag, PidTagAttr);
756
1225
        OPENCHANGE_RETVAL_IF(*data != NULL, MAPI_E_SUCCESS, mem_ctx);
757
1226
 
758
1227
        talloc_free(mem_ctx);
760
1229
        return MAPI_E_NOT_FOUND;
761
1230
}
762
1231
 
 
1232
_PUBLIC_ enum MAPISTATUS openchangedb_set_folder_properties(struct ldb_context *ldb_ctx, uint64_t fid, struct SRow *row)
 
1233
{
 
1234
        TALLOC_CTX              *mem_ctx;
 
1235
        struct ldb_result       *res = NULL;
 
1236
        char                    *PidTagAttr = NULL;
 
1237
        struct SPropValue       *value;
 
1238
        const char * const      attrs[] = { "*", NULL };
 
1239
        struct ldb_message      *msg;
 
1240
        char                    *str_value;
 
1241
        time_t                  unix_time;
 
1242
        NTTIME                  nt_time;
 
1243
        uint32_t                i;
 
1244
        int                     ret;
 
1245
 
 
1246
        unix_time = time(NULL);
 
1247
 
 
1248
        mem_ctx = talloc_named(NULL, 0, "set_folder_property");
 
1249
 
 
1250
        /* Step 1. Find PidTagFolderId record */
 
1251
        ret = ldb_search(ldb_ctx, mem_ctx, &res, ldb_get_default_basedn(ldb_ctx),
 
1252
                         LDB_SCOPE_SUBTREE, attrs, "(PidTagFolderId=%"PRIu64")", fid);
 
1253
        OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS || !res->count, MAPI_E_NOT_FOUND, mem_ctx);
 
1254
 
 
1255
        /* Step 2. Update GlobalCount value */
 
1256
        msg = ldb_msg_new(mem_ctx);
 
1257
        msg->dn = ldb_dn_copy(msg, ldb_msg_find_attr_as_dn(ldb_ctx, mem_ctx, res->msgs[0], "distinguishedName"));
 
1258
 
 
1259
        for (i = 0; i < row->cValues; i++) {
 
1260
                value = row->lpProps + i;
 
1261
 
 
1262
                switch (value->ulPropTag) {
 
1263
                case PR_DEPTH:
 
1264
                case PR_SOURCE_KEY:
 
1265
                case PR_PARENT_SOURCE_KEY:
 
1266
                case PR_CHANGE_KEY:
 
1267
                case PR_CREATION_TIME:
 
1268
                case PR_LAST_MODIFICATION_TIME:
 
1269
                        DEBUG(5, ("Ignored attempt to set handled property %.8x\n", value->ulPropTag));
 
1270
                        break;
 
1271
                default:
 
1272
                        /* Step 2. Convert proptag into PidTag attribute */
 
1273
                        PidTagAttr = (char *) openchangedb_property_get_attribute(value->ulPropTag);
 
1274
                        if (!PidTagAttr) {
 
1275
                                PidTagAttr = talloc_asprintf(mem_ctx, "%.8x", value->ulPropTag);
 
1276
                        }
 
1277
 
 
1278
                        str_value = openchangedb_set_folder_property_data(mem_ctx, value);
 
1279
                        if (!str_value) {
 
1280
                                DEBUG(5, ("Ignored property of unhandled type %.4x\n", (value->ulPropTag & 0xffff)));
 
1281
                                continue;
 
1282
                        }
 
1283
 
 
1284
                        ldb_msg_add_string(msg, PidTagAttr, str_value);
 
1285
                        msg->elements[msg->num_elements-1].flags = LDB_FLAG_MOD_REPLACE;
 
1286
                }
 
1287
        }
 
1288
 
 
1289
        /* We set the last modification time */
 
1290
        value = talloc_zero(NULL, struct SPropValue);
 
1291
 
 
1292
        value->ulPropTag = PR_LAST_MODIFICATION_TIME;
 
1293
        unix_to_nt_time(&nt_time, unix_time);
 
1294
        value->value.ft.dwLowDateTime = nt_time & 0xffffffff;
 
1295
        value->value.ft.dwHighDateTime = nt_time >> 32;
 
1296
        str_value = openchangedb_set_folder_property_data(mem_ctx, value);
 
1297
        ldb_msg_add_string(msg, "PidTagLastModificationTime", str_value);
 
1298
        msg->elements[msg->num_elements-1].flags = LDB_FLAG_MOD_REPLACE;
 
1299
 
 
1300
        value->ulPropTag = PidTagChangeNumber;
 
1301
        openchangedb_get_new_changeNumber(ldb_ctx, (uint64_t *) &value->value.d);
 
1302
        str_value = openchangedb_set_folder_property_data(mem_ctx, value);
 
1303
        ldb_msg_add_string(msg, "PidTagChangeNumber", str_value);
 
1304
        msg->elements[msg->num_elements-1].flags = LDB_FLAG_MOD_REPLACE;
 
1305
 
 
1306
        talloc_free(value);
 
1307
 
 
1308
        ret = ldb_modify(ldb_ctx, msg);
 
1309
        OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS, MAPI_E_NO_SUPPORT, mem_ctx);
 
1310
 
 
1311
        talloc_free(mem_ctx);
 
1312
 
 
1313
        return MAPI_E_SUCCESS;
 
1314
}
 
1315
 
763
1316
 
764
1317
/**
765
1318
   \details Retrieve a MAPI property from a table (ldb search results)
766
1319
 
767
1320
   \param parent_ctx pointer to the memory context
768
 
   \param _ldb_ctx pointer to the openchange LDB context
769
 
   \param recipient the mailbox username
 
1321
   \param ldb_ctx pointer to the openchange LDB context
770
1322
   \param ldb_filter the ldb search string
771
1323
   \param proptag the MAPI property tag to retrieve value for
772
1324
   \param pos the record position in search results
775
1327
   \return MAPI_E_SUCCESS on success, otherwise MAPI_E_NOT_FOUND
776
1328
 */
777
1329
_PUBLIC_ enum MAPISTATUS openchangedb_get_table_property(TALLOC_CTX *parent_ctx,
778
 
                                                         void *_ldb_ctx,
779
 
                                                         char *recipient,
780
 
                                                         char *ldb_filter,
 
1330
                                                         struct ldb_context *ldb_ctx,
 
1331
                                                         const char *ldb_filter,
781
1332
                                                         uint32_t proptag,
782
1333
                                                         uint32_t pos,
783
1334
                                                         void **data)
784
1335
{
785
1336
        TALLOC_CTX              *mem_ctx;
786
 
        struct ldb_context      *ldb_ctx = (struct ldb_context *)_ldb_ctx;
787
1337
        struct ldb_result       *res = NULL;
788
1338
        const char * const      attrs[] = { "*", NULL };
789
1339
        const char              *PidTagAttr = NULL;
797
1347
        OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS || !res->count, MAPI_E_INVALID_OBJECT, mem_ctx);
798
1348
 
799
1349
        /* Step 2. Ensure position is within search results range */
800
 
        OPENCHANGE_RETVAL_IF(pos >= res->count, MAPI_E_INVALID_OBJECT, NULL);
 
1350
        OPENCHANGE_RETVAL_IF(pos >= res->count, MAPI_E_INVALID_OBJECT, mem_ctx);
801
1351
 
802
1352
        /* Step 3. Convert proptag into PidTag attribute */
803
1353
        PidTagAttr = openchangedb_property_get_attribute(proptag);
804
1354
        OPENCHANGE_RETVAL_IF(!PidTagAttr, MAPI_E_NOT_FOUND, mem_ctx);
805
1355
 
806
1356
        /* Step 4. Ensure the element exists */
807
 
        OPENCHANGE_RETVAL_IF(!ldb_msg_find_element(res->msgs[pos], PidTagAttr), MAPI_E_NOT_FOUND, mem_ctx);
 
1357
        OPENCHANGE_RETVAL_IF(!ldb_msg_find_element(res->msgs[0], PidTagAttr), MAPI_E_NOT_FOUND, mem_ctx);
808
1358
 
809
1359
        /* Step 5. Check if this is a "special property" */
810
 
        *data = openchangedb_get_folder_special_property(parent_ctx, ldb_ctx, recipient, res, proptag, PidTagAttr);
 
1360
        *data = openchangedb_get_special_property(parent_ctx, ldb_ctx, res, proptag, PidTagAttr);
811
1361
        OPENCHANGE_RETVAL_IF(*data != NULL, MAPI_E_SUCCESS, mem_ctx);
812
1362
 
813
1363
        /* Step 6. Check if this is not a "special property" */
814
 
        *data = openchangedb_get_folder_property_data(parent_ctx, res, pos, proptag, PidTagAttr);
 
1364
        *data = openchangedb_get_property_data(parent_ctx, res, pos, proptag, PidTagAttr);
815
1365
        OPENCHANGE_RETVAL_IF(*data != NULL, MAPI_E_SUCCESS, mem_ctx);
816
1366
 
817
1367
        talloc_free(mem_ctx);
827
1377
   unique in the context of a parent folder, so the parent folder needs to
828
1378
   be provided.
829
1379
 
830
 
   \param _ldb_ctx pointer to the openchange LDB context
 
1380
   \param ldb_ctx pointer to the openchange LDB context
831
1381
   \param parent_fid the folder ID of the parent folder 
832
1382
   \param foldername the name to look up
833
1383
   \param fid the folder ID for the folder with the specified name (0 if not found)
834
1384
 
835
1385
   \return MAPI_E_SUCCESS on success, otherwise MAPI_E_NOT_FOUND
836
1386
 */
837
 
_PUBLIC_ enum MAPISTATUS openchangedb_get_fid_by_name(void *_ldb_ctx,
 
1387
_PUBLIC_ enum MAPISTATUS openchangedb_get_fid_by_name(struct ldb_context *ldb_ctx,
838
1388
                                                      uint64_t parent_fid,
839
1389
                                                      const char* foldername,
840
1390
                                                      uint64_t *fid)
841
1391
{
842
1392
        TALLOC_CTX              *mem_ctx;
843
 
        struct ldb_context      *ldb_ctx = (struct ldb_context *)_ldb_ctx;
844
1393
        struct ldb_result       *res;
845
1394
        const char * const      attrs[] = { "*", NULL };
846
1395
        int                     ret;
847
1396
 
848
1397
        mem_ctx = talloc_named(NULL, 0, "get_fid_by_name");
849
 
        *fid = 0;
850
1398
 
851
1399
        ret = ldb_search(ldb_ctx, mem_ctx, &res, ldb_get_default_basedn(ldb_ctx),
852
1400
                         LDB_SCOPE_SUBTREE, attrs,
853
 
                         "(&(PidTagParentFolderId=0x%.16"PRIx64")(PidTagDisplayName=%s))",
 
1401
                         "(&(PidTagParentFolderId=%"PRIu64")(PidTagDisplayName=%s))",
854
1402
                         parent_fid, foldername);
855
1403
 
856
1404
        OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS, MAPI_E_NOT_FOUND, mem_ctx);
867
1415
}
868
1416
 
869
1417
/**
 
1418
   \details Retrieve the message ID associated with a given subject (normalized)
 
1419
 
 
1420
   \param ldb_ctx pointer to the openchange LDB context
 
1421
   \param parent_fid the folder ID of the parent folder 
 
1422
   \param subject the normalized subject to look up
 
1423
   \param mid the message ID for the message (0 if not found)
 
1424
 
 
1425
   \return MAPI_E_SUCCESS on success, otherwise MAPI_E_NOT_FOUND
 
1426
 */
 
1427
_PUBLIC_ enum MAPISTATUS openchangedb_get_mid_by_subject(struct ldb_context *ldb_ctx, uint64_t parent_fid, const char *subject, bool mailboxstore, uint64_t *mid)
 
1428
{
 
1429
        TALLOC_CTX              *mem_ctx;
 
1430
        struct ldb_result       *res;
 
1431
        struct ldb_dn           *base_dn;
 
1432
        const char * const      attrs[] = { "*", NULL };
 
1433
        int                     ret;
 
1434
 
 
1435
        mem_ctx = talloc_named(NULL, 0, "get_mid_by_subject");
 
1436
 
 
1437
        if (mailboxstore) {
 
1438
                base_dn = ldb_get_default_basedn(ldb_ctx);
 
1439
        } else {
 
1440
                base_dn = ldb_get_root_basedn(ldb_ctx);
 
1441
        }
 
1442
 
 
1443
        ret = ldb_search(ldb_ctx, mem_ctx, &res, base_dn,
 
1444
                         LDB_SCOPE_SUBTREE, attrs,
 
1445
                         "(&(PidTagParentFolderId=%"PRIu64")(PidTagNormalizedSubject=%s))",
 
1446
                         parent_fid, subject);
 
1447
 
 
1448
        OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS, MAPI_E_NOT_FOUND, mem_ctx);
 
1449
 
 
1450
        /* We should only ever get 0 records or 1 record, but there is always a chance
 
1451
           that things got confused at some point, so just return one of the records */
 
1452
        OPENCHANGE_RETVAL_IF(res->count < 1, MAPI_E_NOT_FOUND, mem_ctx);
 
1453
        
 
1454
        *mid = ldb_msg_find_attr_as_uint64(res->msgs[0], "PidTagMessageId", 0);
 
1455
 
 
1456
        talloc_free(mem_ctx);
 
1457
 
 
1458
        return MAPI_E_SUCCESS;
 
1459
}
 
1460
 
 
1461
_PUBLIC_ enum MAPISTATUS openchangedb_delete_folder(struct ldb_context *ldb_ctx, uint64_t fid)
 
1462
{
 
1463
        TALLOC_CTX      *mem_ctx;
 
1464
        char            *dnstr;
 
1465
        struct ldb_dn   *dn;
 
1466
        int             retval;
 
1467
        enum MAPISTATUS ret;
 
1468
 
 
1469
        mem_ctx = talloc_zero(NULL, TALLOC_CTX);
 
1470
 
 
1471
        ret = openchangedb_get_distinguishedName(mem_ctx, ldb_ctx, fid, &dnstr);
 
1472
        if (ret != MAPI_E_SUCCESS) {
 
1473
                goto end;
 
1474
        }
 
1475
 
 
1476
        dn = ldb_dn_new(mem_ctx, ldb_ctx, dnstr);
 
1477
        retval = ldb_delete(ldb_ctx, dn);
 
1478
        if (retval == LDB_SUCCESS) {
 
1479
                ret = MAPI_E_SUCCESS;
 
1480
        }
 
1481
        else {
 
1482
                ret = MAPI_E_CORRUPT_STORE;
 
1483
        }
 
1484
 
 
1485
end:
 
1486
        talloc_free(mem_ctx);
 
1487
        
 
1488
        return ret;
 
1489
}
 
1490
 
 
1491
/**
870
1492
   \details Set the receive folder for a specific message class.
871
1493
 
872
1494
   \param parent_ctx pointer to the memory context
873
 
   \param _ldb_ctx pointer to the openchange LDB context
 
1495
   \param ldb_ctx pointer to the openchange LDB context
874
1496
   \param recipient pointer to the mailbox's username
875
1497
   \param MessageClass message class (e.g. IPM.whatever) to set
876
1498
   \param fid folder identifier for the recipient folder for the message class
877
1499
 
878
1500
   \return MAPI_E_SUCCESS on success, otherwise MAPI_E_NOT_FOUND
879
1501
 */
880
 
_PUBLIC_ enum MAPISTATUS openchangedb_set_ReceiveFolder(TALLOC_CTX *parent_ctx,
881
 
                                                        void *_ldb_ctx,
882
 
                                                        const char *recipient,
883
 
                                                        const char *MessageClass,
884
 
                                                        uint64_t fid)
 
1502
_PUBLIC_ enum MAPISTATUS openchangedb_set_ReceiveFolder(struct ldb_context *ldb_ctx, const char *recipient, const char *MessageClass, uint64_t fid)
885
1503
{
886
1504
        TALLOC_CTX                      *mem_ctx;
887
 
        struct ldb_context              *ldb_ctx = (struct ldb_context *)_ldb_ctx;
888
1505
        struct ldb_result               *res = NULL;
889
1506
        struct ldb_dn                   *dn;
890
1507
        char                            *dnstr;
896
1513
 
897
1514
        DEBUG(5, ("openchangedb_set_ReceiveFolder, recipient: %s\n", recipient));
898
1515
        DEBUG(5, ("openchangedb_set_ReceiveFolder, MessageClass: %s\n", MessageClass));
899
 
        DEBUG(5, ("openchangedb_set_ReceiveFolder, fid: 0x%016"PRIx64"\n", fid));
 
1516
        DEBUG(5, ("openchangedb_set_ReceiveFolder, fid: 0x%.16"PRIx64"\n", fid));
900
1517
        
901
1518
        /* Step 1. Find mailbox DN for the recipient */
902
1519
        ret = ldb_search(ldb_ctx, mem_ctx, &res, ldb_get_default_basedn(ldb_ctx),
924
1541
        /* Step 3. Delete the old entry if applicable */
925
1542
        if (res->count) {
926
1543
                /* we already have an entry for this message class, so delete it before creating the new one */
927
 
                enum MAPISTATUS         retval;
928
1544
                char                    *distinguishedName;
929
1545
                struct ldb_message      *msg;
930
1546
 
931
1547
                uint64_t folderid = ldb_msg_find_attr_as_uint64(res->msgs[0], "PidTagFolderId", 0x0);
932
 
                DEBUG(6, ("openchangedb_set_ReceiveFolder, fid to delete from: 0x%016"PRIx64"\n", folderid));
 
1548
                DEBUG(6, ("openchangedb_set_ReceiveFolder, fid to delete from: 0x%.16"PRIx64"\n", folderid));
933
1549
 
934
 
                retval = openchangedb_get_distinguishedName(parent_ctx, ldb_ctx, folderid, &distinguishedName);
 
1550
                openchangedb_get_distinguishedName(mem_ctx, ldb_ctx, folderid, &distinguishedName);
935
1551
                DEBUG(6, ("openchangedb_set_ReceiveFolder, dn to delete from: %s\n", distinguishedName));
936
1552
                dn = ldb_dn_new(mem_ctx, ldb_ctx, distinguishedName);
937
1553
                talloc_free(distinguishedName);
951
1567
        
952
1568
        /* Step 4. Create the new entry if applicable */
953
1569
        if (fid != 0x0) {
954
 
                enum MAPISTATUS         retval;
955
1570
                char                    *distinguishedName;
956
1571
                struct ldb_message      *msg;
957
1572
 
958
 
                retval = openchangedb_get_distinguishedName(parent_ctx, ldb_ctx, fid, &distinguishedName);
 
1573
                openchangedb_get_distinguishedName(mem_ctx, ldb_ctx, fid, &distinguishedName);
959
1574
                DEBUG(6, ("openchangedb_set_ReceiveFolder, dn to create in: %s\n", distinguishedName));
960
1575
 
961
1576
                dn = ldb_dn_new(mem_ctx, ldb_ctx, distinguishedName);
978
1593
 
979
1594
        return MAPI_E_SUCCESS;
980
1595
}
 
1596
 
 
1597
 
 
1598
_PUBLIC_ enum MAPISTATUS openchangedb_get_fid_from_partial_uri(struct ldb_context *ldb_ctx,
 
1599
                                                               const char *partialURI,
 
1600
                                                               uint64_t *fid)
 
1601
{
 
1602
        TALLOC_CTX              *mem_ctx;
 
1603
        struct ldb_result       *res = NULL;
 
1604
        const char * const      attrs[] = { "*", NULL };
 
1605
        int                     ret;
 
1606
 
 
1607
        mem_ctx = talloc_named(NULL, 0, "get_fid_from_partial_uri");
 
1608
 
 
1609
        /* Search mapistoreURI given partial URI */
 
1610
        ret = ldb_search(ldb_ctx, mem_ctx, &res, ldb_get_default_basedn(ldb_ctx),
 
1611
                         LDB_SCOPE_SUBTREE, attrs, "(MAPIStoreURI=%s)", partialURI);
 
1612
 
 
1613
        OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS || !res->count, MAPI_E_NOT_FOUND, mem_ctx);
 
1614
        OPENCHANGE_RETVAL_IF(res->count > 1, MAPI_E_COLLISION, mem_ctx);
 
1615
 
 
1616
        *fid = ldb_msg_find_attr_as_uint64(res->msgs[0], "PidTagFolderId", 0);
 
1617
        talloc_free(mem_ctx);
 
1618
        
 
1619
        return MAPI_E_SUCCESS;
 
1620
}
 
1621
 
 
1622
 
 
1623
_PUBLIC_ enum MAPISTATUS openchangedb_get_users_from_partial_uri(TALLOC_CTX *parent_ctx,
 
1624
                                                                 struct ldb_context *ldb_ctx,
 
1625
                                                                 const char *partialURI,
 
1626
                                                                 uint32_t *count,
 
1627
                                                                 char ***MAPIStoreURI,
 
1628
                                                                 char ***users)
 
1629
{
 
1630
        TALLOC_CTX              *mem_ctx;
 
1631
        struct ldb_result       *res = NULL;
 
1632
        struct ldb_result       *mres = NULL;
 
1633
        const char              *mailboxDN;
 
1634
        struct ldb_dn           *dn;
 
1635
        const char * const      attrs[] = { "*", NULL };
 
1636
        const char              *tmp;
 
1637
        int                     i;
 
1638
        int                     ret;
 
1639
 
 
1640
        /* Sanity checks */
 
1641
        OPENCHANGE_RETVAL_IF(!ldb_ctx, MAPI_E_NOT_INITIALIZED, NULL);
 
1642
        OPENCHANGE_RETVAL_IF(!partialURI, MAPI_E_INVALID_PARAMETER, NULL);
 
1643
        OPENCHANGE_RETVAL_IF(!count, MAPI_E_INVALID_PARAMETER, NULL);
 
1644
        OPENCHANGE_RETVAL_IF(!MAPIStoreURI, MAPI_E_INVALID_PARAMETER, NULL);
 
1645
        OPENCHANGE_RETVAL_IF(!users, MAPI_E_INVALID_PARAMETER, NULL);
 
1646
        
 
1647
        mem_ctx = talloc_named(NULL, 0, "get_users_from_partial_uri");
 
1648
 
 
1649
        /* Search mapistoreURI given partial URI */
 
1650
        ret = ldb_search(ldb_ctx, mem_ctx, &res, ldb_get_default_basedn(ldb_ctx),
 
1651
                         LDB_SCOPE_SUBTREE, attrs, "(MAPIStoreURI=%s)", partialURI);
 
1652
        OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS || !res->count, MAPI_E_NOT_FOUND, mem_ctx);
 
1653
 
 
1654
        *count = res->count;
 
1655
        *MAPIStoreURI = talloc_array(parent_ctx, char *, *count);
 
1656
        *users = talloc_array(parent_ctx, char *, *count);
 
1657
 
 
1658
        for (i = 0; i != *count; i++) {
 
1659
                tmp = ldb_msg_find_attr_as_string(res->msgs[i], "MAPIStoreURI", NULL);
 
1660
                *MAPIStoreURI[i] = talloc_strdup((TALLOC_CTX *)*MAPIStoreURI, tmp);
 
1661
 
 
1662
                /* Retrieve the system user name */
 
1663
                mailboxDN = ldb_msg_find_attr_as_string(res->msgs[i], "mailboxDN", NULL);
 
1664
                dn = ldb_dn_new(mem_ctx, ldb_ctx, mailboxDN);
 
1665
                ret = ldb_search(ldb_ctx, mem_ctx, &mres, dn, LDB_SCOPE_SUBTREE, attrs, "(distinguishedName=%s)", mailboxDN);
 
1666
                /* This should NEVER happen */
 
1667
                OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS || !res->count, MAPI_E_NOT_FOUND, mem_ctx);
 
1668
                tmp = ldb_msg_find_attr_as_string(mres->msgs[0], "cn", NULL);
 
1669
                *users[i] = talloc_strdup((TALLOC_CTX *)*users, tmp);
 
1670
                talloc_free(mres);
 
1671
        }
 
1672
 
 
1673
        talloc_free(mem_ctx);
 
1674
 
 
1675
        return MAPI_E_SUCCESS;
 
1676
}
 
1677
 
 
1678
 
 
1679
/**
 
1680
   \details Create a folder in openchangedb
 
1681
 
 
1682
   \param ldb_ctx pointer to the openchangedb LDB context
 
1683
   \param username the owner of the mailbox
 
1684
   \param systemIdx the id of the mailbox
 
1685
   \param fidp a pointer to the fid of the mailbox
 
1686
 
 
1687
   \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
 
1688
 */
 
1689
_PUBLIC_ enum MAPISTATUS openchangedb_create_mailbox(struct ldb_context *ldb_ctx, const char *username, int systemIdx, uint64_t *fidp)
 
1690
{
 
1691
        enum MAPISTATUS         retval;
 
1692
        TALLOC_CTX              *mem_ctx;
 
1693
        struct ldb_dn           *mailboxdn;
 
1694
        struct ldb_message      *msg;
 
1695
        NTTIME                  now;
 
1696
        uint64_t                fid, changeNum;
 
1697
        struct GUID             guid;
 
1698
 
 
1699
        /* Sanity Checks */
 
1700
        MAPI_RETVAL_IF(!ldb_ctx, MAPI_E_NOT_INITIALIZED, NULL);
 
1701
        MAPI_RETVAL_IF(!username, MAPI_E_NOT_INITIALIZED, NULL);
 
1702
 
 
1703
        unix_to_nt_time(&now, time(NULL));
 
1704
 
 
1705
        mem_ctx = talloc_named(NULL, 0, "openchangedb_create_mailbox");
 
1706
 
 
1707
        openchangedb_get_new_folderID(ldb_ctx, &fid);
 
1708
        openchangedb_get_new_changeNumber(ldb_ctx, &changeNum);
 
1709
 
 
1710
        /* Retrieve distinguesName for parent folder */
 
1711
 
 
1712
        mailboxdn = ldb_dn_copy(mem_ctx, ldb_get_default_basedn(ldb_ctx));
 
1713
        MAPI_RETVAL_IF(!mailboxdn, MAPI_E_NOT_ENOUGH_MEMORY, mem_ctx);
 
1714
 
 
1715
        ldb_dn_add_child_fmt(mailboxdn, "CN=%s", username);
 
1716
        MAPI_RETVAL_IF(!ldb_dn_validate(mailboxdn), MAPI_E_BAD_VALUE, mem_ctx);
 
1717
        
 
1718
        msg = ldb_msg_new(mem_ctx);
 
1719
        MAPI_RETVAL_IF(!msg, MAPI_E_NOT_ENOUGH_MEMORY, mem_ctx);
 
1720
 
 
1721
        msg->dn = mailboxdn;
 
1722
        ldb_msg_add_string(msg, "objectClass", "systemfolder");
 
1723
        ldb_msg_add_string(msg, "objectClass", "container");
 
1724
        ldb_msg_add_string(msg, "ReplicaID", "1");
 
1725
        guid = GUID_random();
 
1726
        ldb_msg_add_fmt(msg, "ReplicaGUID", "%s", GUID_string(mem_ctx, &guid));
 
1727
        guid = GUID_random();
 
1728
        ldb_msg_add_fmt(msg, "MailboxGUID", "%s", GUID_string(mem_ctx, &guid));
 
1729
        ldb_msg_add_string(msg, "cn", username);
 
1730
        ldb_msg_add_string(msg, "PidTagAccess", "63");
 
1731
        ldb_msg_add_string(msg, "PidTagRights", "2043");
 
1732
        ldb_msg_add_fmt(msg, "PidTagDisplayName", "OpenChange Mailbox: %s", username);
 
1733
        ldb_msg_add_fmt(msg, "PidTagCreationTime", "%"PRId64, now);
 
1734
        ldb_msg_add_fmt(msg, "PidTagLastModificationTime", "%"PRId64, now);
 
1735
        ldb_msg_add_string(msg, "PidTagSubFolders", "TRUE");
 
1736
        ldb_msg_add_fmt(msg, "PidTagFolderId", "%"PRIu64, fid);
 
1737
        ldb_msg_add_fmt(msg, "PidTagChangeNumber", "%"PRIu64, changeNum);
 
1738
        ldb_msg_add_fmt(msg, "PidTagFolderType", "1");
 
1739
        if (systemIdx > -1) {
 
1740
                ldb_msg_add_fmt(msg, "SystemIdx", "%d", systemIdx);
 
1741
        }
 
1742
        ldb_msg_add_fmt(msg, "distinguishedName", "%s", ldb_dn_get_linearized(msg->dn));
 
1743
 
 
1744
        msg->elements[0].flags = LDB_FLAG_MOD_ADD;
 
1745
 
 
1746
        if (ldb_add(ldb_ctx, msg) != LDB_SUCCESS) {
 
1747
                retval = MAPI_E_CALL_FAILED;
 
1748
        }
 
1749
        else {
 
1750
                if (fidp) {
 
1751
                        *fidp = fid;
 
1752
                }
 
1753
 
 
1754
                retval = MAPI_E_SUCCESS;
 
1755
        }
 
1756
 
 
1757
        talloc_free(mem_ctx);
 
1758
 
 
1759
        return retval;
 
1760
}
 
1761
 
 
1762
/**
 
1763
   \details Create a folder in openchangedb
 
1764
 
 
1765
   \param ldb_ctx pointer to the openchangedb LDB context
 
1766
   \param parentFolderID the FID of the parent folder
 
1767
   \param fid the FID of the folder to create
 
1768
   \param MAPIStoreURI the mapistore URI to associate to this folder
 
1769
   \param nt_time the creation time of the folder
 
1770
   \param changeNumber the change number
 
1771
 
 
1772
   \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
 
1773
 */
 
1774
_PUBLIC_ enum MAPISTATUS openchangedb_create_folder(struct ldb_context *ldb_ctx, uint64_t parentFolderID, uint64_t fid, uint64_t changeNumber, const char *MAPIStoreURI, int systemIdx)
 
1775
{
 
1776
        enum MAPISTATUS         retval;
 
1777
        TALLOC_CTX              *mem_ctx;
 
1778
        char                    *dn;
 
1779
        char                    *mailboxDN;
 
1780
        char                    *parentDN;
 
1781
        struct ldb_dn           *basedn;
 
1782
        struct ldb_message      *msg;
 
1783
        NTTIME                  now;
 
1784
 
 
1785
        /* Sanity Checks */
 
1786
        MAPI_RETVAL_IF(!ldb_ctx, MAPI_E_NOT_INITIALIZED, NULL);
 
1787
        MAPI_RETVAL_IF(!parentFolderID, MAPI_E_NOT_INITIALIZED, NULL);
 
1788
        MAPI_RETVAL_IF(!fid, MAPI_E_NOT_INITIALIZED, NULL);
 
1789
        MAPI_RETVAL_IF(!changeNumber, MAPI_E_NOT_INITIALIZED, NULL);
 
1790
 
 
1791
        unix_to_nt_time(&now, time(NULL));
 
1792
 
 
1793
        mem_ctx = talloc_named(NULL, 0, "openchangedb_create_folder");
 
1794
 
 
1795
        /* Retrieve distinguesName for parent folder */
 
1796
        retval = openchangedb_get_distinguishedName(mem_ctx, ldb_ctx, parentFolderID, &parentDN);
 
1797
        MAPI_RETVAL_IF(retval, retval, mem_ctx);
 
1798
 
 
1799
        retval = openchangedb_get_mailboxDN(mem_ctx, ldb_ctx, parentFolderID, &mailboxDN);
 
1800
        MAPI_RETVAL_IF(retval, retval, mem_ctx);
 
1801
 
 
1802
        dn = talloc_asprintf(mem_ctx, "CN=%"PRIu64",%s", fid, parentDN);
 
1803
        MAPI_RETVAL_IF(!dn, MAPI_E_NOT_ENOUGH_MEMORY, mem_ctx);
 
1804
        basedn = ldb_dn_new(mem_ctx, ldb_ctx, dn);
 
1805
        talloc_free(dn);
 
1806
 
 
1807
        MAPI_RETVAL_IF(!ldb_dn_validate(basedn), MAPI_E_BAD_VALUE, mem_ctx);
 
1808
        
 
1809
        msg = ldb_msg_new(mem_ctx);
 
1810
        MAPI_RETVAL_IF(!msg, MAPI_E_NOT_ENOUGH_MEMORY, mem_ctx);
 
1811
 
 
1812
        msg->dn = ldb_dn_copy(mem_ctx, basedn);
 
1813
        ldb_msg_add_string(msg, "objectClass", "systemfolder");
 
1814
        ldb_msg_add_fmt(msg, "cn", "%"PRIu64, fid);
 
1815
        ldb_msg_add_string(msg, "FolderType", "1");
 
1816
        ldb_msg_add_string(msg, "PidTagContentUnreadCount", "0");
 
1817
        ldb_msg_add_string(msg, "PidTagContentCount", "0");
 
1818
        ldb_msg_add_string(msg, "PidTagAttributeHidden", "0");
 
1819
        ldb_msg_add_string(msg, "PidTagAttributeSystem", "0");
 
1820
        ldb_msg_add_string(msg, "PidTagAttributeReadOnly", "0");
 
1821
        ldb_msg_add_string(msg, "PidTagAccess", "63");
 
1822
        ldb_msg_add_string(msg, "PidTagRights", "2043");
 
1823
        ldb_msg_add_fmt(msg, "PidTagFolderType", "1");
 
1824
        ldb_msg_add_fmt(msg, "PidTagCreationTime", "%"PRIu64, now);
 
1825
        ldb_msg_add_fmt(msg, "PidTagNTSDModificationTime", "%"PRIu64, now);
 
1826
        if (mailboxDN) {
 
1827
                ldb_msg_add_string(msg, "mailboxDN", mailboxDN);
 
1828
        }
 
1829
        if (parentFolderID) {
 
1830
                ldb_msg_add_fmt(msg, "PidTagParentFolderId", "%"PRIu64, parentFolderID);
 
1831
        }
 
1832
        ldb_msg_add_fmt(msg, "PidTagFolderId", "%"PRIu64, fid);
 
1833
        ldb_msg_add_fmt(msg, "PidTagChangeNumber", "%"PRIu64, changeNumber);
 
1834
        if (MAPIStoreURI) {
 
1835
                ldb_msg_add_string(msg, "MAPIStoreURI", MAPIStoreURI);
 
1836
        }
 
1837
        if (systemIdx > -1) {
 
1838
                ldb_msg_add_fmt(msg, "SystemIdx", "%d", systemIdx);
 
1839
        }
 
1840
        ldb_msg_add_fmt(msg, "distinguishedName", "%s", ldb_dn_get_linearized(msg->dn));
 
1841
 
 
1842
        msg->elements[0].flags = LDB_FLAG_MOD_ADD;
 
1843
 
 
1844
        if (ldb_add(ldb_ctx, msg) != LDB_SUCCESS) {
 
1845
                retval = MAPI_E_CALL_FAILED;
 
1846
        }
 
1847
        else {
 
1848
                retval = MAPI_E_SUCCESS;
 
1849
        }
 
1850
 
 
1851
        talloc_free(mem_ctx);
 
1852
 
 
1853
        return retval;
 
1854
}
 
1855
 
 
1856
/**
 
1857
   \details Retrieve the number of messages within the specified folder
 
1858
 
 
1859
   \param ldb_ctx pointer to the openchange LDB context
 
1860
   \param fid the folder identifier to use for the search
 
1861
   \param RowCount pointer to the returned number of results
 
1862
 
 
1863
   \return MAPI_E_SUCCESS on success, otherwise MAPI_E_NOT_FOUND
 
1864
 */
 
1865
_PUBLIC_ enum MAPISTATUS openchangedb_get_message_count(struct ldb_context *ldb_ctx, uint64_t fid, uint32_t *RowCount, bool fai)
 
1866
{
 
1867
        TALLOC_CTX              *mem_ctx;
 
1868
        struct ldb_result       *res;
 
1869
        const char * const      attrs[] = { "*", NULL };
 
1870
        const char              *objectClass;
 
1871
        int                     ret;
 
1872
 
 
1873
        /* Sanity checks */
 
1874
        OPENCHANGE_RETVAL_IF(!ldb_ctx, MAPI_E_NOT_INITIALIZED, NULL);
 
1875
        OPENCHANGE_RETVAL_IF(!RowCount, MAPI_E_INVALID_PARAMETER, NULL);
 
1876
 
 
1877
        mem_ctx = talloc_named(NULL, 0, "get_message_count");
 
1878
        *RowCount = 0;
 
1879
 
 
1880
        objectClass = (fai ? "faiMessage" : "systemMessage");
 
1881
        ret = ldb_search(ldb_ctx, mem_ctx, &res, ldb_get_default_basedn(ldb_ctx),
 
1882
                         LDB_SCOPE_SUBTREE, attrs, 
 
1883
                         "(&(objectClass=%s)(PidTagParentFolderId=%"PRIu64"))", objectClass, fid);
 
1884
        printf("ldb error: %s\n", ldb_errstring(ldb_ctx));
 
1885
        OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS, MAPI_E_NOT_FOUND, mem_ctx);
 
1886
        
 
1887
        *RowCount = res->count;
 
1888
 
 
1889
        talloc_free(mem_ctx);
 
1890
 
 
1891
        return MAPI_E_SUCCESS;
 
1892
}