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

« back to all changes in this revision

Viewing changes to mapiproxy/servers/default/emsmdb/oxcfold.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:
3
3
 
4
4
   EMSMDBP: EMSMDB Provider implementation
5
5
 
6
 
   Copyright (C) Julien Kerihuel 2009-2011
 
6
   Copyright (C) Julien Kerihuel 2009-2010
7
7
 
8
8
   This program is free software; you can redistribute it and/or modify
9
9
   it under the terms of the GNU General Public License as published by
32
32
 
33
33
 
34
34
/**
35
 
   \details Open a System or Special folder object.
36
 
 
37
 
   \param mem_ctx pointer to the memory context
38
 
   \param emsmdbp_ctx pointer to the emsmdb provider context
39
 
   \param request OpenFolder request
40
 
   \param response pointer to the OpenFolder response
41
 
 
42
 
   \return MAPI_E_SUCCESS on success, otherwise MAPI error
43
 
 */
44
 
static enum MAPISTATUS RopOpenFolder_SystemSpecialFolder(TALLOC_CTX *mem_ctx, 
45
 
                                                         struct emsmdbp_context *emsmdbp_ctx,
46
 
                                                         struct OpenFolder_req request,
47
 
                                                         struct OpenFolder_repl *response)
48
 
{
49
 
        /* Find parent record */
50
 
        /* Set parent record as basedn */
51
 
        /* Look for systemfolder given its FolderID */
52
 
 
53
 
        return MAPI_E_SUCCESS;
54
 
}
55
 
 
56
 
 
57
 
static enum MAPISTATUS RopOpenFolder_GenericFolder(TALLOC_CTX *mem_ctx,
58
 
                                                   struct emsmdbp_context *emsmdbp_ctx,
59
 
                                                   struct OpenFolder_req request,
60
 
                                                   struct OpenFolder_repl *response,
61
 
                                                   struct mapi_handles *parent)
62
 
{
63
 
        struct emsmdbp_object   *parent_object = NULL;
64
 
        void                    *data;
65
 
        uint64_t                parent_fid;
66
 
        int                     retval;
67
 
        uint32_t                context_id;
68
 
 
69
 
        /* Step 1. Retrieve the parent fid given the handle */
70
 
        mapi_handles_get_private_data(parent, &data);
71
 
        parent_object = (struct emsmdbp_object *) data;
72
 
        if (!parent_object) {
73
 
                DEBUG(4, ("exchange_emsmdb: [OXCFOLD] OpenFolder null object"));
74
 
                return MAPI_E_NO_SUPPORT;
75
 
        }
76
 
 
77
 
        if (parent_object->type != EMSMDBP_OBJECT_FOLDER) {
78
 
                DEBUG(4, ("exchange_emsmdb: [OXCFOLD] OpenFolder wrong object type: 0x%x\n", parent_object->type));
79
 
                return MAPI_E_NO_SUPPORT;
80
 
        }
81
 
        parent_fid = parent_object->object.folder->folderID;
82
 
        context_id = parent_object->object.folder->contextID;
83
 
 
84
 
        /* Step 2. Open folder from mapistore */
85
 
        retval = mapistore_opendir(emsmdbp_ctx->mstore_ctx, context_id, parent_fid, request.folder_id);
86
 
        if (retval) return MAPI_E_NOT_FOUND;
87
 
 
88
 
        return MAPI_E_SUCCESS;
89
 
}
90
 
 
91
 
/**
92
35
   \details EcDoRpc OpenFolder (0x02) Rop. This operation opens an
93
36
   existing folder.
94
37
 
110
53
                                               uint32_t *handles, uint16_t *size)
111
54
{
112
55
        enum MAPISTATUS                 retval;
 
56
        enum mapistore_error            ret;
113
57
        struct mapi_handles             *parent = NULL;
114
58
        struct mapi_handles             *rec = NULL;
115
 
        struct emsmdbp_object           *object;
 
59
        void                            *private_data;
 
60
        struct emsmdbp_object           *object, *parent_object;
116
61
        uint32_t                        handle;
117
 
        bool                            mapistore = false;
 
62
        struct OpenFolder_req           *request;
 
63
        struct OpenFolder_repl          *response;
118
64
 
119
65
        DEBUG(4, ("exchange_emsmdb: [OXCFOLD] OpenFolder (0x02)\n"));
120
66
 
125
71
        OPENCHANGE_RETVAL_IF(!handles, MAPI_E_INVALID_PARAMETER, NULL);
126
72
        OPENCHANGE_RETVAL_IF(!size, MAPI_E_INVALID_PARAMETER, NULL);
127
73
 
128
 
        mapi_repl->u.mapi_OpenFolder.HasRules = 0;
129
 
        mapi_repl->u.mapi_OpenFolder.IsGhosted = 0;
 
74
        request = &mapi_req->u.mapi_OpenFolder;
 
75
        response = &mapi_repl->u.mapi_OpenFolder;
 
76
 
 
77
        mapi_repl->opnum = mapi_req->opnum;
 
78
        mapi_repl->error_code = MAPI_E_SUCCESS;
 
79
        mapi_repl->handle_idx = request->handle_idx;
130
80
 
131
81
        /* Step 1. Retrieve parent handle in the hierarchy */
132
82
        handle = handles[mapi_req->handle_idx];
133
83
        retval = mapi_handles_search(emsmdbp_ctx->handles_ctx, handle, &parent);
134
 
        OPENCHANGE_RETVAL_IF(retval, retval, NULL);
135
 
 
136
 
        mapistore = emsmdbp_is_mapistore(parent);
137
 
        switch (mapistore) {
138
 
        case false:
139
 
                /* system/special folder */
140
 
                DEBUG(0, ("Opening system/special folder\n"));
141
 
                retval = RopOpenFolder_SystemSpecialFolder(mem_ctx, emsmdbp_ctx, 
142
 
                                                           mapi_req->u.mapi_OpenFolder, 
143
 
                                                           &mapi_repl->u.mapi_OpenFolder);
144
 
                mapi_repl->error_code = retval;
145
 
                break;
146
 
        case true:
147
 
                /* handled by mapistore */
148
 
                DEBUG(0, ("Opening Generic folder\n"));
149
 
                retval = RopOpenFolder_GenericFolder(mem_ctx, emsmdbp_ctx, 
150
 
                                                     mapi_req->u.mapi_OpenFolder,
151
 
                                                     &mapi_repl->u.mapi_OpenFolder, parent);
152
 
                mapi_repl->error_code = retval;
153
 
                break;
154
 
        }
155
 
 
 
84
        if (retval) {
 
85
                DEBUG(5, ("  handle (%x) not found: %x\n", handle, mapi_req->handle_idx));
 
86
                mapi_repl->error_code = MAPI_E_INVALID_OBJECT;
 
87
                goto end;
 
88
        }
 
89
 
 
90
        /* With OpenFolder, the parent object may NOT BE the direct parent folder of the folder */
 
91
        mapi_handles_get_private_data(parent, &private_data);
 
92
        parent_object = private_data;
 
93
        if (!parent_object || (parent_object->type != EMSMDBP_OBJECT_FOLDER && parent_object->type != EMSMDBP_OBJECT_MAILBOX)) {
 
94
                DEBUG(5, ("  invalid handle (%x): %x\n", handle, mapi_req->handle_idx));
 
95
                mapi_repl->error_code = MAPI_E_INVALID_OBJECT;
 
96
                goto end;
 
97
        }
 
98
 
 
99
        /* Fill EcDoRpc_MAPI_REPL reply */
 
100
        response->HasRules = 0;
 
101
        response->IsGhosted = 0;
 
102
 
 
103
        mapi_handles_add(emsmdbp_ctx->handles_ctx, handle, &rec);
 
104
        ret = emsmdbp_object_open_folder_by_fid(rec, emsmdbp_ctx, parent_object, request->folder_id, &object);
 
105
        if (ret != MAPISTORE_SUCCESS) {
 
106
                if (ret == MAPISTORE_ERR_DENIED) {
 
107
                        mapi_repl->error_code = MAPI_E_NO_ACCESS;
 
108
                }
 
109
                else {
 
110
                        mapi_repl->error_code = MAPI_E_NOT_FOUND;
 
111
                }
 
112
                goto end;
 
113
        }
 
114
        retval = mapi_handles_set_private_data(rec, object);
 
115
        handles[mapi_repl->handle_idx] = rec->handle;
 
116
 
 
117
end:
156
118
        *size += libmapiserver_RopOpenFolder_size(mapi_repl);
157
119
 
158
 
        /* Fill EcDoRpc_MAPI_REPL reply */
159
 
        if (!mapi_repl->error_code) {
160
 
                retval = mapi_handles_add(emsmdbp_ctx->handles_ctx, handle, &rec);
161
 
 
162
 
                object = emsmdbp_object_folder_init((TALLOC_CTX *)emsmdbp_ctx, emsmdbp_ctx, 
163
 
                                                    mapi_req->u.mapi_OpenFolder.folder_id, parent);
164
 
                if (object) {
165
 
                        retval = mapi_handles_set_private_data(rec, object);
166
 
                }
167
 
                mapi_repl->opnum = mapi_req->opnum;
168
 
                mapi_repl->handle_idx = mapi_req->u.mapi_OpenFolder.handle_idx;
169
 
 
170
 
                handles[mapi_repl->handle_idx] = rec->handle;
171
 
        }
