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

« back to all changes in this revision

Viewing changes to mapiproxy/libmapistore/backends/mapistore_fsocpf.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:
1
 
/*
2
 
   OpenChange Storage Abstraction Layer library
3
 
   MAPIStore FS / OCPF backend
4
 
 
5
 
   OpenChange Project
6
 
 
7
 
   Copyright (C) Julien Kerihuel 2010-2011
8
 
 
9
 
   This program is free software; you can redistribute it and/or modify
10
 
   it under the terms of the GNU General Public License as published by
11
 
   the Free Software Foundation; either version 3 of the License, or
12
 
   (at your option) any later version.
13
 
   
14
 
   This program is distributed in the hope that it will be useful,
15
 
   but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 
   GNU General Public License for more details.
18
 
   
19
 
   You should have received a copy of the GNU General Public License
20
 
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
 
 */
22
 
 
23
 
#include "mapistore_fsocpf.h"
24
 
 
25
 
#include <string.h>
26
 
#include <sys/stat.h>
27
 
#include <sys/types.h>
28
 
 
29
 
#include <errno.h>
30
 
 
31
 
/**
32
 
   \details Initialize fsocpf mapistore backend
33
 
 
34
 
   \return MAPISTORE_SUCCESS on success
35
 
 */
36
 
static enum MAPISTORE_ERROR fsocpf_init(void)
37
 
{
38
 
        DEBUG(0, ("fsocpf backend initialized\n"));
39
 
 
40
 
        ocpf_init();
41
 
        
42
 
        return MAPISTORE_SUCCESS;
43
 
}
44
 
 
45
 
 
46
 
/**
47
 
   \details Allocate / initialize the fsocpf_context structure
48
 
 
49
 
   \param mem_ctx pointer to the memory context
50
 
   \param mstoredb_ctx pointer to the mapistore backend opaque context
51
 
   \param login_user the username used to authenticate
52
 
   \param username the username we want to impersonate
53
 
   \param uri pointer to the fsocpf path
54
 
   \param dir pointer to the DIR structure associated with the uri
55
 
 */
56
 
static struct fsocpf_context *fsocpf_context_init(TALLOC_CTX *mem_ctx,
57
 
                                                  struct mapistore_backend_context *mstoredb_ctx,
58
 
                                                  const char *login_user,
59
 
                                                  const char *username,
60
 
                                                  const char *uri, 
61
 
                                                  DIR *dir)
62
 
{
63
 
        struct fsocpf_context   *fsocpf_ctx;
64
 
 
65
 
        /* Sanity checks */
66
 
        if (!mstoredb_ctx) return NULL;
67
 
 
68
 
        fsocpf_ctx = talloc_zero(mem_ctx, struct fsocpf_context);
69
 
        if (!fsocpf_ctx) return NULL;
70
 
 
71
 
        fsocpf_ctx->private_data = NULL;
72
 
        fsocpf_ctx->mstoredb_ctx = mstoredb_ctx;
73
 
        fsocpf_ctx->login_user = talloc_strdup(fsocpf_ctx, login_user);
74
 
        fsocpf_ctx->username = talloc_strdup(fsocpf_ctx, username);
75
 
        fsocpf_ctx->uri = talloc_strdup(fsocpf_ctx, uri);
76
 
        fsocpf_ctx->dir = dir;
77
 
        fsocpf_ctx->folders = NULL;
78
 
        fsocpf_ctx->messages = NULL;
79
 
 
80
 
        return fsocpf_ctx;
81
 
}
82
 
 
83
 
static enum MAPISTORE_ERROR fsocpf_provision_namedprops(TALLOC_CTX *mem_ctx,
84
 
                                                        char **ldif,
85
 
                                                        enum MAPISTORE_NAMEDPROPS_PROVISION_TYPE *ntype)
86
 
{
87
 
        return MAPISTORE_ERR_NOT_IMPLEMENTED;
88
 
}
89
 
 
90
 
/**
91
 
   \details Generate a mapistore URI for root (system/special) folders
92
 
 
93
 
   \param private_data pointer to the private data holding the fsocpf_context structure
94
 
   \param index the folder index for which to create the mapistore URI
95
 
   \param username the username for which to create the mapistore URI
96
 
   \param mapistore_uri pointer on pointer to the string to return
97
 
 
98
 
   \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
99
 
 */
100
 
static enum MAPISTORE_ERROR fsocpf_create_mapistore_uri(TALLOC_CTX *mem_ctx,
101
 
                                                        uint32_t index,
102
 
                                                        const char *username,
103
 
                                                        char **mapistore_uri)
104
 
{
105
 
        uint32_t                        i;
106
 
 
107
 
        for (i = 0; dflt_folders[i].name; i++) {
108
 
                if (dflt_folders[i].index == index) {
109
 
                        *mapistore_uri = talloc_asprintf(mem_ctx, "fsocpf://%s/%s/%s", mapistore_get_mapping_path(), username, dflt_folders[i].name);
110
 
                        DEBUG(5, ("* [%s:%d][%s]: URI = %s\n", __FILE__, __LINE__, __FUNCTION__, *mapistore_uri));
111
 
                        return MAPISTORE_SUCCESS;
112
 
                }
113
 
        }
114
 
 
115
 
        return MAPISTORE_ERR_NOT_FOUND;
116
 
}
117
 
 
118
 
 
119
 
/**
120
 
   \details Allocate / initialize a fsocpf_folder_list element
121
 
 
122
 
   This essentially creates a node of the linked list, which will be added to the list
123
 
   by the caller
124
 
 
125
 
   \param mem_ctx pointer to the memory context
126
 
   \param uri pointer to the fsocpf path for the folder
127
 
   \param dir pointer to the DIR structure associated with the fid / uri
128
 
 */
129
 
static struct fsocpf_folder_list *fsocpf_folder_list_element_init(TALLOC_CTX *mem_ctx, 
130
 
                                                                  const char *uri, 
131
 
                                                                  DIR *dir)
132
 
{
133
 
        struct fsocpf_folder_list *el;
134
 
 
135
 
        el = talloc_zero(mem_ctx, struct fsocpf_folder_list);
136
 
        if (!el) return NULL;
137
 
 
138
 
        el->folder = talloc_zero((TALLOC_CTX *)el, struct fsocpf_folder);
139
 
        if (!el->folder) {
140
 
                talloc_free(el);
141
 
                return NULL;
142
 
        }
143
 
 
144
 
        el->folder->uri = talloc_strdup((TALLOC_CTX *)el, uri);
145
 
        el->folder->dir = dir;
146
 
 
147
 
        return el;
148
 
}
149
 
 
150
 
/**
151
 
   \details Search for the fsocpf_folder for a given folder URI
152
 
 
153
 
   \param fsocpf_ctx the fsocpf context
154
 
   \param uri the folder uri
155
 
 
156
 
   \return folder on success or NULL if the folder was not found
157
 
 */
158
 
static struct fsocpf_folder *fsocpf_find_folder(struct fsocpf_context *fsocpf_ctx,
159
 
                                                const char *uri)
160
 
{
161
 
        struct fsocpf_folder_list       *el;
162
 
        const char                      *path = NULL;
163
 
 
164
 
        /* Sanity checks */
165
 
        if (!fsocpf_ctx) return NULL;
166
 
        if (!uri) return NULL;
167
 
 
168
 
        if (mapistore_strip_ns_from_uri(uri, &path) != MAPISTORE_SUCCESS) {
169
 
                /* assume it's already stripped */
170
 
                path = uri;
171
 
        }
172
 
        MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, "finding %s\n", path);
173
 
        for (el = fsocpf_ctx->folders; el; el = el->next) {
174
 
                MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, "el->folder->uri: %s\n", el->folder->uri);
175
 
                if (el->folder && el->folder->uri && !strcmp(path, el->folder->uri)) {
176
 
                        return el->folder;
177
 
                }
178
 
        }
179
 
 
180
 
        MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, "%s not found\n", path);
181
 
 
182
 
        return NULL;
183
 
}
184
 
 
185
 
 
186
 
static struct fsocpf_folder_list *fsocpf_find_folder_list(struct fsocpf_context *fsocpf_ctx,
187
 
                                                          const char *uri)
188
 
{
189
 
        struct fsocpf_folder_list       *el;
190
 
        const char                      *path = NULL;
191
 
 
192
 
        /* Sanity checks */
193
 
        if (!fsocpf_ctx) return NULL;
194
 
        if (!fsocpf_ctx->folders) return NULL;
195
 
        if (!uri) return NULL;
196
 
 
197
 
        if (mapistore_strip_ns_from_uri(uri, &path) != MAPISTORE_SUCCESS) {
198
 
                /* assume it's already stripped */
199
 
                path = uri;
200
 
        }
201
 
 
202
 
        MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, "finding %s\n", path);
203
 
 
204
 
        for (el = fsocpf_ctx->folders; el; el = el->next) {
205
 
                MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, "el->folder->uri: %s\n", el->folder->uri);
206
 
                if (el->folder && el->folder->uri && !strcmp(path, el->folder->uri)) {
207
 
                        return el;
208
 
                }
209
 
        }
210
 
 
211
 
        MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, "%s not found\n", path);
212
 
 
213
 
        return NULL;
214
 
}
215
 
 
216
 
/**
217
 
   \details Allocate / initialize a fsocpf_message_list element
218
 
 
219
 
   This essentialy creates a node of the linked list, which will be
220
 
   added to the list by the caller
221
 
 
222
 
   \param mem_ctx pointer to the memory context
223
 
   \param folder_uri the folder uri for the message
224
 
   \param uri pointer to the fsocpf path for the message
225
 
   \param context_id the ocpf context identifier
226
 
 
227
 
   \return Pointer to allocated folder list on success, otherwise NULL
228
 
 */
229
 
static struct fsocpf_message_list *fsocpf_message_list_element_init(TALLOC_CTX *mem_ctx,
230
 
                                                                    const char *folder_uri,
231
 
                                                                    const char *uri,
232
 
                                                                    uint32_t context_id)
233
 
