2
OpenChange Storage Abstraction Layer library
3
MAPIStore FS / OCPF backend
7
Copyright (C) Julien Kerihuel 2010-2011
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.
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.
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/>.
23
#include "mapistore_fsocpf.h"
27
#include <sys/types.h>
32
\details Initialize fsocpf mapistore backend
34
\return MAPISTORE_SUCCESS on success
36
static enum MAPISTORE_ERROR fsocpf_init(void)
38
DEBUG(0, ("fsocpf backend initialized\n"));
42
return MAPISTORE_SUCCESS;
47
\details Allocate / initialize the fsocpf_context structure
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
56
static struct fsocpf_context *fsocpf_context_init(TALLOC_CTX *mem_ctx,
57
struct mapistore_backend_context *mstoredb_ctx,
58
const char *login_user,
63
struct fsocpf_context *fsocpf_ctx;
66
if (!mstoredb_ctx) return NULL;
68
fsocpf_ctx = talloc_zero(mem_ctx, struct fsocpf_context);
69
if (!fsocpf_ctx) return NULL;
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;
83
static enum MAPISTORE_ERROR fsocpf_provision_namedprops(TALLOC_CTX *mem_ctx,
85
enum MAPISTORE_NAMEDPROPS_PROVISION_TYPE *ntype)
87
return MAPISTORE_ERR_NOT_IMPLEMENTED;
91
\details Generate a mapistore URI for root (system/special) folders
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
98
\return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
100
static enum MAPISTORE_ERROR fsocpf_create_mapistore_uri(TALLOC_CTX *mem_ctx,
102
const char *username,
103
char **mapistore_uri)
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;
115
return MAPISTORE_ERR_NOT_FOUND;
120
\details Allocate / initialize a fsocpf_folder_list element
122
This essentially creates a node of the linked list, which will be added to the list
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
129
static struct fsocpf_folder_list *fsocpf_folder_list_element_init(TALLOC_CTX *mem_ctx,
133
struct fsocpf_folder_list *el;
135
el = talloc_zero(mem_ctx, struct fsocpf_folder_list);
136
if (!el) return NULL;
138
el->folder = talloc_zero((TALLOC_CTX *)el, struct fsocpf_folder);
144
el->folder->uri = talloc_strdup((TALLOC_CTX *)el, uri);
145
el->folder->dir = dir;
151
\details Search for the fsocpf_folder for a given folder URI
153
\param fsocpf_ctx the fsocpf context
154
\param uri the folder uri
156
\return folder on success or NULL if the folder was not found
158
static struct fsocpf_folder *fsocpf_find_folder(struct fsocpf_context *fsocpf_ctx,
161
struct fsocpf_folder_list *el;
162
const char *path = NULL;
165
if (!fsocpf_ctx) return NULL;
166
if (!uri) return NULL;
168
if (mapistore_strip_ns_from_uri(uri, &path) != MAPISTORE_SUCCESS) {
169
/* assume it's already stripped */
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)) {
180
MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, "%s not found\n", path);
186
static struct fsocpf_folder_list *fsocpf_find_folder_list(struct fsocpf_context *fsocpf_ctx,
189
struct fsocpf_folder_list *el;
190
const char *path = NULL;
193
if (!fsocpf_ctx) return NULL;
194
if (!fsocpf_ctx->folders) return NULL;
195
if (!uri) return NULL;
197
if (mapistore_strip_ns_from_uri(uri, &path) != MAPISTORE_SUCCESS) {
198
/* assume it's already stripped */
202
MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, "finding %s\n", path);
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)) {
211
MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, "%s not found\n", path);
217
\details Allocate / initialize a fsocpf_message_list element
219
This essentialy creates a node of the linked list, which will be
220
added to the list by the caller
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
227
\return Pointer to allocated folder list on success, otherwise NULL
229
static struct fsocpf_message_list *fsocpf_message_list_element_init(TALLOC_CTX *mem_ctx,
230
const char *folder_uri,
234
struct fsocpf_message_list *el;
237
if (!folder_uri) return NULL;
238
if (!uri) return NULL;
239
if (!context_id) return NULL;
241
el = talloc_zero(mem_ctx, struct fsocpf_message_list);
242
if (!el) return NULL;
244
el->message = talloc_zero((TALLOC_CTX *)el, struct fsocpf_message);
245
if (!el->message) return NULL;
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;
256
\details search for the fsocpf_message for a given message URI
258
\param fsocpf_ctx the store context
259
\param uri the message URI of the fsocpf_message to search for
261
\return message on success, or NULL if the message was not found
263
static struct fsocpf_message *fsocpf_find_message(struct fsocpf_context *fsocpf_ctx,
266
struct fsocpf_message_list *el;
269
if (!fsocpf_ctx) return NULL;
270
if (!uri) return NULL;
272
for (el = fsocpf_ctx->messages; el; el = el->next) {
273
if (el->message && el->message->uri && !strcmp(el->message->uri, uri)) {
283
\details search for the fsocpf_message_list for a given message URI
285
\param fsocpf_ctx the store context
286
\param uri the message URI of the fsocpf_message to search for
288
\return point to message list on success, or NULL if the message was not found
290
static struct fsocpf_message_list *fsocpf_find_message_list(struct fsocpf_context *fsocpf_ctx,
293
struct fsocpf_message_list *el;
296
if (!fsocpf_ctx) return NULL;
297
if (!fsocpf_ctx->messages) return NULL;
298
if (!uri) return NULL;
300
for (el = fsocpf_ctx->messages; el; el = el->next) {
301
if (el->message && el->message->uri && !strcmp(el->message->uri, uri)) {
311
\details Create a connection context to the fsocpf backend
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
319
static enum MAPISTORE_ERROR fsocpf_create_context(struct mapistore_backend_context *mstoredb_ctx,
320
const char *login_user,
321
const char *username,
330
struct fsocpf_context *fsocpf_ctx;
331
struct fsocpf_folder_list *el;
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);
340
MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, "Creating context for URI: %s\n", uri);
342
mem_ctx = (TALLOC_CTX *) mstoredb_ctx;
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);
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);
351
root_dir = opendir(root_uri);
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;
363
talloc_free(root_uri);
365
/* Step 1. Try to open context directory */
366
top_dir = opendir(uri);
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;
373
top_dir = opendir(uri);
375
MSTORE_DEBUG_ERROR(MSTORE_LEVEL_CRITICAL, "Unable to open folder: %s\n", strerror(errno));
376
return MAPISTORE_ERR_CONTEXT_FAILED;
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);
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);
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);
391
/* Step 3. Store fsocpf context within the opaque private_data pointer */
392
*private_data = (void *)fsocpf_ctx;
394
DEBUG(0, ("%s has been opened\n", uri));
396
struct dirent *curdir;
399
while ((curdir = readdir(fsocpf_ctx->dir)) != NULL) {
400
DEBUG(0, ("%d: readdir: %s\n", j, curdir->d_name));
405
return MAPISTORE_SUCCESS;
410
\details Delete a connection context from the fsocpf backend
412
\param private_data pointer to the current fsocpf context
414
\return MAPISTORE_SUCCESS on success, otherwise MAPISTORE_ERROR
416
static enum MAPISTORE_ERROR fsocpf_delete_context(void *private_data)
418
struct fsocpf_context *fsocpf_ctx = (struct fsocpf_context *)private_data;
420
MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, MSTORE_SINGLE_MSG, "");
423
return MAPISTORE_SUCCESS;
426
if (fsocpf_ctx->dir) {
427
closedir(fsocpf_ctx->dir);
428
fsocpf_ctx->dir = NULL;
431
talloc_free(fsocpf_ctx);
434
return MAPISTORE_SUCCESS;
439
\details Delete data associated to a given folder or message
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
445
\return MAPISTORE_SUCCESS on success, otherwise MAPISTORE_ERROR
447
static enum MAPISTORE_ERROR fsocpf_release_record(void *private_data, const char *uri, uint8_t type)
449
struct fsocpf_context *fsocpf_ctx = (struct fsocpf_context *)private_data;
450
struct fsocpf_message_list *message;
452
MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, MSTORE_SINGLE_MSG, "");
455
MAPISTORE_RETVAL_IF(!fsocpf_ctx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
456
MAPISTORE_RETVAL_IF(!uri, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
459
case MAPISTORE_FOLDER:
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);
467
DLIST_REMOVE(fsocpf_ctx->messages, message);
468
talloc_free(message);
473
return MAPISTORE_SUCCESS;
478
\details return the mapistore path associated to a given message or
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
486
\return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
488
static enum MAPISTORE_ERROR fsocpf_get_path(void *private_data, const char *uri,
489
uint8_t type, char **path)
491
struct fsocpf_folder *folder;
492
struct fsocpf_message *message;
493
struct fsocpf_context *fsocpf_ctx = (struct fsocpf_context *)private_data;
495
DEBUG(5, ("[%s:%d]\n", __FUNCTION__, __LINE__));
498
return MAPISTORE_ERROR;
502
case MAPISTORE_FOLDER:
503
folder = fsocpf_find_folder(fsocpf_ctx, uri);
505
DEBUG(0, ("folder doesn't exist ...\n"));
507
return MAPISTORE_ERROR;
509
DEBUG(0, ("folder->path is %s\n", folder->uri));
512
case MAPISTORE_MESSAGE:
513
message = fsocpf_find_message(fsocpf_ctx, uri);
515
DEBUG(0, ("message doesn't exist ...\n"));
517
return MAPISTORE_ERROR;
519
DEBUG(0, ("message->uri is %s\n", message->uri));
520
*path = message->uri;
523
DEBUG(0, ("[%s]: Invalid type %d\n", __FUNCTION__, type));
524
return MAPISTORE_ERROR;
527
return MAPISTORE_SUCCESS;
530
static enum MAPISTORE_ERROR fsocpf_op_get_uri_by_name(void *private_data,
531
const char *parent_uri,
532
const char *foldername,
535
struct fsocpf_context *fsocpf_ctx = (struct fsocpf_context *)private_data;
536
struct fsocpf_folder *folder;
537
struct dirent *curdir;
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);
545
/* Lookup the parent folder from its URI */
546
folder = fsocpf_find_folder(fsocpf_ctx, parent_uri);
548
return MAPISTORE_ERROR;
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;
560
return MAPISTORE_ERR_NOT_FOUND;
564
\details Set the properties for a folder
566
\param folder_uri the folder full patch
567
\param aRow the properties to set on the folder
569
\return MAPISTORE_SUCCESS on success, otherwise a MAPISTORE_ERROR value.
571
static enum MAPISTORE_ERROR fsocpf_set_folder_props(const char *folder_uri, struct SRow *aRow)
574
struct mapi_SPropValue_array mapi_lpProps;
575
uint32_t ocpf_context_id;
580
mem_ctx = talloc_named(NULL, 0, __FUNCTION__);
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]));
594
uint32_t num_props = 0;
595
struct SPropValue *original_props;
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) {
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;
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;
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]));
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);
635
talloc_free(mem_ctx);
637
return MAPISTORE_SUCCESS;
641
\details Create a folder in the fsocpf backend
643
\param private_data pointer to the current fsocpf context
645
\return MAPISTORE_SUCCESS on success, otherwise MAPISTORE_ERROR
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,
654
enum MAPISTORE_ERROR retval;
657
struct fsocpf_context *fsocpf_ctx = (struct fsocpf_context *)private_data;
658
struct fsocpf_folder *folder;
659
const char *parent_uri;
662
struct fsocpf_folder_list *newel;
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);
672
MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, MSTORE_SINGLE_MSG, "");
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);
678
if (fsocpf_op_get_uri_by_name(private_data, parent_uri, folder_name, &dummy_uri) == MAPISTORE_SUCCESS) {
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;
685
/* Step 1. Search for the parent fid */
686
folder = fsocpf_find_folder(fsocpf_ctx, parent_uri);
688
MSTORE_DEBUG_ERROR(MSTORE_LEVEL_CRITICAL, "Parent context not found for folder '%s'\n", parent_uri);
689
return MAPISTORE_ERR_NO_DIRECTORY;
692
mem_ctx = talloc_named(NULL, 0, __FUNCTION__);
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);
698
MSTORE_DEBUG_ERROR(MSTORE_LEVEL_CRITICAL, "mkdir failed: %s\n", strerror(errno));
699
talloc_free(mem_ctx);
700
return MAPISTORE_ERROR;
702
dir = opendir(newfolder);
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);
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);
711
/* Step 4. Set the properties on the folder */
714
aRow.lpProps = talloc_array(mem_ctx, struct SPropValue, 3);
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;
721
aRow.lpProps = talloc_array(mem_ctx, struct SPropValue, 2);
723
aRow.lpProps[0].ulPropTag = PidTagDisplayName;
724
aRow.lpProps[0].value.lpszW = folder_name;
727
retval = fsocpf_set_folder_props(newfolder, &aRow);
729
/* Step 5. Generate the URI for the new created folder */
730
*folder_uri = talloc_asprintf((TALLOC_CTX *)fsocpf_ctx, "fsocpf://%s", newfolder);
732
talloc_free(aRow.lpProps);
733
talloc_free(newfolder);
734
talloc_free(mem_ctx);
741
\details Delete a folder from the fsocpf backend
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
747
\return MAPISTORE_SUCCESS on success, otherwise MAPISTORE_ERROR
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)
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;
759
struct fsocpf_folder_list *el;
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);
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;
770
MSTORE_DEBUG_INFO(MSTORE_LEVEL_LOW, "Deleting %s from %s\n", folder_path, parent_uri);
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);
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);
780
mem_ctx = talloc_named(NULL, 0, __FUNCTION__);
782
/* Step 3. Remove .properties file */
783
propertiespath = talloc_asprintf(mem_ctx, "%s/.properties", folder_path);
784
ret = unlink(propertiespath);
786
MSTORE_DEBUG_ERROR(MSTORE_LEVEL_CRITICAL, "Unlink failed with error '%s'\n", strerror(errno));
789
/* Step 4. Delete directory */
790
ret = rmdir(folder_path);
792
MSTORE_DEBUG_ERROR(MSTORE_LEVEL_CRITICAL, "rmdir failed with error '%s'\n", strerror(errno));
793
talloc_free(mem_ctx);
794
return MAPISTORE_ERROR;
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);
804
return MAPISTORE_SUCCESS;
809
\details Open a folder from the fsocpf backend
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
815
\return MAPISTORE_SUCCESS on success, otherwise MAPISTORE_ERROR
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)
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;
827
const char *folder_path = NULL;
828
const char *parent_folder_path = NULL;
830
MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, MSTORE_SINGLE_MSG, "");
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);
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;
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;
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);
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);
858
folder = fsocpf_find_folder(fsocpf_ctx, folder_path);
859
MAPISTORE_RETVAL_IF(!folder, MAPISTORE_ERR_NO_DIRECTORY, NULL);
861
return MAPISTORE_SUCCESS;
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);
868
mem_ctx = talloc_named(NULL, 0, __FUNCTION__);
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);
876
while ((curdir = readdir(folder->dir)) != NULL) {
877
MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, "[%d]: readdir: %s\n", i, curdir->d_name);
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);
883
MSTORE_DEBUG_INFO(MSTORE_LEVEL_PEDANTIC, "%s\n", "Folder found");
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);
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);
894
MSTORE_DEBUG_INFO(MSTORE_LEVEL_PEDANTIC, "errno = %d\n", errno);
896
rewinddir(folder->dir);
897
talloc_free(mem_ctx);
899
return MAPISTORE_SUCCESS;
904
\details Close a folder from the fsocpf backend
906
\param private_data pointer to the current fsocpf context
907
\param folder_uri the URI of the folder to close
909
\return MAPISTORE_SUCCESS on success, otherwise MAPISTORE_ERROR
911
static enum MAPISTORE_ERROR fsocpf_op_closedir(void *private_data, const char *folder_uri)
913
struct fsocpf_context *fsocpf_ctx = (struct fsocpf_context *)private_data;
916
return MAPISTORE_ERROR;
918
/* TODO: this probably should be implemented */
920
return MAPISTORE_SUCCESS;
925
\details Read directory content from the fsocpf backend
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
932
\return MAPISTORE_SUCCESS on success, otherwise MAPISTORE_ERROR
934
static enum MAPISTORE_ERROR fsocpf_op_readdir_count(void *private_data,
935
const char *folder_uri,
936
enum MAPISTORE_TABLE_TYPE table_type,
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;
945
MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, MSTORE_SINGLE_MSG, "");
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);
952
if (mapistore_strip_ns_from_uri(folder_uri, &folder_path) != MAPISTORE_SUCCESS) {
953
/* assume its already stripped */
954
folder_path = folder_uri;
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);
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);
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);
972
switch (table_type) {
973
case MAPISTORE_FOLDER_TABLE:
974
rewinddir(folder->dir);
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);
985
case MAPISTORE_MESSAGE_TABLE:
986
rewinddir(folder->dir);
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);
1001
return MAPISTORE_SUCCESS;
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,
1008
enum MAPITAGS proptag,
1012
struct dirent *curdir;
1013
uint32_t counter = 0;
1014
char *folderID = NULL;
1016
uint32_t cValues = 0;
1017
struct SPropValue *lpProps;
1018
uint32_t ocpf_context_id;
1020
MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, MSTORE_SINGLE_MSG, "");
1023
MAPISTORE_RETVAL_IF(!folder, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
1024
MAPISTORE_RETVAL_IF(!data, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
1026
/* Set dir listing to current position */
1027
rewinddir(folder->dir);
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, "..") &&
1033
folderID = talloc_strdup(folder, curdir->d_name);
1036
if (strcmp(curdir->d_name, ".") && strcmp(curdir->d_name, "..") &&
1037
(curdir->d_type == DT_DIR)) {
1042
MAPISTORE_RETVAL_IF(!folderID, MAPISTORE_ERR_NOT_FOUND, NULL);
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);
1048
ret = ocpf_new_context(propfile, &ocpf_context_id, OCPF_FLAGS_READ);
1049
talloc_free(propfile);
1051
/* process the file */
1052
ret = ocpf_parse(ocpf_context_id);
1054
ocpf_server_set_SPropValue(folder, ocpf_context_id);
1055
lpProps = ocpf_get_SPropValue(ocpf_context_id, &cValues);
1057
/* FIXME: We need to find a proper way to handle this (for all types) */
1058
talloc_steal(folder, lpProps);
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));
1068
*data = talloc_strdup(folder, (char *)*data);
1071
if (*data == NULL) {
1072
ret = ocpf_del_context(ocpf_context_id);
1073
return MAPISTORE_ERR_NOT_FOUND;
1076
ret = ocpf_del_context(ocpf_context_id);
1077
return MAPISTORE_SUCCESS;
1081
static enum MAPISTORE_ERROR fsocpf_get_property_from_message_table(struct fsocpf_folder *folder,
1083
enum MAPITAGS proptag,
1087
struct dirent *curdir;
1088
uint32_t counter = 0;
1089
char *messageID = NULL;
1091
uint32_t cValues = 0;
1092
struct SPropValue *lpProps;
1093
uint32_t ocpf_context_id;
1095
MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, MSTORE_SINGLE_MSG, "");
1098
MAPISTORE_RETVAL_IF(!folder, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
1099
MAPISTORE_RETVAL_IF(!data, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
1101
/* Set dir listing to current position */
1102
rewinddir(folder->dir);
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);
1110
if (strcmp(curdir->d_name, ".properties") &&
1111
strcmp(curdir->d_name, ".") &&
1112
strcmp(curdir->d_name, "..") &&
1113
(curdir->d_type == DT_REG)) {
1118
MAPISTORE_RETVAL_IF(!messageID, MAPISTORE_ERR_NOT_FOUND, NULL);
1120
/* if fid, return folder fid */
1121
/* if (proptag == PR_FID) { */
1122
/* *data = (uint64_t *)&folder->fid; */
1123
/* return MAPISTORE_SUCCESS; */
1126
/* If mid, return curdir->d_name */
1127
/* if (proptag == PR_MID) { */
1128
/* uint64_t *mid; */
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; */
1137
/* Otherwise opens curdir->d_name file with ocpf */
1138
propfile = talloc_asprintf(folder, "%s/%s", folder->uri, messageID);
1139
talloc_free(messageID);
1141
ret = ocpf_new_context(propfile, &ocpf_context_id, OCPF_FLAGS_READ);
1142
talloc_free(propfile);
1144
/* process the file */
1145
ret = ocpf_parse(ocpf_context_id);
1147
ocpf_server_set_SPropValue(folder, ocpf_context_id);
1148
lpProps = ocpf_get_SPropValue(ocpf_context_id, &cValues);
1150
/* FIXME: We need to find a proper way to handle this (for all types) */
1151
talloc_steal(folder, lpProps);
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));
1161
*data = talloc_strdup(folder, (char *)*data);
1164
if (*data == NULL) {
1165
ocpf_del_context(ocpf_context_id);
1166
return MAPISTORE_ERR_NOT_FOUND;
1169
ocpf_del_context(ocpf_context_id);
1170
return MAPISTORE_SUCCESS;
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,
1178
enum MAPITAGS proptag,
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;
1186
MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, MSTORE_SINGLE_MSG, "");
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);
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);
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);
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);
1208
switch (table_type) {
1209
case MAPISTORE_FOLDER_TABLE:
1210
retval = fsocpf_get_property_from_folder_table(folder, pos, proptag, data);
1212
case MAPISTORE_MESSAGE_TABLE:
1213
retval = fsocpf_get_property_from_message_table(folder, pos, proptag, data);
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)
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;
1236
MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, MSTORE_SINGLE_MSG, "");
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);
1244
/* Search for the mid fsocpf_message entry */
1245
message = fsocpf_find_message(fsocpf_ctx, message_uri);
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);
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;
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);
1261
MSTORE_DEBUG_INFO(MSTORE_LEVEL_INFO, "Message %s is stored within %s\n", message_uri, folder->uri);
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);
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);
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);
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);
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);
1282
retval = ocpf_server_set_SPropValue(el, ocpf_context_id);
1283
msg->properties->lpProps = ocpf_get_SPropValue(ocpf_context_id, &msg->properties->cValues);
1285
return MAPISTORE_SUCCESS;
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 */
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
1298
static enum MAPISTORE_ERROR fsocpf_op_createmessage(void *private_data,
1299
const char *folder_uri,
1300
char **_message_uri,
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;
1310
MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, MSTORE_SINGLE_MSG, "");
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);
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);
1321
MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, "Message %s will be created within %s\n", message_uri, folder->uri);
1323
ret = ocpf_new_context(message_uri, &ocpf_context_id, OCPF_FLAGS_CREATE);
1324
MAPISTORE_RETVAL_IF(ret, MAPISTORE_ERR_CONTEXT_FAILED, NULL);
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);
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);
1332
*_message_uri = message_uri;
1333
*uri_register = true;
1335
return MAPISTORE_SUCCESS;
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,
1345
struct fsocpf_context *fsocpf_ctx = (struct fsocpf_context *)private_data;
1346
struct fsocpf_message *message;
1348
MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, MSTORE_SINGLE_MSG, "");
1351
MAPISTORE_RETVAL_IF(!fsocpf_ctx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
1352
MAPISTORE_RETVAL_IF(!message_uri, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
1354
message = fsocpf_find_message(fsocpf_ctx, message_uri);
1355
if (!message || !message->ocpf_context_id) {
1356
return MAPISTORE_ERR_NOT_FOUND;
1359
ocpf_write_init(message->ocpf_context_id, 0);
1360
ocpf_write_commit(message->ocpf_context_id);
1362
return MAPISTORE_SUCCESS;
1365
/* FIXME: See savechangesmessage comments */
1366
static enum MAPISTORE_ERROR fsocpf_op_submitmessage(void *private_data,
1367
const char *message_uri,
1370
struct fsocpf_context *fsocpf_ctx = (struct fsocpf_context *)private_data;
1371
struct fsocpf_message *message;
1373
MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, MSTORE_SINGLE_MSG, "");
1376
MAPISTORE_RETVAL_IF(!fsocpf_ctx, MAPISTORE_ERR_NOT_INITIALIZED, NULL);
1377
MAPISTORE_RETVAL_IF(!message_uri, MAPISTORE_ERR_INVALID_PARAMETER, NULL);
1379
/* This implementation is incorrect but should fit for immediate purposes */
1380
message = fsocpf_find_message(fsocpf_ctx, message_uri);
1382
ocpf_write_init(message->ocpf_context_id, 0);
1383
ocpf_write_commit(message->ocpf_context_id);
1385
return MAPISTORE_SUCCESS;
1389
static char *fsocpf_get_recipients(TALLOC_CTX *mem_ctx, struct SRowSet *SRowSet, uint8_t recipient_class)
1391
char *recipient = NULL;
1394
for (i = 0; i < SRowSet->cRows; i++) {
1395
if (SRowSet->aRow[i].lpProps[0].value.l == recipient_class) {
1397
recipient = talloc_strdup(mem_ctx, SRowSet->aRow[i].lpProps[1].value.lpszA);
1399
recipient = talloc_asprintf(recipient, "%s;%s", recipient,
1400
SRowSet->aRow[i].lpProps[1].value.lpszA);
1408
static enum MAPISTORE_ERROR fsocpf_op_getprops(void *private_data,
1411
struct SPropTagArray *SPropTagArray,
1414
struct fsocpf_context *fsocpf_ctx = (struct fsocpf_context *)private_data;
1415
struct fsocpf_message *message;
1417
struct SPropValue *lpProps;
1418
struct SPropValue lpProp;
1419
struct SRowSet *SRowSet;
1422
char *recip_str = NULL;
1424
MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, MSTORE_SINGLE_MSG, "");
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);
1433
case MAPISTORE_FOLDER:
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);
1441
ocpf_dump(message->ocpf_context_id);
1442
for (i = 0; i != SPropTagArray->cValues; i++) {
1443
switch (SPropTagArray->aulPropTag[i]) {
1445
case PR_DISPLAY_TO_UNICODE:
1446
recip_str = fsocpf_get_recipients(fsocpf_ctx, SRowSet, OCPF_MAPI_TO);
1449
case PR_DISPLAY_CC_UNICODE:
1450
recip_str = fsocpf_get_recipients(fsocpf_ctx, SRowSet, OCPF_MAPI_CC);
1452
case PR_DISPLAY_BCC:
1453
case PR_DISPLAY_BCC_UNICODE:
1454
recip_str = fsocpf_get_recipients(fsocpf_ctx, SRowSet, OCPF_MAPI_BCC);
1457
for (j = 0; j != cValues; j++) {
1458
if (SPropTagArray->aulPropTag[i] == lpProps[j].ulPropTag) {
1459
SRow_addprop(aRow, lpProps[j]);
1465
lpProp.ulPropTag = SPropTagArray->aulPropTag[i];
1466
switch (SPropTagArray->aulPropTag[i] & 0xFFFF) {
1468
lpProp.value.lpszA = talloc_strdup(aRow, recip_str);
1471
lpProp.value.lpszW = talloc_strdup(aRow, recip_str);
1474
SRow_addprop(aRow, lpProp);
1475
talloc_free(recip_str);
1481
return MAPISTORE_SUCCESS;
1485
static enum MAPISTORE_ERROR fsocpf_op_setprops(void *private_data,
1490
struct fsocpf_context *fsocpf_ctx = (struct fsocpf_context *) private_data;
1491
struct fsocpf_folder *folder;
1492
struct fsocpf_message *message;
1495
enum MAPISTORE_ERROR retval = MAPISTORE_SUCCESS;
1497
MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, MSTORE_SINGLE_MSG, "");
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);
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;
1508
MSTORE_DEBUG_INFO(MSTORE_LEVEL_DEBUG, "uri: %s, path: %s\n", uri, path);
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);
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);
1523
ocpf_server_add_SPropValue(message->ocpf_context_id, &aRow->lpProps[i]);
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)
1537
struct fsocpf_context *fsocpf_ctx = (struct fsocpf_context *)private_data;
1538
struct fsocpf_message *message;
1540
DEBUG(5, ("[%s:%d]\n", __FUNCTION__, __LINE__));
1542
message = fsocpf_find_message(fsocpf_ctx, message_uri);
1543
MAPISTORE_RETVAL_IF(!message, MAPISTORE_ERR_NOT_FOUND, NULL);
1545
ret = unlink(message->uri);
1546
MAPISTORE_RETVAL_IF(ret, MAPISTORE_ERROR, NULL);
1548
return MAPISTORE_SUCCESS;
1552
\details Entry point for mapistore FSOCPF backend
1554
\return MAPISTORE_SUCCESS on success, otherwise MAPISTORE error
1556
enum MAPISTORE_ERROR mapistore_init_backend(void)
1558
struct mapistore_backend backend;
1559
enum MAPISTORE_ERROR retval;
1561
/* Initialize backend with defaults */
1562
retval = mapistore_backend_init_defaults(&backend);
1563
MAPISTORE_RETVAL_IF(retval, retval, NULL);
1565
/* Fill in our name */
1566
backend.name = "fsocpf";
1567
backend.description = "mapistore filesystem + ocpf backend";
1568
backend.uri_namespace = "fsocpf://";
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;
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;
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);