172
 
 
173
120
        return MAPI_E_SUCCESS;
174
121
}
175
122
 
195
142
                                                      struct EcDoRpc_MAPI_REPL *mapi_repl,
196
143
                                                      uint32_t *handles, uint16_t *size)
197
144
{
198
 
        enum MAPISTATUS         ret;
199
 
        enum MAPISTORE_ERROR    retval;
 
145
        enum MAPISTATUS         retval;
200
146
        struct mapi_handles     *parent;
201
147
        struct mapi_handles     *rec = NULL;
202
 
        struct emsmdbp_object   *object = NULL;
 
148
        struct emsmdbp_object   *object = NULL, *parent_object = NULL;
 
149
        struct mapistore_subscription_list *subscription_list;
 
150
        struct mapistore_subscription *subscription;
 
151
        struct mapistore_table_subscription_parameters subscription_parameters;
203
152
        void                    *data;
204
153
        uint64_t                folderID;
205
 
        uint32_t                contextID;
206
154
        uint32_t                handle;
207
 
        bool                    mapistore = false;
208
155
 
209
156
        DEBUG(4, ("exchange_emsmdb: [OXCFOLD] GetHierarchyTable (0x04)\n"));
210
157
 
215
162
        OPENCHANGE_RETVAL_IF(!handles, MAPI_E_INVALID_PARAMETER, NULL);
216
163
        OPENCHANGE_RETVAL_IF(!size, MAPI_E_INVALID_PARAMETER, NULL);
217
164
 
218
 
        handle = handles[mapi_req->handle_idx];
219
 
        ret = mapi_handles_search(emsmdbp_ctx->handles_ctx, handle, &parent);
220
 
        OPENCHANGE_RETVAL_IF(ret, ret, NULL);
221
 
 
222
165
        /* Initialize default empty GetHierarchyTable reply */
223
166
        mapi_repl->opnum = mapi_req->opnum;
 
167
        mapi_repl->error_code = MAPI_E_SUCCESS;
224
168
        mapi_repl->handle_idx = mapi_req->u.mapi_GetHierarchyTable.handle_idx;
225
 
        mapi_repl->error_code = MAPI_E_SUCCESS;
226
169
 
227
170
        /* GetHierarchyTable can only be called for mailbox/folder objects */
 
171
        handle = handles[mapi_req->handle_idx];
 
172
        retval = mapi_handles_search(emsmdbp_ctx->handles_ctx, handle, &parent);
 
173
        if (retval) {
 
174
                DEBUG(5, ("  handle (%x) not found: %x\n", handle, mapi_req->handle_idx));
 
175
                mapi_repl->error_code = MAPI_E_INVALID_OBJECT;
 
176
                goto end;
 
177
        }
 
178
 
228
179
        mapi_handles_get_private_data(parent, &data);
229
 
        object = (struct emsmdbp_object *)data;
230
 
        if (!object) {
 
180
        parent_object = (struct emsmdbp_object *)data;
 
181
        if (!parent_object) {
 
182
                DEBUG(5, ("  no object found\n"));
231
183
                mapi_repl->error_code = MAPI_E_NO_SUPPORT;
232
 
                *size += libmapiserver_RopGetHierarchyTable_size(NULL);
233
 
                return MAPI_E_SUCCESS;
 
184
                goto end;
234
185
        }
235
186
 
236
 
        switch (object->type) {
 
187
        switch (parent_object->type) {
237
188
        case EMSMDBP_OBJECT_MAILBOX:
238
 
                folderID = object->object.mailbox->folderID;
239
 
                contextID = object->object.folder->contextID;
 
189
                folderID = parent_object->object.mailbox->folderID;
240
190
                break;
241
191
        case EMSMDBP_OBJECT_FOLDER:
242
 
                folderID = object->object.folder->folderID;
243
 
                contextID = object->object.folder->contextID;
 
192
                folderID = parent_object->object.folder->folderID;
244
193
                break;
245
194
        default:
 
195
                DEBUG(5, ("  unsupported object type\n"));
246
196
                mapi_repl->error_code = MAPI_E_NO_SUPPORT;
247
 
                *size += libmapiserver_RopGetHierarchyTable_size(NULL);
248
 
                return MAPI_E_SUCCESS;
249
 
        }
250
 
 
251
 
        mapistore = emsmdbp_is_mapistore(parent);
252
 
        switch (mapistore) {
253
 
        case false:
254
 
                /* system/special folder */
255
 
                ret = openchangedb_get_folder_count(emsmdbp_ctx->oc_ctx, folderID, 
256
 
                                                    &mapi_repl->u.mapi_GetHierarchyTable.RowCount);
257
 
                break;
258
 
        case true:
259
 
                /* handled by mapistore */
260
 
                retval = mapistore_get_folder_count(emsmdbp_ctx->mstore_ctx, contextID, folderID, 
261
 
                                                    &mapi_repl->u.mapi_GetHierarchyTable.RowCount);
262
 
                break;
 
197
                goto end;
263
198
        }
264
199
 
265
200
        /* Initialize Table object */
266
 
        handle = handles[mapi_req->handle_idx];
267
 
        ret = mapi_handles_add(emsmdbp_ctx->handles_ctx, handle, &rec);
 
201
        retval = mapi_handles_add(emsmdbp_ctx->handles_ctx, handle, &rec);
268
202
        handles[mapi_repl->handle_idx] = rec->handle;
269
203
 
270
 
        object = emsmdbp_object_table_init((TALLOC_CTX *)rec, emsmdbp_ctx, parent);
271
 
        if (object) {
272
 
                ret = mapi_handles_set_private_data(rec, object);
273
 
                object->object.table->denominator = mapi_repl->u.mapi_GetHierarchyTable.RowCount;
274
 
                object->object.table->ulType = EMSMDBP_TABLE_FOLDER_TYPE;
275
 
        }
276
 
 
 
204
        object = emsmdbp_folder_open_table(rec, parent_object, MAPISTORE_FOLDER_TABLE, rec->handle);
 
205
        if (!object) {
 
206
                mapi_repl->error_code = MAPI_E_INVALID_OBJECT;
 
207
                goto end;
 
208
        }
 
209
        mapi_handles_set_private_data(rec, object);
 
210
        mapi_repl->u.mapi_GetHierarchyTable.RowCount = object->object.table->denominator;
 
211
 
 
212
        /* notifications */
 
213
        if ((mapi_req->u.mapi_GetHierarchyTable.TableFlags & TableFlags_NoNotifications)) {
 
214
                DEBUG(5, ("  notifications skipped\n"));
 
215
        }
 
216
        else {
 
217
                /* we attach the subscription to the session object */
 
218
                subscription_list = talloc_zero(emsmdbp_ctx->mstore_ctx, struct mapistore_subscription_list);
 
219
                DLIST_ADD(emsmdbp_ctx->mstore_ctx->subscriptions, subscription_list);
 
220
 
 
221
                subscription_parameters.table_type = MAPISTORE_FOLDER_TABLE;
 
222
                subscription_parameters.folder_id = folderID;
 
223
 
 
224
                /* note that a mapistore_subscription can exist without a corresponding emsmdbp_object (tables) */
 
225
                subscription = mapistore_new_subscription(subscription_list, emsmdbp_ctx->mstore_ctx,
 
226
                                                          emsmdbp_ctx->username,
 
227
                                                          rec->handle, fnevTableModified, &subscription_parameters);
 
228
                subscription_list->subscription = subscription;
 
229
                object->object.table->subscription_list = subscription_list;
 
230
        }
 
231
 
 
232
end:
277
233
        *size += libmapiserver_RopGetHierarchyTable_size(mapi_repl);
278
234
 
279
235
        return MAPI_E_SUCCESS;
301
257
                                                     struct EcDoRpc_MAPI_REPL *mapi_repl,
302
258
                                                     uint32_t *handles, uint16_t *size)
303
259
{
304
 
        enum MAPISTORE_ERROR    retval;
305
 
        enum MAPISTATUS         ret;
 
260
        enum MAPISTATUS         retval;
306
261
        struct mapi_handles     *parent;
307
262
        struct mapi_handles     *rec = NULL;
308
 
        struct emsmdbp_object   *object = NULL;
 
263
        struct emsmdbp_object   *object = NULL, *parent_object;
 
264
        struct mapistore_subscription_list *subscription_list;
 
265
        struct mapistore_subscription *subscription;
 
266
        struct mapistore_table_subscription_parameters subscription_parameters;
309
267
        void                    *data;
310
268
        uint64_t                folderID;
311
 
        uint32_t                contextID;
312
269
        uint32_t                handle;
313
 
        bool                    mapistore = false;
 
270
        uint8_t                 table_type;
314
271
 
315
272
        DEBUG(4, ("exchange_emsmdb: [OXCFOLD] GetContentsTable (0x05)\n"));
316
273
 
328
285
        mapi_repl->u.mapi_GetContentsTable.RowCount = 0;
329
286
 
330
287
        handle = handles[mapi_req->handle_idx];
331
 
        ret = mapi_handles_search(emsmdbp_ctx->handles_ctx, handle, &parent);
332
 
        if (ret) {
 
288
        retval = mapi_handles_search(emsmdbp_ctx->handles_ctx, handle, &parent);
 
289
        if (retval) {
 
290
                DEBUG(5, ("  handle (%x) not found: %x\n", handle, mapi_req->handle_idx));
333
291
                mapi_repl->error_code = MAPI_E_NO_SUPPORT;
334
 
                *size += libmapiserver_RopGetContentsTable_size(NULL);
335
 
                return MAPI_E_SUCCESS;
 
292
                goto end;
336
293
        }
337
294
 
338
295
        /* GetContentsTable can only be called for folder objects */
339
 
        mapi_handles_get_private_data(parent, &data);
340
 
        object = (struct emsmdbp_object *)data;
341
 
        if (!object) {
 
296
        retval = mapi_handles_get_private_data(parent, &data);
 
297
        if (retval) {
 
298
                mapi_repl->error_code = retval;
 
299
                DEBUG(5, ("  handle data not found, idx = %x\n", mapi_req->handle_idx));
 
300
                goto end;
 
301
        }
 
302
 
 
303
        parent_object = (struct emsmdbp_object *)data;
 
304
        if (!parent_object) {
342
305
                mapi_repl->error_code = MAPI_E_NO_SUPPORT;
343
 
                *size += libmapiserver_RopGetContentsTable_size(NULL);
344
 
                return MAPI_E_SUCCESS;
345
 
        }
346
 
 
347
 
        switch (object->type) {
348
 
        case EMSMDBP_OBJECT_FOLDER:
349
 
                folderID = object->object.folder->folderID;
350
 
                contextID = object->object.folder->contextID;
351
 
                break;
352
 
        default:
353
 
                mapi_repl->u.mapi_GetContentsTable.RowCount = 0;
354
 
                *size += libmapiserver_RopGetContentsTable_size(NULL);
355
 
                return MAPI_E_SUCCESS;
356
 
        }
357
 
 
358
 
        mapistore = emsmdbp_is_mapistore(parent);
359
 
        switch (mapistore) {
360
 
        case false:
361
 
                /* system/special folder */
362
 
                mapi_repl->u.mapi_GetContentsTable.RowCount = 0;
363
 
                break;
364
 
        case true:
365
 
                /* handled by mapistore */
366
 
                retval = mapistore_get_message_count(emsmdbp_ctx->mstore_ctx, contextID, folderID,
367
 
                                                     &mapi_repl->u.mapi_GetContentsTable.RowCount);
368
 
                break;
 
306
                DEBUG(5, ("  handle data not found, idx = %x\n", mapi_req->handle_idx));
 
307
                goto end;
 
308
        }
 
309
 
 
310
        if (parent_object->type != EMSMDBP_OBJECT_FOLDER) {
 
311
                mapi_repl->error_code = MAPI_E_INVALID_OBJECT;
 
312
                goto end;
 
313
        }
 
314
 
 
315
        folderID = parent_object->object.folder->folderID;
 
316
        if ((mapi_req->u.mapi_GetContentsTable.TableFlags & TableFlags_Associated)) {
 
317
                DEBUG(5, ("  table is FAI table\n"));
 
318
                table_type = MAPISTORE_FAI_TABLE;
 
319
        }
 
320
        else {
 
321
                DEBUG(5, ("  table is contents table\n"));
 
322
                table_type = MAPISTORE_MESSAGE_TABLE;
369
323
        }
370
324
 
371
325
        /* Initialize Table object */
372
 
        handle = handles[mapi_req->handle_idx];
373
 
        ret = mapi_handles_add(emsmdbp_ctx->handles_ctx, handle, &rec);
 
326
        retval = mapi_handles_add(emsmdbp_ctx->handles_ctx, handle, &rec);
374
327
        handles[mapi_repl->handle_idx] = rec->handle;
375
328
 
376
 
        object = emsmdbp_object_table_init((TALLOC_CTX *)rec, emsmdbp_ctx, parent);
377
 
        if (object) {
378
 
                ret = mapi_handles_set_private_data(rec, object);
379
 
                object->object.table->denominator = mapi_repl->u.mapi_GetHierarchyTable.RowCount;
380
 
                object->object.table->ulType = EMSMDBP_TABLE_MESSAGE_TYPE;
381
 
        }
 
329
        object = emsmdbp_folder_open_table(rec, parent_object, table_type, rec->handle);
 
330
        if (!object) {
 
331
                mapi_repl->error_code = MAPI_E_INVALID_OBJECT;
 
332
                goto end;
 
333
        }
 
334
        mapi_handles_set_private_data(rec, object);
 
335
        mapi_repl->u.mapi_GetContentsTable.RowCount = object->object.table->denominator;
 
336
 
 
337
        /* notifications */
 
338
        if ((mapi_req->u.mapi_GetContentsTable.TableFlags & TableFlags_NoNotifications)) {
 
339
                DEBUG(5, ("  notifications skipped\n"));
 
340
        }
 
341
        else {
 
342
                /* we attach the subscription to the session object */
 
343
                subscription_list = talloc_zero(emsmdbp_ctx->mstore_ctx, struct mapistore_subscription_list);
 
344
                DLIST_ADD(emsmdbp_ctx->mstore_ctx->subscriptions, subscription_list);
 
345
                
 
346
                if ((mapi_req->u.mapi_GetContentsTable.TableFlags & TableFlags_Associated)) {
 
347
                        subscription_parameters.table_type = MAPISTORE_FAI_TABLE;
 
348
                }
 
349
                else {
 
350
                        subscription_parameters.table_type = MAPISTORE_MESSAGE_TABLE;
 
351
                }
 
352
                subscription_parameters.folder_id = folderID; 
 
353
                
 
354
                /* note that a mapistore_subscription can exist without a corresponding emsmdbp_object (tables) */
 
355
                subscription = mapistore_new_subscription(subscription_list, emsmdbp_ctx->mstore_ctx,
 
356
                                                          emsmdbp_ctx->username,
 
357
                                                          rec->handle, fnevTableModified, &subscription_parameters);
 
358
                subscription_list->subscription = subscription;
 
359
                object->object.table->subscription_list = subscription_list;
 
360
        }
 
361
 
 
362
end:
382
363
        
383
364
        *size += libmapiserver_RopGetContentsTable_size(mapi_repl);
384
365
 
385
366
        return MAPI_E_SUCCESS;
386
367
}
387
368
 
388
 
 
389
 
static enum MAPISTATUS EcDoRpc_RopCreateSystemSpecialFolder(struct emsmdbp_context *emsmdbp_ctx,
390
 
                                                            struct SRow *aRow, 
391
 
                                                            enum FOLDER_FLAGS folderFlags,
392
 
                                                            uint64_t parentFolder,
393
 
                                                            struct CreateFolder_repl *response)
394
 
{
395
 
        TALLOC_CTX                      *mem_ctx;
396
 
        enum MAPISTATUS                 retval;
397
 
        struct ldb_message              *msg;
398
 
        struct ldb_dn                   *basedn;
399
 
        char                            *dn;
400
 
        char                            *parentfid;
401
 
        int                             ret = 0;
402
 
        char                            *displayName;
403
 
        char                            *comment;
404
 
        uint32_t                        *folderType;
405
 
 
406
 
        DEBUG(4, ("exchange_emsmdb: [OXCFOLD] CreateSystemSpecialFolder\n"));
407
 
 
408
 
        displayName = (char *) find_SPropValue_data(aRow, PR_DISPLAY_NAME);
409
 
        if (!displayName) {
410
 
                displayName = (char *) find_SPropValue_data(aRow, PR_DISPLAY_NAME_UNICODE);
411
 
        }
412
 
 
413
 
        /* Step 0. Determine if the folder already exists */
414
 
        if (openchangedb_get_fid_by_name(emsmdbp_ctx->oc_ctx, parentFolder,
415
 
                                         displayName, &response->folder_id) == MAPI_E_SUCCESS) {
416
 
                /* this folder already exists */
417
 
                if ( folderFlags & OPEN_IF_EXISTS ) {
418
 
                        DEBUG(4, ("exchange_emsmdb: [OXCFOLD] CreateFolder Duplicate Folder\n"));
419
 
                        response->IsExistingFolder = true;
420
 
                        return MAPI_E_SUCCESS;
421
 
                } else {
422
 
                        DEBUG(4, ("exchange_emsmdb: [OXCFOLD] CreateFolder Duplicate Folder error\n"));
423
 
                        return MAPI_E_COLLISION;
424
 
                }
425
 
        }
426
 
 
427
 
        mem_ctx = talloc_named(NULL, 0, "RopCreateSystemSpecialFolder");
428
 
 
429
 
        /* Step 1. Retrieve the next available folderID */
430
 
        retval = openchangedb_get_new_folderID(emsmdbp_ctx->oc_ctx, &response->folder_id);
431
 
        OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
432
 
 
433
 
        /* Retrieve dn of parentfolder */
434
 
        retval = openchangedb_get_distinguishedName(mem_ctx, emsmdbp_ctx->oc_ctx, parentFolder, &parentfid);
435
 
        OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
436
 
 
437
 
        /* Step 2. Create the folder LDB record for openchange.ldb */
438
 
        dn = talloc_asprintf(mem_ctx, "CN=0x%016"PRIx64",%s", response->folder_id, parentfid);
439
 
 
440
 
        /* Ensure dn is within user mailbox / prevent from creating
441
 
         * folders in other mailboxes: check dn vs emsmdbp_ctx->username */
442
 
 
443
 
        basedn = ldb_dn_new(mem_ctx, (struct ldb_context *)emsmdbp_ctx->oc_ctx, dn);
444
 
        talloc_free(dn);
445
 
        OPENCHANGE_RETVAL_IF(!ldb_dn_validate(basedn), MAPI_E_BAD_VALUE, mem_ctx);
446
 
        
447
 
        msg = ldb_msg_new(mem_ctx);
448
 
        msg->dn = ldb_dn_copy(mem_ctx, basedn);
449
 
        ldb_msg_add_string(msg, "objectClass", "systemfolder");
450
 
        ldb_msg_add_fmt(msg, "cn", "0x%.16"PRIx64, response->folder_id);
451
 
        ldb_msg_add_string(msg, "PidTagContentUnreadCount", "0");
452
 
        ldb_msg_add_string(msg, "PidTagContentCount", "0");
453
 
        ldb_msg_add_string(msg, "PidTagContainerClass", "IPF.Note");
454
 
        ldb_msg_add_string(msg, "PidTagAttrHidden", "0");
455
 
        ldb_msg_add_string(msg, "PidTagAccess", "63");
456
 
        ldb_msg_add_string(msg, "PidTagRights", "2043");
457
 
        ldb_msg_add_string(msg, "PidTagDisplayName", displayName);
458
 
 
459
 
        folderType = (uint32_t *) find_SPropValue_data(aRow, PR_FOLDER_TYPE);
460
 
        ldb_msg_add_fmt(msg, "PidTagFolderType", "%d", *folderType);
461
 
 
462
 
        comment = (char *) find_SPropValue_data(aRow, PR_COMMENT);
463
 
        if (!comment) {
464
 
                comment = (char *) find_SPropValue_data(aRow, PR_COMMENT_UNICODE);
465
 
        }
466
 
        ldb_msg_add_string(msg, "PidTagComment", comment);
467
 
 
468
 
        ldb_msg_add_fmt(msg, "PidTagParentFolderId", "0x%.16"PRIx64, parentFolder);
469
 
        ldb_msg_add_fmt(msg, "PidTagFolderId", "0x%.16"PRIx64, response->folder_id);
470
 
        ldb_msg_add_fmt(msg, "mapistore_uri", "fsocpf:///usr/local/samba/private/mapistore/%s/0x%.16"PRIx64, 
471
 
                        emsmdbp_ctx->username, response->folder_id);
472
 
        ldb_msg_add_string(msg, "PidTagSubFolders", "0");
473
 
        ldb_msg_add_string(msg, "FolderType", "1");
474
 
        ldb_msg_add_fmt(msg, "distinguishedName", "%s", ldb_dn_get_linearized(msg->dn));
475
 
 
476
 
        msg->elements[0].flags = LDB_FLAG_MOD_ADD;
477
 
 
478
 
        ret = ldb_add((struct ldb_context *)emsmdbp_ctx->oc_ctx, msg);
479
 
        OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS, MAPI_E_NO_SUPPORT, mem_ctx);
480
 
 
481
 
        talloc_free(parentfid);
482
 
        talloc_free(mem_ctx);
483
 
 
484
 
        return MAPI_E_SUCCESS;
485
 
}
486
 
 
487
 
 
488
 
static enum MAPISTATUS EcDoRpc_RopCreateGenericFolder(struct emsmdbp_context *emsmdbp_ctx,
489
 
                                                      struct mapi_handles *parent,
490
 
                                                      struct SRow *aRow,
491
 
                                                      enum FOLDER_FLAGS folderFlags,
492
 
                                                      struct CreateFolder_repl *response)
493
 
{
494
 
        TALLOC_CTX              *mem_ctx;
495
 
        enum MAPISTORE_ERROR    retval;
496
 
        enum MAPISTATUS         retmapi;
497
 
        int                     ret;
498
 
        struct ldb_result       *res = NULL;
499
 
        struct ldb_message      *msg;
500
 
        const char              *new_folder_name = NULL;
501
 
        struct ldb_dn           *ldb_dn;
502
 
        struct emsmdbp_object   *parent_object = NULL;
503
 
        const char * const      attrs[] = { "*", NULL };
504
 
        void                    *data;
505
 
        uint64_t                parent_fid;
506
 
        uint64_t                folder_fid;
507
 
        uint32_t                context_id;
508
 
        char                    *parentfid;
509
 
        int                     count;
510
 
        uint32_t                i;
511
 
 
512
 
        DEBUG(4, ("exchange_emsmdb: [OXCFOLD] CreateGenericFolder\n"));
513
 
 
514
 
        /* Step 1. Retrieve the parent fid given the handle */
515
 
        mapi_handles_get_private_data(parent, &data);
516
 
        parent_object = (struct emsmdbp_object *) data;
517
 
        /* checks are already done in upper function / code factorization required */
518
 
 
519
 
        parent_fid = parent_object->object.folder->folderID;
520
 
        context_id = parent_object->object.folder->contextID;
521
 
 
522
 
        /* Step 2. Get the name of the folder we have to create */
523
 
        for (i = 0; i < aRow->cValues; ++i) {
524
 
                if (aRow->lpProps[i].ulPropTag == PR_DISPLAY_NAME) {
525
 
                        new_folder_name = aRow->lpProps[i].value.lpszA;
526
 
                }
527
 
        }
528
 
        DEBUG(4, ("target folder name: %s\n", new_folder_name));
529
 
        if (folderFlags & OPEN_IF_EXISTS) {
530
 
                /* Determine if the folder already exists */
531
 
                retval = mapistore_get_fid_by_name(emsmdbp_ctx->mstore_ctx, context_id, parent_fid,
532
 
                                                   new_folder_name, &folder_fid);
533
 
                if (retval == MAPISTORE_SUCCESS) {
534
 
                        DEBUG(4, ("exchange_emsmdb: [OXCFOLD] CreateFolder Duplicate Folder at 0x%.16"PRIx64"\n", folder_fid));
535
 
                        /* Open the folder using folder_fid */
536
 
                        retval = mapistore_opendir(emsmdbp_ctx->mstore_ctx, context_id, parent_fid, folder_fid);
537
 
                        if (retval != MAPISTORE_SUCCESS) {
538
 
                                return MAPI_E_NOT_FOUND; /* shouldn't happen */
539
 
                        }
540
 
                        response->IsExistingFolder = true;
541
 
                        return MAPI_E_SUCCESS;
542
 
                }
543
 
        }
544
 
        /* Step 3. Retrieve the next available folderID */
545
 
        retmapi = openchangedb_get_new_folderID(emsmdbp_ctx->oc_ctx, &response->folder_id);
546
 
        OPENCHANGE_RETVAL_IF(retmapi, retmapi, NULL);
547
 
 
548
 
        /* Step 4. Create folder in mapistore */
549
 
        /* FIXME: THIS IS MAPISTORE V1 CODE TO BE CHANGED */
550
 
        /* retval = mapistore_mkdir(emsmdbp_ctx->mstore_ctx, context_id, parent_fid, response->folder_id,  */
551
 
        /*                       aRow); */
552
 
        if (retval == MAPISTORE_ERR_EXIST) {
553
 
                /* folder with this name already exists */
554
 
                DEBUG(4, ("exchange_emsmdb: [OXCFOLD] CreateFolder Duplicate Folder error\n"));
555
 
                return MAPI_E_COLLISION;
556
 
        }
557
 
        OPENCHANGE_RETVAL_IF(retval, MAPI_E_CALL_FAILED, NULL);
558
 
 
559
 
        /* Step 5. Update openchangedb record if needed */
560
 
        if (parent_object->type == EMSMDBP_OBJECT_FOLDER && parent_object->object.folder->mapistore_root == true) {
561
 
                mem_ctx = talloc_named(NULL, 0, "RopCreateGenericFolder");
562
 
 
563
 
                /* Retrieve previous value */
564
 
                ret = ldb_search((struct ldb_context *)emsmdbp_ctx->oc_ctx, mem_ctx, &res, 
565
 
                                 ldb_get_default_basedn((struct ldb_context *)emsmdbp_ctx->oc_ctx),
566
 
                                 LDB_SCOPE_SUBTREE, attrs, "PidTagFolderId=0x%.16"PRIx64, parent_fid);
567
 
                OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS || !res->count, MAPI_E_NOT_FOUND, mem_ctx);
568
 
 
569
 
                count = ldb_msg_find_attr_as_int(res->msgs[0], "PidTagFolderChildCount", 0);
570
 
                
571
 
                /* Update record */
572
 
                retmapi = openchangedb_get_distinguishedName(mem_ctx, emsmdbp_ctx->oc_ctx, parent_fid, &parentfid);
573
 
                OPENCHANGE_RETVAL_IF(retmapi, retmapi, mem_ctx);
574
 
 
575
 
                ldb_dn = ldb_dn_new(mem_ctx, (struct ldb_context *)emsmdbp_ctx->oc_ctx, parentfid);
576
 
                OPENCHANGE_RETVAL_IF(!ldb_dn_validate(ldb_dn), MAPI_E_BAD_VALUE, mem_ctx);
577
 
 
578
 
                msg = ldb_msg_new(mem_ctx);
579
 
                msg->dn = ldb_dn_copy(mem_ctx, ldb_dn);
580
 
                ldb_msg_add_fmt(msg, "PidTagFolderChildCount", "%d", count + 1);
581
 
                ldb_msg_add_fmt(msg, "PidTagSubFolders", "TRUE");
582
 
                msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
583
 
                msg->elements[1].flags = LDB_FLAG_MOD_REPLACE;
584
 
 
585
 
                ret = ldb_modify((struct ldb_context *)emsmdbp_ctx->oc_ctx, msg);
586
 
                OPENCHANGE_RETVAL_IF(ret != LDB_SUCCESS, MAPI_E_NO_SUPPORT, mem_ctx);
587
 
 
588
 
                talloc_free(mem_ctx);
589
 
        }
590
 
 
591
 
        return MAPI_E_SUCCESS;
592
 
}
593
 
 
594
 
 
595
369
/**
596
370
   \details EcDoRpc CreateFolder (0x1c) Rop. This operation creates a
597
371
   folder on the remote server.
616
390
                                                 uint32_t *handles, uint16_t *size)
617
391
{
618
392
        enum MAPISTATUS                 retval;
 
393
        enum mapistore_error            ret;
619
394
        struct mapi_handles             *parent = NULL;
620
395
        uint32_t                        handle;
621
 
        uint64_t                        parent_fid;
 
396
        uint64_t                        parent_fid, fid, cn;
 
397
        struct SPropValue               cnValue;
622
398
        struct emsmdbp_object           *parent_object = NULL;
623
399
        struct emsmdbp_object           *object = NULL;
624
 
        struct SRow                     *aRow;
 
400
        struct CreateFolder_req         *request;
 
401
        struct CreateFolder_repl        *response;
 
402
        struct SRow                     *aRow = NULL;
625
403
        void                            *data;
626
404
        struct mapi_handles             *rec = NULL;
627
 
        bool                            mapistore = false;
628
405
 
629
406
        DEBUG(4, ("exchange_emsmdb: [OXCFOLD] CreateFolder (0x1c)\n"));
630
407
 
637
414
 
638
415
        /* Set up sensible values for the reply */
639
416
        mapi_repl->opnum = mapi_req->opnum;
 
417
        mapi_repl->error_code = MAPI_E_SUCCESS;
640
418
        mapi_repl->handle_idx = mapi_req->u.mapi_CreateFolder.handle_idx;
641
 
        mapi_repl->u.mapi_CreateFolder.IsExistingFolder = false;
642
419
 
643
420
        /* Step 1. Retrieve parent handle in the hierarchy */
644
421
        handle = handles[mapi_req->handle_idx];
645
422
        retval = mapi_handles_search(emsmdbp_ctx->handles_ctx, handle, &parent);
646
423
        OPENCHANGE_RETVAL_IF(retval, retval, NULL);
647
424
 
 
425
        /* With CreateFolder, the parent object really IS the parent object */
648
426
        mapi_handles_get_private_data(parent, &data);
649
427
        parent_object = (struct emsmdbp_object *)data;
650
428
        if (!parent_object) {
651
429
                DEBUG(4, ("exchange_emsmdb: [OXCFOLD] CreateFolder null object\n"));
652
430
                mapi_repl->error_code = MAPI_E_NO_SUPPORT;
653
 
                return MAPI_E_SUCCESS;
 
431
                goto end;
654
432
        }
655
433
 
656
 
        if (parent_object->type != EMSMDBP_OBJECT_FOLDER) {
 
434
        if (parent_object->type != EMSMDBP_OBJECT_FOLDER && parent_object->type != EMSMDBP_OBJECT_MAILBOX) {
657
435
                DEBUG(4, ("exchange_emsmdb: [OXCFOLD] CreateFolder wrong object type: 0x%x\n", parent_object->type));
658
436
                mapi_repl->error_code = MAPI_E_NO_SUPPORT;
659
 
                return MAPI_E_SUCCESS;
660
 
        }
661
 
        parent_fid = parent_object->object.folder->folderID;
662
 
        DEBUG(4, ("exchange_emsmdb: [OXCFOLD] CreateFolder parent: 0x%"PRIx64"\n", parent_fid));
663
 
        DEBUG(4, ("exchange_emsmdb: [OXCFOLD] Creating %s\n", mapi_req->u.mapi_CreateFolder.FolderName.lpszA));
664
 
        
665
 
        /* Step 3. Turn CreateFolder parameters into MAPI property array */
666
 
        aRow = libmapiserver_ROP_request_to_properties(mem_ctx, (void *)&mapi_req->u.mapi_CreateFolder, op_MAPI_CreateFolder);
667
 
        aRow->lpProps = add_SPropValue(mem_ctx, aRow->lpProps, &(aRow->cValues), PR_PARENT_FID, (void *)(&parent_fid));
668
 
 
669
 
        /* Step 4. Do effective work here */
670
 
        mapistore = emsmdbp_is_mapistore(parent);
671
 
        switch (mapistore) {
672
 
        case false:
673
 
                switch (mapi_req->u.mapi_CreateFolder.ulFolderType) {
674
 
                case FOLDER_GENERIC:
675
 
                        mapi_repl->error_code = EcDoRpc_RopCreateSystemSpecialFolder(emsmdbp_ctx, aRow,
676
 
                                                                                     mapi_req->u.mapi_CreateFolder.ulFlags,
677
 
                                                                                     parent_fid, &mapi_repl->u.mapi_CreateFolder);
678
 
                        break;
679
 
                case FOLDER_SEARCH:
680
 
                        DEBUG(4, ("exchange_emsmdb: [OXCFOLD] FOLDER_SEARCH not implemented\n"));
681
 
                        mapi_repl->error_code = MAPI_E_NO_SUPPORT;
682
 
                        break;
683
 
                default:
684
 
                        DEBUG(4, ("exchange_emsmdb: [OXCFOLD] Unexpected folder type 0x%x\n", mapi_req->u.mapi_CreateFolder.ulType));
685
 
                        mapi_repl->error_code = MAPI_E_NO_SUPPORT;
686
 
                }
687
 
                break;
688
 
        case true:
689
 
                mapi_repl->error_code = EcDoRpc_RopCreateGenericFolder(emsmdbp_ctx, parent, aRow,
690
 
                                                                       mapi_req->u.mapi_CreateFolder.ulFlags,
691
 
                                                                       &mapi_repl->u.mapi_CreateFolder);
692
 
                break;
693
 
        }
694
 
 
695
 
        mapi_repl->handle_idx = mapi_req->u.mapi_CreateFolder.handle_idx;
696
 
 
697
 
        if (mapi_repl->u.mapi_CreateFolder.IsExistingFolder == true) {
698
 
                mapi_repl->u.mapi_CreateFolder.GhostUnion.GhostInfo.HasRules = false;
699
 
                mapi_repl->u.mapi_CreateFolder.GhostUnion.GhostInfo.IsGhosted = false;
700
 
        }
701
 
 
702
 
        if (!mapi_repl->error_code) {
703
 
                retval = mapi_handles_add(emsmdbp_ctx->handles_ctx, handle, &rec);
704
 
                object = emsmdbp_object_folder_init((TALLOC_CTX *)rec, emsmdbp_ctx, 
705
 
                                                    mapi_repl->u.mapi_CreateFolder.folder_id, parent);
706
 
                if (object) {
707
 
                        retval = mapi_handles_set_private_data(rec, object);
708
 
                }
709
 
 
710
 
                handles[mapi_repl->handle_idx] = rec->handle;
711
 
        }
712
 
 
 
437
                goto end;
 
438
        }
 
439
 
 
440
        request = &mapi_req->u.mapi_CreateFolder;
 
441
        response = &mapi_repl->u.mapi_CreateFolder;
 
442
 
 
443
        /* DEBUG(4, ("exchange_emsmdb: [OXCFOLD] CreateFolder parent: 0x%.16"PRIx64"\n", parent_fid)); */
 
444
        /* DEBUG(4, ("exchange_emsmdb: [OXCFOLD] Creating %s\n", request->FolderName.lpszW)); */
 
445
 
 
446
        /* if (request->ulFolderType != FOLDER_GENERIC) { */
 
447
        /*      DEBUG(4, ("exchange_emsmdb: [OXCFOLD] Unexpected folder type 0x%x\n", request->ulType)); */
 
448
        /*      mapi_repl->error_code = MAPI_E_NO_SUPPORT; */
 
449
        /*      goto end; */
 
450
        /* } */
 
451
 
 
452
        response->IsExistingFolder = false;
 
453
 
 
454
        ret = emsmdbp_object_get_fid_by_name(emsmdbp_ctx, parent_object, request->FolderName.lpszW, &fid);
 
455
        if (ret == MAPISTORE_SUCCESS) {
 
456
                if (request->ulFlags != OPEN_IF_EXISTS) {
 
457
                        mapi_repl->error_code = MAPI_E_COLLISION;
 
458
                        goto end;
 
459
                }
 
460
                response->IsExistingFolder = true;
 
461
        }
 
462
 
 
463
        mapi_handles_add(emsmdbp_ctx->handles_ctx, handle, &rec);
 
464
        if (response->IsExistingFolder) {
 
465
                ret = emsmdbp_object_open_folder_by_fid(rec, emsmdbp_ctx, parent_object, fid, &object);
 
466
                if (ret != MAPISTORE_SUCCESS) {
 
467
                        DEBUG(5, (__location__": failure opening existing folder\n"));
 
468
                        mapi_handles_delete(emsmdbp_ctx->handles_ctx, rec->handle);
 
469
                        mapi_repl->error_code = retval;
 
470
                        if (ret == MAPISTORE_ERR_DENIED) {
 
471
                                mapi_repl->error_code = MAPI_E_NO_ACCESS;
 
472
                        }
 
473
                        else {
 
474
                                mapi_repl->error_code = MAPI_E_CALL_FAILED;
 
475
                        }
 
476
                        goto end;
 
477
                }
 
478
        }
 
479
        else {
 
480
                /* Step 3. Turn CreateFolder parameters into MAPI property array */
 
481
                retval = openchangedb_get_new_folderID(emsmdbp_ctx->oc_ctx, &fid);
 
482
                if (retval != MAPI_E_SUCCESS) {
 
483
                        DEBUG(4, ("exchange_emsmdb: [OXCFOLD] Could not obtain a new folder id\n"));
 
484
                        mapi_repl->error_code = MAPI_E_NO_SUPPORT;
 
485
                        goto end;
 
486
                }
 
487
 
 
488
                retval = openchangedb_get_new_changeNumber(emsmdbp_ctx->oc_ctx, &cn);
 
489
                if (retval != MAPI_E_SUCCESS) {
 
490
                        DEBUG(4, ("exchange_emsmdb: [OXCFOLD] Could not obtain a new folder cn\n"));
 
491
                        mapi_repl->error_code = MAPI_E_NO_SUPPORT;
 
492
                        goto end;
 
493
                }
 
494
 
 
495
                parent_fid = parent_object->object.folder->folderID;
 
496
                
 
497
                aRow = libmapiserver_ROP_request_to_properties(mem_ctx, (void *)&mapi_req->u.mapi_CreateFolder, op_MAPI_CreateFolder);
 
498
                aRow->lpProps = add_SPropValue(mem_ctx, aRow->lpProps, &(aRow->cValues), PR_PARENT_FID, (void *)(&parent_fid));
 
499
                cnValue.ulPropTag = PidTagChangeNumber;
 
500
                cnValue.value.d = cn;
 
501
                SRow_addprop(aRow, cnValue);
 
502
 
 
503
                retval = emsmdbp_object_create_folder(emsmdbp_ctx, parent_object, rec, fid, aRow, &object);
 
504
                if (retval != MAPI_E_SUCCESS) {
 
505
                        DEBUG(5, (__location__": folder creation failed\n"));
 
506
                        mapi_handles_delete(emsmdbp_ctx->handles_ctx, rec->handle);
 
507
                        mapi_repl->error_code = retval;
 
508
                        goto end;
 
509
                }
 
510
        }
 
511
 
 
512
        handles[mapi_repl->handle_idx] = rec->handle;
 
513
        mapi_handles_set_private_data(rec, object);
 
514
 
 
515
        response->folder_id = fid;
 
516
 
 
517
        if (response->IsExistingFolder == true) {
 
518
                response->GhostUnion.GhostInfo.HasRules = false;
 
519
                response->GhostUnion.GhostInfo.IsGhosted = false;
 
520
        }
 
521
 
 
522
end:
713
523
        *size += libmapiserver_RopCreateFolder_size(mapi_repl);
714
524
 
715
525
        if (aRow) {
719
529
        return MAPI_E_SUCCESS;
720
530
}
721
531
 
722
 
static enum MAPISTATUS DoDeleteSystemFolder(struct emsmdbp_context *emsmdbp_ctx,
723
 
                                            uint64_t parent_fid, uint64_t fid,
724
 
                                            uint8_t flags)
725
 
{
726
 
        TALLOC_CTX                      *mem_ctx;
727
 
        char                            *parentdn;
728
 
        enum MAPISTATUS                 retval;
729
 
        struct ldb_dn                   *dn;
730
 
        char                            *dn_str;
731
 
        int                             ret = 0;
732
 
 
733
 
        DEBUG(4, ("exchange_emsmdb: [OXCFOLD] DeleteFolder parent FID: 0x%"PRIx64"\n", parent_fid));
734
 
        DEBUG(4, ("exchange_emsmdb: [OXCFOLD] DeleteFolder target FID: 0x%"PRIx64"\n", fid));
735
 
 
736
 
        mem_ctx = talloc_named(NULL, 0, "DoDeleteFolder");
737
 
 
738
 
        /* TODO:
739
 
                1. We should be careful not to delete special folders
740
 
                2. We need to handle deleting associated folders and messages (based on the flags)
741
 
        */
742
 
        /* Retrieve dn of parentfolder */
743
 
        retval = openchangedb_get_distinguishedName(mem_ctx, emsmdbp_ctx->oc_ctx, parent_fid, &parentdn);
744
 
        OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx);
745
 
 
746
 
        /* Create the folder dn record for openchange.ldb */
747
 
        dn_str = talloc_asprintf(mem_ctx, "CN=0x%016"PRIx64",%s", fid, parentdn);
748
 
        DEBUG(4, ("exchange_emsmdb: [OXCFOLD] DeleteFolder target DN: %s\n", dn_str));
749
 
        dn = ldb_dn_new(mem_ctx, (struct ldb_context *)emsmdbp_ctx->oc_ctx, dn_str);
750
 
        talloc_free(dn_str);
751
 
        OPENCHANGE_RETVAL_IF(!ldb_dn_validate(dn), MAPI_E_BAD_VALUE, mem_ctx);
752
 
 
753
 
        ret = ldb_delete((struct ldb_context *)emsmdbp_ctx->oc_ctx, dn);
754
 
        if (ret != LDB_SUCCESS) {
755
 
                DEBUG(4, ("exchange_emsmdb: [OXCFOLD] DeleteFolder failed ldb_delete, ret: 0x%x\n", ret));
756
 
                talloc_free(mem_ctx);
757
 
                return MAPI_E_NO_SUPPORT;
758
 
        }
759
 
 
760
 
        talloc_free(mem_ctx);
761
 
        return MAPI_E_SUCCESS;
762
 
}
763
 
 
764
 
 
765
532
/**
766
533
   \details EcDoRpc DeleteFolder (0x1d) Rop. This operation deletes a
767
534
   folder on the remote server.
782
549
                                                 struct EcDoRpc_MAPI_REPL *mapi_repl,
783
550
                                                 uint32_t *handles, uint16_t *size)
784
551
{
785
 
        enum MAPISTORE_ERROR    retval;
786
 
        enum MAPISTATUS         ret;
 
552
        enum MAPISTATUS         retval;
 
553
        enum mapistore_error    ret;
787
554
        struct mapi_handles     *rec = NULL;
788
555
        uint32_t                handle;
789
556
        void                    *handle_priv_data;
790
557
        struct emsmdbp_object   *handle_object = NULL;
791
 
        uint64_t                parent_fid = 0;
792
 
        bool                    mapistore = false;
793
 
        uint32_t                context_id;
794
558
 
795
559
        DEBUG(4, ("exchange_emsmdb: [OXCFOLD] DeleteFolder (0x1d)\n"));
796
560
 
801
565
        OPENCHANGE_RETVAL_IF(!handles, MAPI_E_INVALID_PARAMETER, NULL);
802
566
        OPENCHANGE_RETVAL_IF(!size, MAPI_E_INVALID_PARAMETER, NULL);
803
567
 
 
568
        /* Initialize default empty DeleteFolder reply */
 
569
        mapi_repl->opnum = mapi_req->opnum;
 
570
        mapi_repl->error_code = MAPI_E_SUCCESS;
 
571
        mapi_repl->handle_idx = mapi_req->handle_idx;
 
572
 
804
573
        /* TODO: factor this out to be convenience API */
805
574
        /* Convert the handle index into a handle, and then get the folder id */
806
575
        handle = handles[mapi_req->handle_idx];
807
 
        ret = mapi_handles_search(emsmdbp_ctx->handles_ctx, handle, &rec);
808
 
        OPENCHANGE_RETVAL_IF(ret, ret, NULL);
 
576
        retval = mapi_handles_search(emsmdbp_ctx->handles_ctx, handle, &rec);
 
577
        OPENCHANGE_RETVAL_IF(retval, retval, NULL);
809
578
 
810
579
        mapi_handles_get_private_data(rec, &handle_priv_data);
811
580
        handle_object = (struct emsmdbp_object *)handle_priv_data;
820
589
                mapi_repl->error_code = MAPI_E_NO_SUPPORT;
821
590
                return MAPI_E_SUCCESS;
822
591
        }