{
234
 
        struct fsocpf_message_list      *el;
235
 
 
236
 
        /* Sanity checks */
237
 
        if (!folder_uri) return NULL;
238
 
        if (!uri) return NULL;
239
 
        if (!context_id) return NULL;
240
 
 
241
 
        el = talloc_zero(mem_ctx, struct fsocpf_message_list);
242
 
        if (!el) return NULL;
243
 
 
244
 
        el->message = talloc_zero((TALLOC_CTX *)el, struct fsocpf_message);
245
 
        if (!el->message) return NULL;
246
 
 
247
 
        el->message->folder_uri = talloc_strdup(el->message, uri);
248
 
        el->message->uri = talloc_strdup((TALLOC_CTX *)el->message, uri);
249
 
        el->message->ocpf_context_id = context_id;
250
 
 
251
 
        return el;
252
 
}
253
 
 
254
 
 
255
 
/**
256
 
   \details search for the fsocpf_message for a given message URI
257
 
 
258
 
   \param fsocpf_ctx the store context
259
 
   \param uri the message URI of the fsocpf_message to search for
260
 
 
261
 
   \return message on success, or NULL if the message was not found
262
 
 */
263
 
static struct fsocpf_message *fsocpf_find_message(struct fsocpf_context *fsocpf_ctx,
264
 
                                                  const char *uri)
265
 
{
266
 
        struct fsocpf_message_list      *el;
267
 
 
268
 
        /* Sanity checks */
269
 
        if (!fsocpf_ctx) return NULL;
270
 
        if (!uri) return NULL;
271
 
 
272
 
        for (el = fsocpf_ctx->messages; el; el = el->next) {
273
 
                if (el->message && el->message->uri && !strcmp(el->message->uri, uri)) {
274
 
                        return el->message;
275
 
                }
276
 
        }
277
 
 
278
 
        return NULL;
279
 
}
280
 
 
281
 
 
282
 
/**
283
 
   \details search for the fsocpf_message_list for a given message URI
284
 
 
285
 
   \param fsocpf_ctx the store context
286
 
   \param uri the message URI of the fsocpf_message to search for
287
 
 
288
 
   \return point to message list on success, or NULL if the message was not found
289
 
 */
290
 
static struct fsocpf_message_list *fsocpf_find_message_list(struct fsocpf_context *fsocpf_ctx,
291
 
                                                            const char *uri)
292
 
{
293
 
        struct fsocpf_message_list      *el;
294
 
 
295
 
        /* Sanity checks */
296
 
        if (!fsocpf_ctx) return NULL;
297
 
        if (!fsocpf_ctx->messages) return NULL;
298
 
        if (!uri) return NULL;
299
 
 
300
 
        for (el = fsocpf_ctx->messages; el; el = el->next) {
301
 
                if (el->message && el->message->uri && !strcmp(el->message->uri, uri)) {
302
 
                        return el;
303
 
                }
304
 
        }
305
 
 
306
 
        return NULL;
307
 
}
308
 
 
309
 
 
310
 
/**
311
 
   \details Create a connection context to the fsocpf backend
312
 
 
313
 
   \param mem_ctx pointer to the memory context
314
 
   \param login_user the username used for authentication
315
 
   \param username the username we want to impersonate
316
 
   \param uri pointer to the fsocpf path
317
 
   \param private_data pointer to the private backend context 
318
 
 */
319
 
static enum MAPISTORE_ERROR fsocpf_create_context(struct mapistore_backend_context *mstoredb_ctx, 
320
 
                                                  const char *login_user, 
321
 
                                                  const char *username,
322
 
                                                  const char *uri, 
323
 
                                                  void **private_data)
324
 