823
 
        parent_fid = handle_object->object.folder->folderID;
824
 
        context_id = handle_object->object.folder->contextID;
825
 
 
826
 
        /* Initialize default empty DeleteFolder reply */
827
 
        mapi_repl->opnum = mapi_req->opnum;
828
 
        mapi_repl->handle_idx = mapi_req->handle_idx;
829
 
        mapi_repl->u.mapi_DeleteFolder.PartialCompletion = false;
830
 
 
831
 
        mapistore = emsmdbp_is_mapistore(rec);
832
 
        switch (mapistore) {
833
 
        case false:
834
 
                /* system/special folder */
835
 
                DEBUG(0, ("Deleting system/special folder\n"));
836
 
                mapi_repl->error_code = DoDeleteSystemFolder(emsmdbp_ctx, parent_fid,
837
 
                                                             mapi_req->u.mapi_DeleteFolder.FolderId,
838
 
                                                             mapi_req->u.mapi_DeleteFolder.DeleteFolderFlags);
839
 
 
840
 
                break;
841
 
        case true:
842
 
                /* handled by mapistore */
843
 
                DEBUG(0, ("Deleting mapistore folder\n"));
844
 
                retval = mapistore_rmdir(emsmdbp_ctx->mstore_ctx, context_id, parent_fid,
845
 
                                         mapi_req->u.mapi_DeleteFolder.FolderId,
846
 
                                         mapi_req->u.mapi_DeleteFolder.DeleteFolderFlags);
847
 
                if (retval) {
848
 
                          DEBUG(4, ("exchange_emsmdb: [OXCFOLD] DeleteFolder failed to delete fid 0x%"PRIx64" (0x%x)",
849
 
                                    mapi_req->u.mapi_DeleteFolder.FolderId, retval));
850
 
                          mapi_repl->error_code = MAPI_E_NOT_FOUND;
851
 
                } else {
852
 
                        mapi_repl->error_code = MAPI_E_SUCCESS;
853
 
                }
854
 
                break;
855
 
        }
 
592
 
 
593
        retval = MAPI_E_SUCCESS;
 
594
        ret = emsmdbp_folder_delete(emsmdbp_ctx, handle_object, mapi_req->u.mapi_DeleteFolder.FolderId, mapi_req->u.mapi_DeleteFolder.DeleteFolderFlags);
 
595
        if (ret == MAPISTORE_ERR_EXIST) {
 
596
                mapi_repl->u.mapi_DeleteFolder.PartialCompletion = true;
 
597
        }
 
598
        else if (ret != MAPISTORE_SUCCESS) {
 
599
                DEBUG(4, ("exchange_emsmdb: [OXCFOLD] DeleteFolder failed to delete fid 0x%.16"PRIx64" (0x%x)",
 
600
                          mapi_req->u.mapi_DeleteFolder.FolderId, retval));
 
601
                retval = MAPI_E_NOT_FOUND;
 
602
        }
 
603
        mapi_repl->error_code = retval;
856
604
 
857
605
        *size += libmapiserver_RopDeleteFolder_size(mapi_repl);
858
606
 
859
 
        return ret;
 
607
        return MAPI_E_SUCCESS;
860
608
}
861
609
 
862
610
 
885
633
        struct mapi_handles     *parent_folder = NULL;
886
634
        void                    *parent_folder_private_data;