{
325
 
        TALLOC_CTX                      *mem_ctx;
326
 
        DIR                             *top_dir;
327
 
        DIR                             *root_dir;
328
 
        char                            *root_uri;
329
 
        char                            *tmp;
330
 
        struct fsocpf_context           *fsocpf_ctx;
331
 
        struct fsocpf_folder_list       *el;
332
 
 
333
 
        /* Sanity checks */
334
 
        MAPISTORE_RETVAL_IF(!mstoredb_ctx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
335
 
        MAPISTORE_RETVAL_IF(!login_user, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
336
 
        MAPISTORE_RETVAL_IF(!username, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
337
 
        MAPISTORE_RETVAL_IF(!uri, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
338
 
        MAPISTORE_RETVAL_IF(!private_data, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
339
 
 
340
 
        MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, "Creating context for URI: %s\n", uri);
341
 
 
342
 
        mem_ctx = (TALLOC_CTX *) mstoredb_ctx;
343
 
 
344
 
        /* Step 1. Try to open root context directory (username based) */
345
 
        tmp = strstr(uri, username);
346
 
        MAPISTORE_RETVAL_IF(!tmp, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
347
 
        
348
 
        root_uri = talloc_strndup(mem_ctx, uri, strlen(uri) - strlen(tmp) + strlen(username));
349
 
        MAPISTORE_RETVAL_IF(!root_uri, MAPISTORE_ERR_NO_MEMORY, NULL);
350
 
 
351
 
        root_dir = opendir(root_uri);
352
 
        if (!root_dir) {
353
 
                /* If it doesn't exist, try to create it */
354
 
                if (mkdir(root_uri, S_IRWXU) != 0) {
355
 
                        MSTORE_DEBUG_ERROR(MSTORE_LEVEL_CRITICAL, "Unable to create mapistore root folder: %s (%s)\n",
356
 
                                           root_uri, strerror(errno));
357
 
                        talloc_free(root_uri);
358
 
                        return MAPISTORE_ERR_CONTEXT_FAILED;
359
 
                }
360
 
        } else {
361
 
                closedir(root_dir);
362
 
        }
363
 
        talloc_free(root_uri);
364
 
 
365
 
        /* Step 1. Try to open context directory */
366
 
        top_dir = opendir(uri);
367
 
        if (!top_dir) {
368
 
                /* If it doesn't exist, try to create it */
369
 
                if (mkdir(uri, S_IRWXU) != 0 ) {
370
 
                        MSTORE_DEBUG_ERROR(MSTORE_LEVEL_CRITICAL, "Unable to create fsocpf folder: %s\n", strerror(errno));
371
 
                        return MAPISTORE_ERR_CONTEXT_FAILED;
372
 
                }
373
 
                top_dir = opendir(uri);
374
 
                if (!top_dir) {
375
 
                        MSTORE_DEBUG_ERROR(MSTORE_LEVEL_CRITICAL, "Unable to open folder: %s\n", strerror(errno));
376
 
                        return MAPISTORE_ERR_CONTEXT_FAILED;
377
 
                }
378
 
        }
379
 
 
380
 
        /* Step 2. Allocate / Initialize the fsocpf context structure */
381
 
        fsocpf_ctx = fsocpf_context_init(mstoredb_ctx, mem_ctx, login_user, username, uri, top_dir);
382
 
        MAPISTORE_RETVAL_IF(!fsocpf_ctx, MAPISTORE_ERR_NO_MEMORY, NULL);
383
 
 
384
 
        /* Create the entry in the list for top mapistore folders */
385
 
        el = fsocpf_folder_list_element_init((TALLOC_CTX *)fsocpf_ctx, uri, top_dir);
386
 
        MAPISTORE_RETVAL_IF(!el, MAPISTORE_ERR_NO_MEMORY, NULL);
387
 
 
388
 
        DLIST_ADD_END(fsocpf_ctx->folders, el, struct fsocpf_folder_list *);
389
 
        MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, "Folder added to the list: %s\n", el->folder->uri);
390
 
 
391
 
        /* Step 3. Store fsocpf context within the opaque private_data pointer */
392
 
        *private_data = (void *)fsocpf_ctx;
393
 
 
394
 
        DEBUG(0, ("%s has been opened\n", uri));
395
 
        {
396
 
                struct dirent *curdir;
397
 
                int j = 0;
398
 
 
399
 
                while ((curdir = readdir(fsocpf_ctx->dir)) != NULL) {
400
 
                        DEBUG(0, ("%d: readdir: %s\n", j, curdir->d_name));
401
 
                        j++;
402
 
                }
403
 
        }
404
 
 
405
 
        return MAPISTORE_SUCCESS;
406
 
}
407
 
 
408
 
 
409
 
/**
410
 
   \details Delete a connection context from the fsocpf backend
411
 
 
412
 
   \param private_data pointer to the current fsocpf context
413
 
 
414
 
   \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE_ERROR
415
 
 */
416
 
static enum MAPISTORE_ERROR fsocpf_delete_context(void *private_data)
417
 
{
418
 
        struct fsocpf_context   *fsocpf_ctx = (struct fsocpf_context *)private_data;
419
 
 
420
 
        MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, MSTORE_SINGLE_MSG, "");
421
 
 
422
 
        if (!fsocpf_ctx) {
423
 
                return MAPISTORE_SUCCESS;
424
 
        }
425
 
 
426
 
        if (fsocpf_ctx->dir) {
427
 
                closedir(fsocpf_ctx->dir);
428
 
                fsocpf_ctx->dir = NULL;
429
 
        }
430
 
 
431
 
        talloc_free(fsocpf_ctx);
432
 
        fsocpf_ctx = NULL;
433
 
 
434
 
        return MAPISTORE_SUCCESS;
435
 
}
436
 
 
437
 
 
438
 
/**
439
 
   \details Delete data associated to a given folder or message
440
 
 
441
 
   \param private_data pointer to the current fsocpf context
442
 
   \param uri the URI to lookup for release
443
 
   \param type the type of the element to release
444
 
 
445
 
   \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE_ERROR
446
 
 */
447
 
static enum MAPISTORE_ERROR fsocpf_release_record(void *private_data, const char *uri, uint8_t type)
448
 
{
449
 
        struct fsocpf_context           *fsocpf_ctx = (struct fsocpf_context *)private_data;
450
 
        struct fsocpf_message_list      *message;
451
 
 
452
 
        MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, MSTORE_SINGLE_MSG, "");
453
 
 
454
 
        /* Sanity checks */
455
 
        MAPISTORE_RETVAL_IF(!fsocpf_ctx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
456
 
        MAPISTORE_RETVAL_IF(!uri, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
457
 
 
458
 
        switch (type) {
459
 
        case MAPISTORE_FOLDER:
460
 
                break;
461
 
        case MAPISTORE_MESSAGE:
462
 
                message = fsocpf_find_message_list(fsocpf_ctx, uri);
463
 
                if (message && message->message) {
464
 
                        if (message->message->ocpf_context_id) {
465
 
                                ocpf_del_context(message->message->ocpf_context_id);
466
 
                        }
467
 
                        DLIST_REMOVE(fsocpf_ctx->messages, message);
468
 
                        talloc_free(message);
469
 
                }
470
 
                break;
471
 
        }
472
 
 
473
 
        return MAPISTORE_SUCCESS;
474
 
}
475
 
 
476
 
 
477
 
/**
478
 
   \details return the mapistore path associated to a given message or
479
 
   folder ID
480
 
 
481
 
   \param private_data pointer to the current fsocpf context
482
 
   \param uri the folder/message URI to lookup
483
 
   \param type whether it is a folder or message
484
 
   \param path pointer on pointer to the path to return
485
 
 
486
 
   \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
487
 
 */
488
 
static enum MAPISTORE_ERROR fsocpf_get_path(void *private_data, const char *uri,
489
 
                                            uint8_t type, char **path)
490
 
{
491
 
        struct fsocpf_folder    *folder;
492
 
        struct fsocpf_message   *message;
493
 
        struct fsocpf_context   *fsocpf_ctx = (struct fsocpf_context *)private_data;
494
 
 
495
 
        DEBUG(5, ("[%s:%d]\n", __FUNCTION__, __LINE__));
496
 
 
497
 
        if (!fsocpf_ctx) {
498
 
                return MAPISTORE_ERROR;
499
 
        }
500
 
 
501
 
        switch (type) {
502
 
        case MAPISTORE_FOLDER:
503
 
                folder = fsocpf_find_folder(fsocpf_ctx, uri);
504
 
                if (!folder) {
505
 
                        DEBUG(0, ("folder doesn't exist ...\n"));
506
 
                        *path = NULL;
507
 
                        return MAPISTORE_ERROR;
508
 
                }
509
 
                DEBUG(0, ("folder->path is %s\n", folder->uri));
510
 
                *path = folder->uri;
511
 
                break;
512
 
        case MAPISTORE_MESSAGE:
513
 
                message = fsocpf_find_message(fsocpf_ctx, uri);
514
 
                if (!message) {
515
 
                        DEBUG(0, ("message doesn't exist ...\n"));
516
 
                        *path = NULL;
517
 
                        return MAPISTORE_ERROR;
518
 
                }
519
 
                DEBUG(0, ("message->uri is %s\n", message->uri));
520
 
                *path = message->uri;
521
 
                break;
522
 
        default:
523
 
                DEBUG(0, ("[%s]: Invalid type %d\n", __FUNCTION__, type));
524
 
                return MAPISTORE_ERROR;
525
 
        }
526
 
 
527
 
        return MAPISTORE_SUCCESS;
528
 
}
529
 
 
530
 
static enum MAPISTORE_ERROR fsocpf_op_get_uri_by_name(void *private_data, 
531
 
                                                      const char *parent_uri, 
532
 
                                                      const char *foldername, 
533
 
                                                      char **uri)
534
 
{
535
 
        struct fsocpf_context   *fsocpf_ctx = (struct fsocpf_context *)private_data;
536
 
        struct fsocpf_folder    *folder;
537
 
        struct dirent           *curdir;
538
 
 
539
 
        /* Sanity checks */
540
 
        MAPISTORE_RETVAL_IF(!fsocpf_ctx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
541
 
        MAPISTORE_RETVAL_IF(!parent_uri, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
542
 
        MAPISTORE_RETVAL_IF(!foldername, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
543
 
        MAPISTORE_RETVAL_IF(!uri, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
544
 
 
545
 
        /* Lookup the parent folder from its URI */
546
 
        folder = fsocpf_find_folder(fsocpf_ctx, parent_uri);
547
 
        if (!folder) {
548
 
                return MAPISTORE_ERROR;
549
 
        }
550
 
 
551
 
        /* Iterate over the contents of the parent folder, searching for a matching name */
552
 
        rewinddir(folder->dir);
553
 
        while ((curdir = readdir(folder->dir)) != NULL) {
554
 
                if ((curdir->d_type == DT_DIR) && (strcmp(curdir->d_name, foldername) == 0)) {
555
 
                        MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, "folder name %s found\n", foldername);
556
 
                        *uri = talloc_asprintf((TALLOC_CTX *)fsocpf_ctx, "%s/%s", folder->uri, curdir->d_name);
557
 
                        return MAPISTORE_SUCCESS;
558
 
                }
559
 
        }
560
 
        return MAPISTORE_ERR_NOT_FOUND;
561
 
}
562
 
 
563
 
/**
564
 
  \details Set the properties for a folder
565
 
  
566
 
  \param folder_uri the folder full patch
567
 
  \param aRow the properties to set on the folder
568
 
  
569
 
  \return MAPISTORE_SUCCESS on success, otherwise a MAPISTORE_ERROR value.
570
 
*/
571
 
static enum MAPISTORE_ERROR fsocpf_set_folder_props(const char *folder_uri, struct SRow *aRow)
572
 
{
573
 
        TALLOC_CTX                      *mem_ctx;
574
 
        struct mapi_SPropValue_array    mapi_lpProps;
575
 
        uint32_t                        ocpf_context_id;
576
 
        char                            *propfile;
577
 
        uint32_t                        i;
578
 
        struct stat                     sb;
579
 
 
580
 
        mem_ctx = talloc_named(NULL, 0, __FUNCTION__);
581
 
        
582
 
        /* Create the .properties file */
583
 
        propfile = talloc_asprintf(mem_ctx, "%s/.properties", folder_uri);
584
 
        if (stat(propfile, &sb) == -1) {
585
 
                ocpf_new_context(propfile, &ocpf_context_id, OCPF_FLAGS_CREATE);
586
 
                /* Create the array of mapi properties */
587
 
                mapi_lpProps.lpProps = talloc_array(mem_ctx, struct mapi_SPropValue, aRow->cValues);
588
 
                mapi_lpProps.cValues = aRow->cValues;
589
 
                for (i = 0; i < aRow->cValues; i++) {
590
 
                        cast_mapi_SPropValue((TALLOC_CTX *)mapi_lpProps.lpProps,
591
 
                                              &(mapi_lpProps.lpProps[i]), &(aRow->lpProps[i]));
592
 
                }
593
 
        } else {
594
 
                uint32_t num_props = 0;
595
 
                struct SPropValue *original_props;
596
 
                int i = 0;
597
 
                ocpf_new_context(propfile, &ocpf_context_id, OCPF_FLAGS_RDWR);
598
 
                /* get all the old folder properties */
599
 
                ocpf_parse(ocpf_context_id); /* TODO: check return type */
600
 
                ocpf_server_set_SPropValue(mem_ctx, ocpf_context_id);
601
 
                original_props = ocpf_get_SPropValue(ocpf_context_id, &num_props);
602
 
                /* add new and update existing properties */
603
 
                for (i = 0; i < aRow->cValues; ++i) {
604
 
                        int j = 0;
605
 
                        bool found = false;
606
 
                        for (j = 0; j < num_props; ++j) {
607
 
                                if (aRow->lpProps[i].ulPropTag == original_props[j].ulPropTag) {
608
 
                                        original_props[j].value = aRow->lpProps[i].value;
609
 
                                        found = true;
610
 
                                }
611
 
                        }
612
 
                        if (!found) {
613
 
                                num_props += 1;
614
 
                                original_props = talloc_realloc(NULL, original_props, struct SPropValue, num_props);
615
 
                                original_props[num_props -1].ulPropTag = aRow->lpProps[i].ulPropTag;
616
 
                                original_props[num_props -1].value = aRow->lpProps[i].value;
617
 
                        }
618
 
                }
619
 
                /* convert the output to the right format */
620
 
                mapi_lpProps.lpProps = talloc_array(mem_ctx, struct mapi_SPropValue, num_props);
621
 
                mapi_lpProps.cValues = num_props;
622
 
                for (i = 0; i < num_props; i++) {
623
 
                        cast_mapi_SPropValue((TALLOC_CTX *)mapi_lpProps.lpProps,
624
 
                                              &(mapi_lpProps.lpProps[i]), &(original_props[i]));
625
 
                }
626
 
        }
627
 
 
628
 
        /* ocpf_write_init(ocpf_context_id, fid); */
629
 
        ocpf_clear_props(ocpf_context_id);
630
 
        ocpf_write_init(ocpf_context_id, 0);
631
 
        ocpf_write_auto(ocpf_context_id, NULL, &mapi_lpProps);
632
 
        ocpf_write_commit(ocpf_context_id);
633
 
        ocpf_del_context(ocpf_context_id);
634
 
        
635
 
        talloc_free(mem_ctx);
636
 
 
637
 
        return MAPISTORE_SUCCESS;
638
 
}
639
 
 
640
 
/**
641
 
   \details Create a folder in the fsocpf backend
642
 
   
643
 
   \param private_data pointer to the current fsocpf context
644
 
 
645
 
   \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE_ERROR
646
 
 */
647
 
static enum MAPISTORE_ERROR fsocpf_op_mkdir(void *private_data,
648
 
                                            const char *_parent_uri,
649
 
                                            const char *folder_name,
650
 
                                            const char *folder_desc,
651
 
                                            enum FOLDER_TYPE folder_type,
652
 
                                            char **folder_uri)
653
 
{
654
 
        enum MAPISTORE_ERROR            retval;
655
 
        struct SRow                     aRow;
656
 
        TALLOC_CTX                      *mem_ctx;
657
 
        struct fsocpf_context           *fsocpf_ctx = (struct fsocpf_context *)private_data;
658
 
        struct fsocpf_folder            *folder;
659
 
        const char                      *parent_uri;
660
 
        char                            *newfolder;
661
 
        char                            *dummy_uri;
662
 
        struct fsocpf_folder_list       *newel;
663
 
        DIR                             *dir;
664
 
        int                             ret;
665
 
 
666
 
        /* Sanity checks */
667
 
        MAPISTORE_RETVAL_IF(!fsocpf_ctx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
668
 
        MAPISTORE_RETVAL_IF(!_parent_uri, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
669
 
        MAPISTORE_RETVAL_IF(!folder_name, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
670
 
        MAPISTORE_RETVAL_IF(!folder_uri, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
671
 
 
672
 
        MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, MSTORE_SINGLE_MSG, "");
673
 
 
674
 
        /* Step 0. Check if it already exists */
675
 
        retval = mapistore_strip_ns_from_uri(_parent_uri, &parent_uri);
676
 
        MAPISTORE_RETVAL_IF(retval, retval, NULL);
677
 
 
678
 
        if (fsocpf_op_get_uri_by_name(private_data, parent_uri, folder_name, &dummy_uri) == MAPISTORE_SUCCESS) {
679
 
                /* already exists */
680
 
                talloc_free(dummy_uri);
681
 
                MSTORE_DEBUG_ERROR(MSTORE_LEVEL_INFO, "Cannot create folder '%s' in directory'%s', that name already exists\n", folder_name, parent_uri);
682
 
                return MAPISTORE_ERR_EXIST;
683
 
        }
684
 
 
685
 
        /* Step 1. Search for the parent fid */
686
 
        folder = fsocpf_find_folder(fsocpf_ctx, parent_uri);
687
 
        if (!folder) {
688
 
                MSTORE_DEBUG_ERROR(MSTORE_LEVEL_CRITICAL, "Parent context not found for folder '%s'\n", parent_uri);
689
 
                return MAPISTORE_ERR_NO_DIRECTORY;
690
 
        }
691
 
 
692
 
        mem_ctx = talloc_named(NULL, 0, __FUNCTION__);
693
 
 
694
 
        /* Step 2. Stringify fid and create directory */
695
 
        newfolder = talloc_asprintf(mem_ctx, "%s/%s", folder->uri, folder_name);
696
 
        ret = mkdir(newfolder, 0700);
697
 
        if (ret) {
698
 
                MSTORE_DEBUG_ERROR(MSTORE_LEVEL_CRITICAL, "mkdir failed: %s\n", strerror(errno));
699
 
                talloc_free(mem_ctx);
700
 
                return MAPISTORE_ERROR;
701
 
        }
702
 
        dir = opendir(newfolder);
703
 
        
704
 
        /* Step 3. Add this folder to the list of ones we know about */
705
 
        newel = fsocpf_folder_list_element_init((TALLOC_CTX *)fsocpf_ctx, newfolder, dir);
706
 
        MAPISTORE_RETVAL_IF(!newel, MAPISTORE_ERR_NO_MEMORY, mem_ctx);
707
 
 
708
 
        DLIST_ADD_END(fsocpf_ctx->folders, newel, struct fsocpf_folder_list *);
709
 
        MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, "Element added to the list '%s'\n", folder_name);
710
 
 
711
 
        /* Step 4. Set the properties on the folder */
712
 
 
713
 
        if (folder_desc) {
714
 
                aRow.lpProps = talloc_array(mem_ctx, struct SPropValue, 3);
715
 
                aRow.cValues = 2;
716
 
                aRow.lpProps[0].ulPropTag = PidTagDisplayName;
717
 
                aRow.lpProps[0].value.lpszW = folder_name;
718
 
                aRow.lpProps[1].ulPropTag = PidTagComment;
719
 
                aRow.lpProps[1].value.lpszW = folder_desc;
720
 
        } else {
721
 
                aRow.lpProps = talloc_array(mem_ctx, struct SPropValue, 2);
722
 
                aRow.cValues = 1;
723
 
                aRow.lpProps[0].ulPropTag = PidTagDisplayName;
724
 
                aRow.lpProps[0].value.lpszW = folder_name;
725
 
        }
726
 
 
727
 
        retval = fsocpf_set_folder_props(newfolder, &aRow);
728
 
 
729
 
        /* Step 5. Generate the URI for the new created folder */
730
 
        *folder_uri = talloc_asprintf((TALLOC_CTX *)fsocpf_ctx, "fsocpf://%s", newfolder);
731
 
 
732
 
        talloc_free(aRow.lpProps);
733
 
        talloc_free(newfolder);
734
 
        talloc_free(mem_ctx);
735
 
 
736
 
        return retval;
737
 
}
738
 
 
739
 
 
740
 
/**
741
 
   \details Delete a folder from the fsocpf backend
742
 
 
743
 
   \param private_data pointer to the current fsocpf context
744
 
   \param parent_uri the URI for the parent of the folder to delete
745
 
   \param folder_uri the URI for the folder to delete
746
 
 
747
 
   \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE_ERROR
748
 
 */
749
 
/* FIXME: there's no check to ensure parent_uri is the folder_uri parent ... */
750
 
static enum MAPISTORE_ERROR fsocpf_op_rmdir(void *private_data, const char *parent_uri, const char *folder_uri)
751
 
{
752
 
        struct fsocpf_context           *fsocpf_ctx = (struct fsocpf_context *)private_data;
753
 
        struct fsocpf_folder            *parent;
754
 
        struct fsocpf_folder            *folder;
755
 
        const char                      *folder_path = NULL;
756
 
        char                            *propertiespath;
757
 
        TALLOC_CTX                      *mem_ctx;
758
 
        int                             ret;
759
 
        struct fsocpf_folder_list       *el;
760
 
 
761
 
        /* Sanity checks */
762
 
        MAPISTORE_RETVAL_IF(!fsocpf_ctx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
763
 
        MAPISTORE_RETVAL_IF(!parent_uri, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
764
 
        MAPISTORE_RETVAL_IF(!folder_uri, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
765
 
 
766
 
        if (mapistore_strip_ns_from_uri(folder_uri, &folder_path) != MAPISTORE_SUCCESS) {
767
 
                MSTORE_DEBUG_INFO(MSTORE_LEVEL_CRITICAL, "misformed folder_uri: %s\n", folder_uri);
768
 
                return MAPISTORE_ERR_INVALID_PARAMETER;
769
 
        }
770
 
        MSTORE_DEBUG_INFO(MSTORE_LEVEL_LOW, "Deleting %s from %s\n", folder_path, parent_uri);
771
 
 
772
 
        /* Step 1. Search for the parent fid */
773
 
        parent = fsocpf_find_folder(fsocpf_ctx, parent_uri);
774
 
        MAPISTORE_RETVAL_IF(!parent, MAPISTORE_ERR_NO_DIRECTORY, NULL);
775
 
 
776
 
        /* Step 2. Search for the folder element */
777
 
        folder = fsocpf_find_folder(fsocpf_ctx, folder_path);
778
 
        MAPISTORE_RETVAL_IF(!folder, MAPISTORE_ERR_NO_DIRECTORY, NULL);
779
 
 
780
 
        mem_ctx = talloc_named(NULL, 0, __FUNCTION__);
781
 
 
782
 
        /* Step 3. Remove .properties file */
783
 
        propertiespath = talloc_asprintf(mem_ctx, "%s/.properties", folder_path);
784
 
        ret = unlink(propertiespath);
785
 
        if (ret) {
786
 
                MSTORE_DEBUG_ERROR(MSTORE_LEVEL_CRITICAL, "Unlink failed with error '%s'\n", strerror(errno));
787
 
        }
788
 
 
789
 
        /* Step 4. Delete directory */
790
 
        ret = rmdir(folder_path);
791
 
        if (ret) {
792
 
                MSTORE_DEBUG_ERROR(MSTORE_LEVEL_CRITICAL, "rmdir failed with error '%s'\n", strerror(errno));
793
 
                talloc_free(mem_ctx);
794
 
                return MAPISTORE_ERROR;
795
 
        }
796
 
        for (el = fsocpf_ctx->folders; el; el = el->next) {
797
 
                MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, "el->folder->uri: %s\n", el->folder->uri);
798
 
                if (el->folder && el->folder->uri && !strcmp(folder_path, el->folder->uri)) {
799
 
                        MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, "removing: %s\n", el->folder->uri);
800
 
                        DLIST_REMOVE(fsocpf_ctx->folders, el);
801
 
                }
802
 
        }
803
 
         
804
 
        return MAPISTORE_SUCCESS;
805
 
}
806
 
 
807
 
 
808
 
/**
809
 
   \details Open a folder from the fsocpf backend
810
 
 
811
 
   \param private_data pointer to the current fsocpf context
812
 
   \param parent_uri the parent folder URI
813
 
   \param folder_uri the URI of the folder to open
814
 
 
815
 
   \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE_ERROR
816
 
 */
817
 
/* FIXME: curdir->d_name is NOT the full path */
818
 
static enum MAPISTORE_ERROR fsocpf_op_opendir(void *private_data, const char *parent_uri, const char *folder_uri)
819
 
{
820
 
        TALLOC_CTX                      *mem_ctx;
821
 
        struct fsocpf_context           *fsocpf_ctx = (struct fsocpf_context *)private_data;
822
 
        struct fsocpf_folder            *folder;
823
 
        struct fsocpf_folder_list       *el;
824
 
        struct fsocpf_folder_list       *newel;
825
 
        struct dirent                   *curdir;
826
 
        DIR                             *dir;
827
 
        const char                      *folder_path = NULL;
828
 
        const char                      *parent_folder_path = NULL;
829
 
 
830
 
        MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, MSTORE_SINGLE_MSG, "");
831
 
 
832
 
        /* Sanity checks */
833
 
        MAPISTORE_RETVAL_IF(!fsocpf_ctx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
834
 
        MAPISTORE_RETVAL_IF(!parent_uri, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
835
 
        MAPISTORE_RETVAL_IF(!folder_uri, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
836
 
 
837
 
        if (mapistore_strip_ns_from_uri(folder_uri, &folder_path) != MAPISTORE_SUCCESS) {
838
 
                MSTORE_DEBUG_INFO(MSTORE_LEVEL_CRITICAL, "misformed folder_uri: %s\n", folder_uri);
839
 
                return MAPISTORE_ERR_INVALID_PARAMETER;
840
 
        }
841
 
        if (mapistore_strip_ns_from_uri(parent_uri, &parent_folder_path) != MAPISTORE_SUCCESS) {
842
 
                MSTORE_DEBUG_INFO(MSTORE_LEVEL_CRITICAL, "misformed parent_uri: %s\n", folder_uri);
843
 
                return MAPISTORE_ERR_INVALID_PARAMETER;
844
 
        }
845
 
 
846
 
        /* Step 0. If fid equals top folder fid, it is already open */
847
 
        MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, "Have context uri %s, looking for %s\n", fsocpf_ctx->uri, folder_path);
848
 
        if (!strcmp(fsocpf_ctx->uri, folder_path)) {
849
 
                /* If we access it for the first time, just add an entry to the folder list */
850
 
                if (!fsocpf_ctx->folders) {
851
 
                        el = fsocpf_folder_list_element_init((TALLOC_CTX *)fsocpf_ctx, fsocpf_ctx->uri, fsocpf_ctx->dir);
852
 
                        MAPISTORE_RETVAL_IF(!el, MAPISTORE_ERR_NO_MEMORY, NULL);
853
 
 
854
 
                        DLIST_ADD_END(fsocpf_ctx->folders, el, struct fsocpf_folder_list *);
855
 
                        MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, "Folder added to the list '%s'\n", el->folder->uri);
856
 
                }
857
 
 
858
 
                folder = fsocpf_find_folder(fsocpf_ctx, folder_path);
859
 
                MAPISTORE_RETVAL_IF(!folder, MAPISTORE_ERR_NO_DIRECTORY, NULL);
860
 
 
861
 
                return MAPISTORE_SUCCESS;
862
 
        } else {
863
 
                /* Step 1. Search for the parent fid */
864
 
                folder = fsocpf_find_folder(fsocpf_ctx, parent_folder_path);
865
 
                MAPISTORE_RETVAL_IF(!folder, MAPISTORE_ERR_NO_DIRECTORY, NULL);
866
 
        }
867
 
 
868
 
        mem_ctx = talloc_named(NULL, 0, __FUNCTION__);
869
 
 
870
 
        /* Read the directory and search for the fid to open */
871
 
        MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, "Looking for '%s'\n", folder_path);
872
 
        rewinddir(folder->dir);
873
 
        errno = 0;
874
 
        {
875
 
                int i = 0;
876
 
                while ((curdir = readdir(folder->dir)) != NULL) {
877
 
                        MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, "[%d]: readdir: %s\n", i, curdir->d_name);
878
 
                        i++;
879
 
                        if (curdir->d_name && !strcmp(curdir->d_name, folder_path)) {
880
 
                                dir = opendir(folder_path);
881
 
                                MAPISTORE_RETVAL_IF(!dir, MAPISTORE_ERR_CONTEXT_FAILED, mem_ctx);
882
 
 
883
 
                                MSTORE_DEBUG_INFO(MSTORE_LEVEL_PEDANTIC, "%s\n", "Folder found");
884
 
 
885
 
                                newel = fsocpf_folder_list_element_init((TALLOC_CTX *)fsocpf_ctx, folder_path, dir);
886
 
                                MAPISTORE_RETVAL_IF(!newel, MAPISTORE_ERR_NO_MEMORY, mem_ctx);
887
 
 
888
 
                                DLIST_ADD_END(fsocpf_ctx->folders, newel, struct fsocpf_folder_list *);
889
 
                                MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, "Element added to the list: %s\n", folder_path);
890
 
                        }
891
 
                }
892
 
        }
893
 
 
894
 
        MSTORE_DEBUG_INFO(MSTORE_LEVEL_PEDANTIC, "errno = %d\n", errno);
895
 
 
896
 
        rewinddir(folder->dir);
897
 
        talloc_free(mem_ctx);
898
 
                
899
 
        return MAPISTORE_SUCCESS;
900
 
}
901
 
 
902
 
 
903
 
/**
904
 
   \details Close a folder from the fsocpf backend
905
 
 
906
 
   \param private_data pointer to the current fsocpf context
907
 
   \param folder_uri the URI of the folder to close
908
 
 
909
 
   \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE_ERROR
910
 
 */
911
 
static enum MAPISTORE_ERROR fsocpf_op_closedir(void *private_data, const char *folder_uri)
912
 
{
913
 
        struct fsocpf_context   *fsocpf_ctx = (struct fsocpf_context *)private_data;
914
 
 
915
 
        if (!fsocpf_ctx) {
916
 
                return MAPISTORE_ERROR;
917
 
        }
918
 
        /* TODO: this probably should be implemented */
919
 
 
920
 
        return MAPISTORE_SUCCESS;
921
 
}
922
 
 
923
 
 
924
 
/**
925
 
   \details Read directory content from the fsocpf backend
926
 
 
927
 
   \param private_data pointer to the current fsocpf context
928
 
   \param folder_uri pointer to the URI of the folder
929
 
   \param table_type the type of table to read
930
 
   \param RowCount pointer to the number of rows to return
931
 
 
932
 
   \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE_ERROR
933
 
 */
934
 
static enum MAPISTORE_ERROR fsocpf_op_readdir_count(void *private_data, 
935
 
                                                    const char *folder_uri,
936
 
                                                    enum MAPISTORE_TABLE_TYPE table_type,
937
 
                                                    uint32_t *RowCount)
938
 
{
939
 
        struct fsocpf_context           *fsocpf_ctx = (struct fsocpf_context *)private_data;
940
 
        struct fsocpf_folder            *folder;
941
 
        struct fsocpf_folder_list       *el;
942
 
        struct dirent                   *curdir;
943
 
        const char                      *folder_path = NULL;
944
 
 
945
 
        MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, MSTORE_SINGLE_MSG, "");
946
 
 
947
 
        /* Sanity checks */
948
 
        MAPISTORE_RETVAL_IF(!fsocpf_ctx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
949
 
        MAPISTORE_RETVAL_IF(!folder_uri, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
950
 
        MAPISTORE_RETVAL_IF(!RowCount, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
951
 
 
952
 
        if (mapistore_strip_ns_from_uri(folder_uri, &folder_path) != MAPISTORE_SUCCESS) {
953
 
                /* assume its already stripped */
954
 
                folder_path = folder_uri;
955
 
        }
956
 
 
957
 
        if (!strcmp(fsocpf_ctx->uri, folder_path)) {
958
 
                /* If we access it for the first time, just add an entry to the folder list */
959
 
                if (!fsocpf_ctx->folders) {
960
 
                        el = fsocpf_folder_list_element_init((TALLOC_CTX *)fsocpf_ctx, fsocpf_ctx->uri, fsocpf_ctx->dir);
961
 
                        MAPISTORE_RETVAL_IF(!el, MAPISTORE_ERR_NO_MEMORY, NULL);
962
 
 
963
 
                        DLIST_ADD_END(fsocpf_ctx->folders, el, struct fsocpf_folder_list *);
964
 
                        MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, "Element added to the list '%s'\n", el->folder->uri);
965
 
                }
966
 
        }
967
 
 
968
 
        /* Search for the fid fsocpf_folder entry */
969
 
        folder = fsocpf_find_folder(fsocpf_ctx, folder_path);
970
 
        MAPISTORE_RETVAL_IF(!folder, MAPISTORE_ERR_NO_DIRECTORY, NULL);
971
 
 
972
 
        switch (table_type) {
973
 
        case MAPISTORE_FOLDER_TABLE:
974
 
                rewinddir(folder->dir);
975
 
                errno = 0;
976
 
                *RowCount = 0;
977
 
                while ((curdir = readdir(folder->dir)) != NULL) {
978
 
                        if (curdir->d_name && curdir->d_type == DT_DIR &&
979
 
                            strcmp(curdir->d_name, ".") && strcmp(curdir->d_name, "..")) {
980
 
                                MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, "Adding folder entry to RowCount: '%s'\n", curdir->d_name);
981
 
                                *RowCount += 1;
982
 
                        }
983
 
                }
984
 
                break;
985
 
        case MAPISTORE_MESSAGE_TABLE:
986
 
                rewinddir(folder->dir);
987
 
                errno = 0;
988
 
                *RowCount = 0;
989
 
                while ((curdir = readdir(folder->dir)) != NULL) {
990
 
                        if (curdir->d_name && curdir->d_type == DT_REG &&
991
 
                            strcmp(curdir->d_name, ".properties")) {
992
 
                                MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, "Adding message entry to RowCount: '%s'\n", curdir->d_name);
993
 
                                *RowCount += 1;
994
 
                        }
995
 
                }
996
 
                break;
997
 
        default:
998
 
                break;
999
 
        }
1000
 
 
1001
 
        return MAPISTORE_SUCCESS;
1002
 
}
1003
 
 
1004
 
 
1005
 
/* FIXME: We don't use FID anymore, nor do backends should know about them */
1006
 
static enum MAPISTORE_ERROR fsocpf_get_property_from_folder_table(struct fsocpf_folder *folder,
1007
 
                                                                  uint32_t pos,
1008
 
                                                                  enum MAPITAGS proptag,
1009
 
                                                                  void **data)
1010
 
{
1011
 
        int                     ret;
1012
 
        struct dirent           *curdir;
1013
 
        uint32_t                counter = 0;
1014
 
        char                    *folderID = NULL;
1015
 
        char                    *propfile;
1016
 
        uint32_t                cValues = 0;
1017
 
        struct SPropValue       *lpProps;
1018
 
        uint32_t                ocpf_context_id;
1019
 
 
1020
 
        MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, MSTORE_SINGLE_MSG, "");
1021
 
 
1022
 
        /* Sanity checks */
1023
 
        MAPISTORE_RETVAL_IF(!folder, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
1024
 
        MAPISTORE_RETVAL_IF(!data, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
1025
 
 
1026
 
        /* Set dir listing to current position */
1027
 
        rewinddir(folder->dir);
1028
 
        errno = 0;
1029
 
        while ((curdir = readdir(folder->dir)) != NULL) {
1030
 
                if (curdir->d_name && curdir->d_type == DT_DIR &&
1031
 
                    strcmp(curdir->d_name, ".") && strcmp(curdir->d_name, "..") &&
1032
 
                    counter == pos) {
1033
 
                        folderID = talloc_strdup(folder, curdir->d_name);
1034
 
                        break;
1035
 
                }
1036
 
                if (strcmp(curdir->d_name, ".") && strcmp(curdir->d_name, "..") && 
1037
 
                    (curdir->d_type == DT_DIR)) {
1038
 
                        counter++;
1039
 
                }
1040
 
        }
1041
 
 
1042
 
        MAPISTORE_RETVAL_IF(!folderID, MAPISTORE_ERR_NOT_FOUND, NULL);
1043
 
 
1044
 
        /* Otherwise opens .properties file with ocpf for fid entry */
1045
 
        propfile = talloc_asprintf(folder, "%s/%s/.properties", folder->uri, folderID);
1046
 
        talloc_free(folderID);
1047
 
 
1048
 
        ret = ocpf_new_context(propfile, &ocpf_context_id, OCPF_FLAGS_READ);
1049
 
        talloc_free(propfile);
1050
 
 
1051
 
        /* process the file */
1052
 
        ret = ocpf_parse(ocpf_context_id);
1053
 
 
1054
 
        ocpf_server_set_SPropValue(folder, ocpf_context_id);
1055
 
        lpProps = ocpf_get_SPropValue(ocpf_context_id, &cValues);
1056
 
 
1057
 
        /* FIXME: We need to find a proper way to handle this (for all types) */
1058
 
        talloc_steal(folder, lpProps);
1059
 
 
1060
 
        *data = (void *) get_SPropValue(lpProps, proptag);
1061
 
        if (((proptag & 0xFFFF) == PT_STRING8) || ((proptag & 0xFFFF) == PT_UNICODE)) {
1062
 
                /* Hack around PT_STRING8 and PT_UNICODE */
1063
 
                if (*data == NULL && ((proptag & 0xFFFF) == PT_STRING8)) {
1064
 
                  *data = (void *) get_SPropValue(lpProps, (enum MAPITAGS)(((int)proptag & 0xFFFF0000) + PT_UNICODE));
1065
 
                } else if (*data == NULL && (proptag & 0xFFFF) == PT_UNICODE) {
1066
 
                  *data = (void *) get_SPropValue(lpProps, (enum MAPITAGS)((int)(proptag & 0xFFFF0000) + PT_STRING8));
1067
 
                }
1068
 
                *data = talloc_strdup(folder, (char *)*data);
1069
 
        }
1070
 
 
1071
 
        if (*data == NULL) {
1072
 
                ret = ocpf_del_context(ocpf_context_id);
1073
 
                return MAPISTORE_ERR_NOT_FOUND;
1074
 
        }
1075
 
 
1076
 
        ret = ocpf_del_context(ocpf_context_id);
1077
 
        return MAPISTORE_SUCCESS;
1078
 
}
1079
 
 
1080
 
 
1081
 
static enum MAPISTORE_ERROR fsocpf_get_property_from_message_table(struct fsocpf_folder *folder,
1082
 
                                                                   uint32_t pos,
1083
 
                                                                   enum MAPITAGS proptag,
1084
 
                                                                   void **data)
1085
 
{
1086
 
        int                     ret;
1087
 
        struct dirent           *curdir;
1088
 
        uint32_t                counter = 0;
1089
 
        char                    *messageID = NULL;
1090
 
        char                    *propfile;
1091
 
        uint32_t                cValues = 0;
1092
 
        struct SPropValue       *lpProps;
1093
 
        uint32_t                ocpf_context_id;
1094
 
 
1095
 
        MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, MSTORE_SINGLE_MSG, "");
1096
 
 
1097
 
        /* Sanity checks */
1098
 
        MAPISTORE_RETVAL_IF(!folder, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
1099
 
        MAPISTORE_RETVAL_IF(!data, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
1100
 
 
1101
 
        /* Set dir listing to current position */
1102
 
        rewinddir(folder->dir);
1103
 
        errno = 0;
1104
 
        while ((curdir = readdir(folder->dir)) != NULL) {
1105
 
                if (curdir->d_name && curdir->d_type == DT_REG &&
1106
 
                    strcmp(curdir->d_name, ".properties") && counter == pos) {
1107
 
                        messageID = talloc_strdup(folder, curdir->d_name);
1108
 
                        break;
1109
 
                }
1110
 
                if (strcmp(curdir->d_name, ".properties") && 
1111
 
                    strcmp(curdir->d_name, ".") &&
1112
 
                    strcmp(curdir->d_name, "..") &&
1113
 
                    (curdir->d_type == DT_REG)) {
1114
 
                        counter++;
1115
 
                }
1116
 
        }
1117
 
 
1118
 
        MAPISTORE_RETVAL_IF(!messageID, MAPISTORE_ERR_NOT_FOUND, NULL);
1119
 
 
1120
 
        /* if fid, return folder fid */
1121
 
        /* if (proptag == PR_FID) { */
1122
 
        /*      *data = (uint64_t *)&folder->fid; */
1123
 
        /*      return MAPISTORE_SUCCESS; */
1124
 
        /*   } */
1125
 
 
1126
 
        /* If mid, return curdir->d_name */
1127
 
        /* if (proptag == PR_MID) { */
1128
 
        /*      uint64_t        *mid; */
1129
 
 
1130
 
        /*      mid = talloc_zero(folder, uint64_t); */
1131
 
        /*      *mid = strtoull(messageID, NULL, 16); */
1132
 
        /*      talloc_free(messageID); */
1133
 
        /*      *data = (uint64_t *)mid; */
1134
 
        /*      return MAPISTORE_SUCCESS; */
1135
 
        /* } */
1136
 
 
1137
 
        /* Otherwise opens curdir->d_name file with ocpf */
1138
 
        propfile = talloc_asprintf(folder, "%s/%s", folder->uri, messageID);
1139
 
        talloc_free(messageID);
1140
 
 
1141
 
        ret = ocpf_new_context(propfile, &ocpf_context_id, OCPF_FLAGS_READ);
1142
 
        talloc_free(propfile);
1143
 
 
1144
 
        /* process the file */
1145
 
        ret = ocpf_parse(ocpf_context_id);
1146
 
 
1147
 
        ocpf_server_set_SPropValue(folder, ocpf_context_id);
1148
 
        lpProps = ocpf_get_SPropValue(ocpf_context_id, &cValues);
1149
 
 
1150
 
        /* FIXME: We need to find a proper way to handle this (for all types) */
1151
 
        talloc_steal(folder, lpProps);
1152
 
 
1153
 
        *data = (void *) get_SPropValue(lpProps, proptag);
1154
 
        if (((proptag & 0xFFFF) == PT_STRING8) || ((proptag & 0xFFFF) == PT_UNICODE)) {
1155
 
                /* Hack around PT_STRING8 and PT_UNICODE */
1156
 
                if (*data == NULL && ((proptag & 0xFFFF) == PT_STRING8)) {
1157
 
                  *data = (void *) get_SPropValue(lpProps, (enum MAPITAGS)(((int)proptag & 0xFFFF0000) + PT_UNICODE));
1158
 
                } else if (*data == NULL && (proptag & 0xFFFF) == PT_UNICODE) {
1159
 
                  *data = (void *) get_SPropValue(lpProps, (enum MAPITAGS)(((int)proptag & 0xFFFF0000) + PT_STRING8));
1160
 
                }
1161
 
                *data = talloc_strdup(folder, (char *)*data);
1162
 
        }
1163
 
 
1164
 
        if (*data == NULL) {
1165
 
                ocpf_del_context(ocpf_context_id);
1166
 
                return MAPISTORE_ERR_NOT_FOUND;
1167
 
        }
1168
 
 
1169
 
        ocpf_del_context(ocpf_context_id);
1170
 
        return MAPISTORE_SUCCESS;       
1171
 
}
1172
 
 
1173
 
 
1174
 
static enum MAPISTORE_ERROR fsocpf_op_get_table_property(void *private_data,
1175
 
                                                         const char *folder_uri,
1176
 
                                                         enum MAPISTORE_TABLE_TYPE table_type,
1177
 
                                                         uint32_t pos,
1178
 
                                                         enum MAPITAGS proptag,
1179
 
                                                         void **data)
1180
 
{
1181
 
        struct fsocpf_context           *fsocpf_ctx = (struct fsocpf_context *)private_data;
1182
 
        struct fsocpf_folder_list       *el;
1183
 
        struct fsocpf_folder            *folder;
1184
 
        enum MAPISTORE_ERROR            retval = MAPISTORE_SUCCESS;
1185
 
 
1186
 
        MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, MSTORE_SINGLE_MSG, "");
1187
 
 
1188
 
        /* Sanity checks */
1189
 
        MAPISTORE_RETVAL_IF(!fsocpf_ctx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
1190
 
        MAPISTORE_RETVAL_IF(!folder_uri, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
1191
 
        MAPISTORE_RETVAL_IF(!data, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
1192
 
 
1193
 
        if (!strcmp(fsocpf_ctx->uri, folder_uri)) {
1194
 
                /* If we access it for the first time, just add an entry to the folder list */
1195
 
                if (!fsocpf_ctx->folders || !fsocpf_ctx->folders->folder) {
1196
 
                        el = fsocpf_folder_list_element_init((TALLOC_CTX *)fsocpf_ctx, fsocpf_ctx->uri, fsocpf_ctx->dir);
1197
 
                        MAPISTORE_RETVAL_IF(!el, MAPISTORE_ERR_NO_MEMORY, NULL);
1198
 
 
1199
 
                        DLIST_ADD_END(fsocpf_ctx->folders, el, struct fsocpf_folder_list *);
1200
 
                        MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, "Element added to the list '%s'\n", el->folder->uri);
1201
 
                }
1202
 
        }
1203
 
 
1204
 
        /* Search for the fid fsocpf_folder entry */
1205
 
        folder = fsocpf_find_folder(fsocpf_ctx, folder_uri);
1206
 
        MAPISTORE_RETVAL_IF(!folder, MAPISTORE_ERR_NO_DIRECTORY, NULL);
1207
 
 
1208
 
        switch (table_type) {
1209
 
        case MAPISTORE_FOLDER_TABLE:
1210
 
                retval = fsocpf_get_property_from_folder_table(folder, pos, proptag, data);
1211
 
                break;
1212
 
        case MAPISTORE_MESSAGE_TABLE:
1213
 
                retval = fsocpf_get_property_from_message_table(folder, pos, proptag, data);
1214
 
                break;
1215
 
        default:
1216
 
                break;
1217
 
        }
1218
 
 
1219
 
        return retval;
1220
 
}
1221
 
 
1222
 
 
1223
 
static enum MAPISTORE_ERROR fsocpf_op_openmessage(void *private_data,
1224
 
                                                  const char *folder_uri,
1225
 
                                                  const char *message_uri,
1226
 
                                                  struct mapistore_message *msg)
1227
 
{
1228
 
        int                             ret;
1229
 
        enum MAPISTATUS                 retval;
1230
 
        struct fsocpf_context           *fsocpf_ctx = (struct fsocpf_context *)private_data;
1231
 
        struct fsocpf_message_list      *el;
1232
 
        struct fsocpf_message           *message;
1233
 
        struct fsocpf_folder            *folder;
1234
 
        uint32_t                        ocpf_context_id;
1235
 
 
1236
 
        MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, MSTORE_SINGLE_MSG, "");
1237
 
 
1238
 
        /* Sanity checks */
1239
 
        MAPISTORE_RETVAL_IF(!fsocpf_ctx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
1240
 
        MAPISTORE_RETVAL_IF(!folder_uri, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
1241
 
        MAPISTORE_RETVAL_IF(!message_uri, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
1242
 
        MAPISTORE_RETVAL_IF(!msg, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
1243
 
 
1244
 
        /* Search for the mid fsocpf_message entry */
1245
 
        message = fsocpf_find_message(fsocpf_ctx, message_uri);
1246
 
        if (message) {
1247
 
                MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, "Message already %s\n", "opened");
1248
 
                msg->properties = talloc_zero(fsocpf_ctx, struct SRow);
1249
 
                MAPISTORE_RETVAL_IF(!msg->properties, MAPISTORE_ERR_NO_MEMORY, NULL);
1250
 
 
1251
 
                retval = ocpf_get_recipients(message, message->ocpf_context_id, &msg->recipients);
1252
 
                msg->properties->lpProps = ocpf_get_SPropValue(message->ocpf_context_id, 
1253
 
                                                               &msg->properties->cValues);
1254
 
                return MAPISTORE_SUCCESS;
1255
 
        }
1256
 
 
1257
 
        /* Search for the fid fsocpf_folder entry */
1258
 
        folder = fsocpf_find_folder(fsocpf_ctx, folder_uri);
1259
 
        MAPISTORE_RETVAL_IF(!folder, MAPISTORE_ERR_NOT_FOUND, NULL);
1260
 
 
1261
 
        MSTORE_DEBUG_INFO(MSTORE_LEVEL_INFO, "Message %s is stored within %s\n", message_uri, folder->uri);
1262
 
 
1263
 
        /* Trying to open and map the file with OCPF */
1264
 
        ret = ocpf_new_context(message_uri, &ocpf_context_id, OCPF_FLAGS_READ);
1265
 
        ret = ocpf_parse(ocpf_context_id);
1266
 
        MAPISTORE_RETVAL_IF(ret, MAPISTORE_ERR_CONTEXT_FAILED, NULL);
1267
 
 
1268
 
        el = fsocpf_message_list_element_init((TALLOC_CTX *)fsocpf_ctx, folder_uri, message_uri, ocpf_context_id);
1269
 
        MAPISTORE_RETVAL_IF(!el, MAPISTORE_ERR_NO_MEMORY, NULL);
1270
 
 
1271
 
        DLIST_ADD_END(fsocpf_ctx->messages, el, struct fsocpf_message_list *);
1272
 
        MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, "Element added to the list '%s'\n", message_uri);
1273
 
 
1274
 
        /* Retrieve recipients from the message */
1275
 
        retval = ocpf_get_recipients(el, ocpf_context_id, &msg->recipients);
1276
 
        MAPISTORE_RETVAL_IF(retval, MAPISTORE_ERR_NOT_FOUND, NULL);
1277
 
 
1278
 
        /* Retrieve properties from the message */
1279
 
        msg->properties = talloc_zero(el, struct SRow);
1280
 
        MAPISTORE_RETVAL_IF(!msg->properties, MAPISTORE_ERR_NO_MEMORY, NULL);
1281
 
 
1282
 
        retval = ocpf_server_set_SPropValue(el, ocpf_context_id);
1283
 
        msg->properties->lpProps = ocpf_get_SPropValue(ocpf_context_id, &msg->properties->cValues);
1284
 
 
1285
 
        return MAPISTORE_SUCCESS;
1286
 
}
1287
 
 
1288
 
 
1289
 
/* FIXME: the backend should be responsible for setting the message URI / unique ID */
1290
 
/* When creating the message, the URI doesn't exist yet, this should be returned by the function */
1291
 
 
1292
 
/* Some backends will only be able to get the URI once they commit the
1293
 
 * message, we should offer the possibility for backends to register
1294
 
 * the indexing URI later and deal with a temporary URI until they
1295
 
 * come to commit/save operations 
1296
 
*/
1297
 
 
1298
 
static enum MAPISTORE_ERROR fsocpf_op_createmessage(void *private_data,
1299
 
                                                    const char *folder_uri,
1300
 
                                                    char **_message_uri,
1301
 
                                                    bool *uri_register)
1302
 
{
1303
 
        int                             ret;
1304
 
        struct fsocpf_context           *fsocpf_ctx = (struct fsocpf_context *)private_data;
1305
 
        struct fsocpf_message_list      *el;
1306
 
        struct fsocpf_folder            *folder;
1307
 
        char                            *message_uri = NULL;
1308
 
        uint32_t                        ocpf_context_id;
1309
 
 
1310
 
        MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, MSTORE_SINGLE_MSG, "");
1311
 
 
1312
 
        /* Sanity checks */
1313
 
        MAPISTORE_RETVAL_IF(!fsocpf_ctx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
1314
 
        MAPISTORE_RETVAL_IF(!folder_uri, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
1315
 
        MAPISTORE_RETVAL_IF(!message_uri, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
1316
 
        
1317
 
        /* Search for the fid fsocpf_folder entry */
1318
 
        folder = fsocpf_find_folder(fsocpf_ctx, folder_uri);
1319
 
        MAPISTORE_RETVAL_IF(!folder, MAPISTORE_ERR_NOT_FOUND, NULL);
1320
 
 
1321
 
        MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, "Message %s will be created within %s\n", message_uri, folder->uri);
1322
 
        
1323
 
        ret = ocpf_new_context(message_uri, &ocpf_context_id, OCPF_FLAGS_CREATE);
1324
 
        MAPISTORE_RETVAL_IF(ret, MAPISTORE_ERR_CONTEXT_FAILED, NULL);
1325
 
 
1326
 
        el = fsocpf_message_list_element_init((TALLOC_CTX *)fsocpf_ctx, folder_uri, message_uri, ocpf_context_id);
1327
 
        MAPISTORE_RETVAL_IF(!el, MAPISTORE_ERR_NO_MEMORY, NULL);
1328
 
 
1329
 
        DLIST_ADD_END(fsocpf_ctx->messages, el, struct fsocpf_message_list *);
1330
 
        MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, "Element added to the list '%s'\n", message_uri);
1331
 
        
1332
 
        *_message_uri = message_uri;
1333
 
        *uri_register = true;
1334
 
 
1335
 
        return MAPISTORE_SUCCESS;
1336
 
}
1337
 
 
1338
 
 
1339
 
/* FIXME: ocpf is using the fid to create the filename, we MUST offer a different mechanism
1340
 
   OR we could let backends register the message on their own. To be decided */
1341
 
static enum MAPISTORE_ERROR fsocpf_op_savechangesmessage(void *private_data,
1342
 
                                                         const char *message_uri,
1343
 
                                                         uint8_t flags)
1344
 
{
1345
 
        struct fsocpf_context           *fsocpf_ctx = (struct fsocpf_context *)private_data;
1346
 
        struct fsocpf_message           *message;
1347
 
        
1348
 
        MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, MSTORE_SINGLE_MSG, "");
1349
 
 
1350
 
        /* Sanity checks */
1351
 
        MAPISTORE_RETVAL_IF(!fsocpf_ctx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
1352
 
        MAPISTORE_RETVAL_IF(!message_uri, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
1353
 
 
1354
 
        message = fsocpf_find_message(fsocpf_ctx, message_uri);
1355
 
        if (!message || !message->ocpf_context_id) {
1356
 
                return MAPISTORE_ERR_NOT_FOUND;
1357
 
        }
1358
 
 
1359
 
        ocpf_write_init(message->ocpf_context_id, 0);
1360
 
        ocpf_write_commit(message->ocpf_context_id);
1361
 
 
1362
 
        return MAPISTORE_SUCCESS;
1363
 
}
1364
 
 
1365
 
/* FIXME: See savechangesmessage comments */
1366
 
static enum MAPISTORE_ERROR fsocpf_op_submitmessage(void *private_data,
1367
 
                                                    const char *message_uri,
1368
 
                                                    uint8_t flags)
1369
 
{
1370
 
        struct fsocpf_context           *fsocpf_ctx = (struct fsocpf_context *)private_data;
1371
 
        struct fsocpf_message           *message;
1372
 
 
1373
 
        MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, MSTORE_SINGLE_MSG, "");
1374
 
 
1375
 
        /* Sanity checks */
1376
 
        MAPISTORE_RETVAL_IF(!fsocpf_ctx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
1377
 
        MAPISTORE_RETVAL_IF(!message_uri, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
1378
 
 
1379
 
        /* This implementation is incorrect but should fit for immediate purposes */
1380
 
        message = fsocpf_find_message(fsocpf_ctx, message_uri);
1381
 
 
1382
 
        ocpf_write_init(message->ocpf_context_id, 0);
1383
 
        ocpf_write_commit(message->ocpf_context_id);
1384
 
 
1385
 
        return MAPISTORE_SUCCESS;
1386
 
}
1387
 
 
1388
 
 
1389
 
static char *fsocpf_get_recipients(TALLOC_CTX *mem_ctx, struct SRowSet *SRowSet, uint8_t recipient_class)
1390
 
{
1391
 
        char            *recipient = NULL;
1392
 
        uint32_t        i;
1393
 
 
1394
 
        for (i = 0; i < SRowSet->cRows; i++) {
1395
 
                if (SRowSet->aRow[i].lpProps[0].value.l == recipient_class) {
1396
 
                        if (!recipient) {
1397
 
                                recipient = talloc_strdup(mem_ctx, SRowSet->aRow[i].lpProps[1].value.lpszA);
1398
 
                        } else {
1399
 
                                recipient = talloc_asprintf(recipient, "%s;%s", recipient, 
1400
 
                                                            SRowSet->aRow[i].lpProps[1].value.lpszA);
1401
 
                        }
1402
 
                }
1403
 
        }
1404
 
 
1405
 
        return recipient;
1406
 
}
1407
 
 
1408
 
static enum MAPISTORE_ERROR fsocpf_op_getprops(void *private_data, 
1409
 
                                               const char *uri,
1410
 
                                               uint8_t type, 
1411
 
                                               struct SPropTagArray *SPropTagArray,
1412
 
                                               struct SRow *aRow)
1413
 
{
1414
 
        struct fsocpf_context   *fsocpf_ctx = (struct fsocpf_context *)private_data;
1415
 
        struct fsocpf_message   *message;
1416
 
        uint32_t                cValues;
1417
 
        struct SPropValue       *lpProps;
1418
 
        struct SPropValue       lpProp;
1419
 
        struct SRowSet          *SRowSet;
1420
 
        uint32_t                i;
1421
 
        uint32_t                j;
1422
 
        char                    *recip_str = NULL;
1423
 
 
1424
 
        MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, MSTORE_SINGLE_MSG, "");
1425
 
 
1426
 
        /* Sanity checks */
1427
 
        MAPISTORE_RETVAL_IF(!fsocpf_ctx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
1428
 
        MAPISTORE_RETVAL_IF(!uri, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
1429
 
        MAPISTORE_RETVAL_IF(!SPropTagArray, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
1430
 
        MAPISTORE_RETVAL_IF(!aRow, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
1431
 
 
1432
 
        switch (type) {
1433
 
        case MAPISTORE_FOLDER:
1434
 
                break;
1435
 
        case MAPISTORE_MESSAGE:
1436
 
                message = fsocpf_find_message(fsocpf_ctx, uri);
1437
 
                ocpf_server_set_SPropValue(fsocpf_ctx, message->ocpf_context_id);
1438
 
                lpProps = ocpf_get_SPropValue(message->ocpf_context_id, &cValues);
1439
 
                ocpf_get_recipients(fsocpf_ctx, message->ocpf_context_id, &SRowSet);
1440
 
 
1441
 
                ocpf_dump(message->ocpf_context_id);
1442
 
                for (i = 0; i != SPropTagArray->cValues; i++) {
1443
 
                        switch (SPropTagArray->aulPropTag[i]) {
1444
 
                        case PR_DISPLAY_TO:
1445
 
                        case PR_DISPLAY_TO_UNICODE:
1446
 
                                recip_str = fsocpf_get_recipients(fsocpf_ctx, SRowSet, OCPF_MAPI_TO);
1447
 
                                break;
1448
 
                        case PR_DISPLAY_CC:
1449
 
                        case PR_DISPLAY_CC_UNICODE:
1450
 
                                recip_str = fsocpf_get_recipients(fsocpf_ctx, SRowSet, OCPF_MAPI_CC);
1451
 
                                break;
1452
 
                        case PR_DISPLAY_BCC:
1453
 
                        case PR_DISPLAY_BCC_UNICODE:
1454
 
                                recip_str = fsocpf_get_recipients(fsocpf_ctx, SRowSet, OCPF_MAPI_BCC);
1455
 
                                break;
1456
 
                        default:
1457
 
                                for (j = 0; j != cValues; j++) {
1458
 
                                        if (SPropTagArray->aulPropTag[i] == lpProps[j].ulPropTag)  {
1459
 
                                                SRow_addprop(aRow, lpProps[j]);
1460
 
                                        }
1461
 
                                }
1462
 
                        }
1463
 
 
1464
 
                        if (recip_str) {
1465
 
                                lpProp.ulPropTag = SPropTagArray->aulPropTag[i];
1466
 
                                switch (SPropTagArray->aulPropTag[i] & 0xFFFF) {
1467
 
                                case PT_STRING8:
1468
 
                                        lpProp.value.lpszA = talloc_strdup(aRow, recip_str);
1469
 
                                        break;
1470
 
                                case PT_UNICODE:
1471
 
                                        lpProp.value.lpszW = talloc_strdup(aRow, recip_str);
1472
 
                                        break;
1473
 
                                }
1474
 
                                SRow_addprop(aRow, lpProp);
1475
 
                                talloc_free(recip_str);
1476
 
                                recip_str = NULL;
1477
 
                        }
1478
 
                }
1479
 
        }
1480
 
 
1481
 
        return MAPISTORE_SUCCESS;
1482
 
}
1483
 
 
1484
 
 
1485
 
static enum MAPISTORE_ERROR fsocpf_op_setprops(void *private_data,
1486
 
                                               const char *uri,
1487
 
                                               uint8_t type,
1488
 
                                               struct SRow *aRow)
1489
 
{
1490
 
        struct fsocpf_context   *fsocpf_ctx = (struct fsocpf_context *) private_data;
1491
 
        struct fsocpf_folder    *folder;
1492
 
        struct fsocpf_message   *message;
1493
 
        uint32_t                i;
1494
 
        const char              *path;
1495
 
        enum MAPISTORE_ERROR    retval = MAPISTORE_SUCCESS;
1496
 
 
1497
 
        MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, MSTORE_SINGLE_MSG, "");
1498
 
 
1499
 
        /* Sanity checks */
1500
 
        MAPISTORE_RETVAL_IF(!fsocpf_ctx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
1501
 
        MAPISTORE_RETVAL_IF(!uri, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
1502
 
        MAPISTORE_RETVAL_IF(!aRow, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
1503
 
 
1504
 
        if (mapistore_strip_ns_from_uri(uri, &path) != MAPISTORE_SUCCESS) {
1505
 
                MSTORE_DEBUG_INFO(MSTORE_LEVEL_CRITICAL, "misformed uri: %s\n", uri);
1506
 
                return MAPISTORE_ERR_INVALID_PARAMETER;
1507
 
        }
1508
 
        MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, "uri: %s, path: %s\n", uri, path);
1509
 
 
1510
 
        switch (type) {
1511
 
        case MAPISTORE_FOLDER:
1512
 
                folder = fsocpf_find_folder(fsocpf_ctx, path);
1513
 
                MAPISTORE_RETVAL_IF(!folder, MAPISTORE_ERR_NOT_FOUND, NULL);
1514
 
                retval = fsocpf_set_folder_props(folder->uri, aRow);
1515
 
                break;
1516
 
        case MAPISTORE_MESSAGE:
1517
 
                message = fsocpf_find_message(fsocpf_ctx, path);
1518
 
                MAPISTORE_RETVAL_IF(!message, MAPISTORE_ERR_NOT_FOUND, NULL);
1519
 
                for (i = 0; i < aRow->cValues; i++) {
1520
 
                        if (aRow->lpProps[i].ulPropTag == PidTagMessageClass) {
1521
 
                                ocpf_server_set_type(message->ocpf_context_id, aRow->lpProps[i].value.lpszW);
1522
 
                        }
1523
 
                        ocpf_server_add_SPropValue(message->ocpf_context_id, &aRow->lpProps[i]);
1524
 
                }
1525
 
                break;
1526
 
        }
1527
 
 
1528
 
        return retval;
1529
 
}
1530
 
 
1531
 
/* TODO: this looks like it probably does not handle soft deletion */
1532
 
static enum MAPISTORE_ERROR fsocpf_op_deletemessage(void *private_data,
1533
 
                                                    const char *message_uri,
1534
 
                                                    enum MAPISTORE_DELETION_TYPE deletion_type)
1535
 
{
1536
 
        int                             ret;
1537
 
        struct fsocpf_context           *fsocpf_ctx = (struct fsocpf_context *)private_data;
1538
 
        struct fsocpf_message           *message;
1539
 
        
1540
 
        DEBUG(5, ("[%s:%d]\n", __FUNCTION__, __LINE__));
1541
 
 
1542
 
        message = fsocpf_find_message(fsocpf_ctx, message_uri);
1543
 
        MAPISTORE_RETVAL_IF(!message, MAPISTORE_ERR_NOT_FOUND, NULL);
1544
 
 
1545
 
        ret = unlink(message->uri);
1546
 
        MAPISTORE_RETVAL_IF(ret, MAPISTORE_ERROR, NULL);
1547
 
 
1548
 
        return MAPISTORE_SUCCESS;
1549
 
}
1550
 
 
1551
 
/**
1552
 
   \details Entry point for mapistore FSOCPF backend
1553
 
 
1554
 
   \return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
1555
 
 */
1556
 
enum MAPISTORE_ERROR mapistore_init_backend(void)
1557
 
{
1558
 
        struct mapistore_backend        backend;
1559
 
        enum MAPISTORE_ERROR            retval;
1560
 
 
1561
 
        /* Initialize backend with defaults */
1562
 
        retval = mapistore_backend_init_defaults(&backend);
1563
 
        MAPISTORE_RETVAL_IF(retval, retval, NULL);
1564
 
 
1565
 
        /* Fill in our name */
1566
 
        backend.name = "fsocpf";
1567
 
        backend.description = "mapistore filesystem + ocpf backend";
1568
 
        backend.uri_namespace = "fsocpf://";
1569
 
 
1570
 
        /* Fill in all the operations */
1571
 
        backend.init = fsocpf_init;
1572
 
        backend.create_context = fsocpf_create_context;
1573
 
        backend.delete_context = fsocpf_delete_context;
1574
 
        backend.release_record = fsocpf_release_record;
1575
 
        backend.get_path = fsocpf_get_path;
1576
 
        backend.op_mkdir = fsocpf_op_mkdir;
1577
 
        backend.op_rmdir = fsocpf_op_rmdir;
1578
 
        backend.op_opendir = fsocpf_op_opendir;
1579
 
        backend.op_closedir = fsocpf_op_closedir;
1580
 
        backend.op_readdir_count = fsocpf_op_readdir_count;
1581
 
        backend.op_get_table_property = fsocpf_op_get_table_property;
1582
 
        backend.op_openmessage = fsocpf_op_openmessage;
1583
 
        backend.op_createmessage = fsocpf_op_createmessage;
1584
 
        backend.op_savechangesmessage = fsocpf_op_savechangesmessage;
1585
 
        backend.op_submitmessage = fsocpf_op_submitmessage;
1586
 
        backend.op_getprops = fsocpf_op_getprops;
1587
 
        backend.op_get_uri_by_name = fsocpf_op_get_uri_by_name;
1588
 
        backend.op_setprops = fsocpf_op_setprops;
1589
 
        backend.op_deletemessage = fsocpf_op_deletemessage;
1590
 
 
1591
 
        /* Fill in admin operations on mapistore database/store */
1592
 
        backend.op_db_create_uri = fsocpf_create_mapistore_uri;
1593
 
        backend.op_db_provision_namedprops = fsocpf_provision_namedprops;
1594
 
 
1595
 
        /* Register ourselves with the MAPISTORE subsystem */
1596
 
        retval = mapistore_backend_register(&backend);
1597
 
        if (retval != MAPISTORE_SUCCESS) {
1598
 
                MSTORE_DEBUG_ERROR(MSTORE_LEVEL_CRITICAL, "Failed to register the '%s' mapistore backend!\n", backend.name);
1599
 
        }
1600
 
 
1601
 
        return retval;
1602
 
}