887
635
        struct emsmdbp_object   *parent_object;
 
636
        char                    *owner;
888
637
        enum MAPISTATUS         retval;
889
 
        uint64_t                parent_folderID;
890
638
        uint32_t                contextID;
891
639
        int                     i;
892
640
 
917
665
                goto delete_message_response;
918
666
        }
919
667
 
920
 
        if (! emsmdbp_is_mapistore(parent_folder) ) {
 
668
        if (!emsmdbp_is_mapistore(parent_object) ) {
921
669
                DEBUG(0, ("Got parent folder not in mapistore\n"));
922
670
                mapi_repl->error_code = MAPI_E_NO_SUPPORT;
923
671
                goto delete_message_response;
924
672
        }
925
673
 
926
 
        parent_folderID = parent_object->object.folder->folderID;
927
 
        contextID = parent_object->object.folder->contextID;
928
 
 
 
674
        contextID = emsmdbp_get_contextID(parent_object);
 
675
        owner = emsmdbp_get_owner(parent_object);
929
676
        for (i = 0; i < mapi_req->u.mapi_DeleteMessages.cn_ids; ++i) {
930
677
                int ret;
931
678
                uint64_t mid = mapi_req->u.mapi_DeleteMessages.message_ids[i];
932
 
                DEBUG(0, ("MID %i to delete: 0x%016"PRIx64"\n", i, mid));
933
 
                ret = mapistore_deletemessage(emsmdbp_ctx->mstore_ctx, contextID, mid, MAPISTORE_SOFT_DELETE);
934
 
                if (ret != MAPISTORE_SUCCESS) {
935
 
                        mapi_repl->error_code = MAPI_E_CALL_FAILED;
 
679
                DEBUG(0, ("MID %i to delete: 0x%.16"PRIx64"\n", i, mid));
 
680
                ret = mapistore_folder_delete_message(emsmdbp_ctx->mstore_ctx, contextID, parent_object->backend_object, mid, MAPISTORE_SOFT_DELETE);
 
681
                if (ret != MAPISTORE_SUCCESS && ret != MAPISTORE_ERR_NOT_FOUND) {
 
682
                        if (ret == MAPISTORE_ERR_DENIED) {
 
683
                                mapi_repl->error_code = MAPI_E_NO_ACCESS;
 
684
                        }
 
685
                        else {
 
686
                                mapi_repl->error_code = MAPI_E_CALL_FAILED;
 
687
                        }
936
688
                        goto delete_message_response;
937
689
                }
938
 
                ret = mapistore_indexing_record_del_mid(emsmdbp_ctx->mstore_ctx, contextID, mid, MAPISTORE_SOFT_DELETE);
 
690
 
 
691
                ret = mapistore_indexing_record_del_mid(emsmdbp_ctx->mstore_ctx, contextID, owner, mid, MAPISTORE_SOFT_DELETE);
939
692
                if (ret != MAPISTORE_SUCCESS) {
940
693
                        mapi_repl->error_code = MAPI_E_CALL_FAILED;
941
694
                        goto delete_message_response;
1012
765
                                                      struct EcDoRpc_MAPI_REPL *mapi_repl,
1013
766
                                                      uint32_t *handles, uint16_t *size)
1014
767
{
1015
 
        struct mapi_SRestriction *res;
 
768
        /* struct mapi_SRestriction *res; */
1016
769
 
1017
770
        DEBUG(4, ("exchange_emsmdb: [OXCFOLD] GetSearchCriteria (0x31)\n"));
1018
771
 
1027
780
        mapi_repl->handle_idx = mapi_req->handle_idx;
1028
781
        mapi_repl->error_code = MAPI_E_SUCCESS;
1029
782
 
1030
 
        res = NULL;
 
783
        /* res = NULL; */
1031
784
        mapi_repl->u.mapi_GetSearchCriteria.RestrictionDataSize = 0;
1032
785
        mapi_repl->u.mapi_GetSearchCriteria.LogonId = mapi_req->logon_id;
1033
786
        mapi_repl->u.mapi_GetSearchCriteria.FolderIdCount = 0;
1047
800
                                                    struct EmptyFolder_repl *response,
1048
801
                                                    struct mapi_handles *folder)
1049
802
{
 
803
        enum MAPISTATUS         ret = MAPI_E_SUCCESS;
1050
804
        void                    *folder_priv;
1051
805
        struct emsmdbp_object   *folder_object = NULL;
1052
 
        uint64_t                fid;
1053
806
        uint32_t                context_id;
1054
 
        int                     retval;
 
807
        enum mapistore_error    retval;
1055
808
        uint64_t                *childFolders;
1056
809
        uint32_t                childFolderCount;
1057
810
        uint32_t                i;
1058
811
        uint8_t                 flags = DELETE_HARD_DELETE| DEL_MESSAGES | DEL_FOLDERS;
 
812
        TALLOC_CTX              *local_mem_ctx;
 
813
        void                    *subfolder;
1059
814
 
1060
815
        /* Step 1. Retrieve the fid for the folder, given the handle */
1061
816
        mapi_handles_get_private_data(folder, &folder_priv);
1069
824
                DEBUG(4, ("exchange_emsmdb: [OXCFOLD] EmptyFolder wrong object type: 0x%x\n", folder_object->type));
1070
825
                return MAPI_E_NO_SUPPORT;
1071
826
        }
1072
 
        fid = folder_object->object.folder->folderID;
1073
 
        context_id = folder_object->object.folder->contextID;
1074
 
 
1075
 
        retval = mapistore_get_child_fids(emsmdbp_ctx->mstore_ctx, context_id, fid,
1076
 
                                          &childFolders, &childFolderCount);
1077
 
        DEBUG(4, ("exchange_emsmdb: [OXCFOLD] EmptyFolder fid: 0x%"PRIx64", count: %d\n", fid, childFolderCount));
 
827
        context_id = emsmdbp_get_contextID(folder_object);
 
828
 
 
829
        local_mem_ctx = talloc_zero(NULL, TALLOC_CTX);
 
830
 
 
831
        retval = mapistore_folder_get_child_fmids(emsmdbp_ctx->mstore_ctx, context_id, folder_object->backend_object, MAPISTORE_FOLDER_TABLE, local_mem_ctx,
 
832
                                                  &childFolders, &childFolderCount);
1078
833
        if (retval) {
1079
834
                DEBUG(4, ("exchange_emsmdb: [OXCFOLD] EmptyFolder bad retval: 0x%x", retval));
1080
 
                return MAPI_E_NOT_FOUND;
 
835
                ret = MAPI_E_NOT_FOUND;
 
836
                goto end;
1081
837
        }
1082
838
 
1083
839
        /* Step 3. Delete contents of the folder in mapistore */
1084
840
        for (i = 0; i < childFolderCount; ++i) {
1085
 
                retval = mapistore_rmdir(emsmdbp_ctx->mstore_ctx, context_id, fid, childFolders[i],
1086
 
                                         flags);
 
841
                retval = mapistore_folder_open_folder(emsmdbp_ctx->mstore_ctx, context_id, folder, local_mem_ctx, childFolders[i], &subfolder);
 
842
                if (retval != MAPISTORE_SUCCESS) {
 
843
                        ret = MAPI_E_NOT_FOUND;
 
844
                        goto end;
 
845
                }
 
846
 
 
847
                retval = mapistore_folder_delete(emsmdbp_ctx->mstore_ctx, context_id, subfolder, flags);
1087
848
                if (retval) {
1088
 
                          DEBUG(4, ("exchange_emsmdb: [OXCFOLD] EmptyFolder failed to delete fid 0x%"PRIx64" (0x%x)", childFolders[i], retval));
1089
 
                          talloc_free(childFolders);
1090
 
                          return MAPI_E_NOT_FOUND;
 
849
                          DEBUG(4, ("exchange_emsmdb: [OXCFOLD] EmptyFolder failed to delete fid 0x%.16"PRIx64" (0x%x)", childFolders[i], retval));
 
850
                          ret = MAPI_E_NOT_FOUND;
 
851
                          goto end;
1091
852
                }
1092
853
        }
1093
 
        return MAPI_E_SUCCESS;
 
854
 
 
855
end:
 
856
        talloc_free(local_mem_ctx);
 
857
 
 
858
        return ret;
1094
859
}
1095
860
 
1096
861
/**
1116
881
{
1117
882
        enum MAPISTATUS                 retval;
1118
883
        struct mapi_handles             *folder = NULL;
 
884
        struct emsmdbp_object           *folder_object;
 
885
        void                            *private_data;
1119
886
        bool                            mapistore = false;
1120
887
 
1121
888
        DEBUG(4, ("exchange_emsmdb: [OXCFOLD] EmptyFolder (0x58)\n"));
1134
901
        /* Step 1. Retrieve folder handle */
1135
902
        retval = mapi_handles_search(emsmdbp_ctx->handles_ctx, handles[mapi_req->handle_idx], &folder);
1136
903
        OPENCHANGE_RETVAL_IF(retval, retval, NULL);
 
904
        mapi_handles_get_private_data(folder, &private_data);
 
905
        folder_object = private_data;
1137
906
 
1138
 
        mapistore = emsmdbp_is_mapistore(folder);
 
907
        mapistore = emsmdbp_is_mapistore(folder_object);
1139
908
        switch (mapistore) {
1140
909
        case false:
1141
910
                /* system/special folder */
1164
933
 
1165
934
        return MAPI_E_SUCCESS;
1166
935
}
 
936
 
 
937
/**
 
938
 
 
939
 */
 
940
_PUBLIC_ enum MAPISTATUS EcDoRpc_RopMoveCopyMessages(TALLOC_CTX *mem_ctx,
 
941
                                                     struct emsmdbp_context *emsmdbp_ctx,
 
942
                                                     struct EcDoRpc_MAPI_REQ *mapi_req,
 
943
                                                     struct EcDoRpc_MAPI_REPL *mapi_repl,
 
944
                                                     uint32_t *handles, uint16_t *size)
 
945
{
 
946
        enum MAPISTATUS         retval;
 
947
        uint32_t                handle;
 
948
        uint32_t                contextID;
 
949
        struct mapi_handles     *rec = NULL;
 
950
        void                    *private_data = NULL;
 
951
        struct emsmdbp_object   *destination_object;
 
952
        struct emsmdbp_object   *source_object;
 
953
        uint64_t                *targetMIDs;
 
954
        uint32_t                i;
 
955
        bool                    mapistore = false;
 
956
 
 
957
        DEBUG(4, ("exchange_emsmdb: [OXCFOLD] RopMoveCopyMessages (0x33)\n"));
 
958
 
 
959
        /* Sanity checks */
 
960
        OPENCHANGE_RETVAL_IF(!emsmdbp_ctx, MAPI_E_NOT_INITIALIZED, NULL);
 
961
        OPENCHANGE_RETVAL_IF(!mapi_req, MAPI_E_INVALID_PARAMETER, NULL);
 
962
        OPENCHANGE_RETVAL_IF(!mapi_repl, MAPI_E_INVALID_PARAMETER, NULL);
 
963
        OPENCHANGE_RETVAL_IF(!handles, MAPI_E_INVALID_PARAMETER, NULL);
 
964
        OPENCHANGE_RETVAL_IF(!size, MAPI_E_INVALID_PARAMETER, NULL);
 
965
 
 
966
        mapi_repl->opnum = mapi_req->opnum;
 
967
        mapi_repl->error_code = MAPI_E_SUCCESS;
 
968
        mapi_repl->handle_idx = mapi_req->handle_idx;
 
969
 
 
970
        mapi_repl->u.mapi_MoveCopyMessages.PartialCompletion = 0;
 
971
 
 
972
        /* Get the destionation information */
 
973
        handle = handles[mapi_req->u.mapi_MoveCopyMessages.handle_idx];
 
974
        retval = mapi_handles_search(emsmdbp_ctx->handles_ctx, handle, &rec);
 
975
        if (retval) {
 
976
                mapi_repl->error_code = MAPI_E_INVALID_OBJECT;
 
977
                DEBUG(5, ("  handle (%x) not found: %x\n", handle, mapi_req->handle_idx));
 
978
                goto end;
 
979
        }
 
980
 
 
981
        retval = mapi_handles_get_private_data(rec, &private_data);
 
982
 
 
983
        /* object is our destination folder */
 
984
        destination_object = private_data;
 
985
        if (!destination_object) {
 
986
                mapi_repl->error_code = MAPI_E_INVALID_OBJECT;
 
987
                DEBUG(5, ("  object (%x) not found: %x\n", handle, mapi_req->handle_idx));
 
988
                goto end;
 
989
        }
 
990
        
 
991
        /* Get the source folder information */
 
992
        handle = handles[mapi_req->handle_idx];
 
993
        retval = mapi_handles_search(emsmdbp_ctx->handles_ctx, handle, &rec);
 
994
        if (retval) {
 
995
                mapi_repl->error_code = MAPI_E_INVALID_OBJECT;
 
996
                DEBUG(5, ("  handle (%x) not found: %x\n", handle, mapi_req->handle_idx));
 
997
                goto end;
 
998
        }
 
999
 
 
1000
        retval = mapi_handles_get_private_data(rec, &private_data);
 
1001
        source_object = private_data;
 
1002
        if (!source_object) {
 
1003
                mapi_repl->error_code = MAPI_E_INVALID_OBJECT;
 
1004
                DEBUG(5, ("  object (%x) not found: %x\n", handle, mapi_req->u.mapi_MoveCopyMessages.handle_idx));
 
1005
                goto end;
 
1006
        }
 
1007
 
 
1008
        contextID = emsmdbp_get_contextID(destination_object);
 
1009
        mapistore = emsmdbp_is_mapistore(source_object);
 
1010
        if (mapistore) {
 
1011
                /* We prepare a set of new MIDs for the backend */
 
1012
                targetMIDs = talloc_array(NULL, uint64_t, mapi_req->u.mapi_MoveCopyMessages.count);
 
1013
                for (i = 0; i < mapi_req->u.mapi_MoveCopyMessages.count; i++) {
 
1014
                        openchangedb_get_new_folderID(emsmdbp_ctx->oc_ctx, &targetMIDs[i]);
 
1015
                }
 
1016
 
 
1017
                /* We invoke the backend method */
 
1018
                mapistore_folder_move_copy_messages(emsmdbp_ctx->mstore_ctx, contextID, destination_object->backend_object, source_object->backend_object, mapi_req->u.mapi_MoveCopyMessages.count, mapi_req->u.mapi_MoveCopyMessages.message_id, targetMIDs, NULL, mapi_req->u.mapi_MoveCopyMessages.WantCopy);
 
1019
                talloc_free(targetMIDs);
 
1020
 
 
1021
                /* /\* The backend might do this for us. In any case, we try to add it ourselves *\/ */
 
1022
                /* mapistore_indexing_record_add_mid(emsmdbp_ctx->mstore_ctx, contextID, targetMID); */
 
1023
        }
 
1024
        else {
 
1025
                DEBUG(0, ("["__location__"] - mapistore support not implemented yet - shouldn't occur\n"));
 
1026
                mapi_repl->error_code = MAPI_E_NO_SUPPORT;
 
1027
        }
 
1028
 
 
1029
end:
 
1030
        *size += libmapiserver_RopMoveCopyMessages_size(mapi_repl);
 
1031
 
 
1032
        return MAPI_E_SUCCESS;
 
1033
}