2
OpenChange Server implementation
4
EMSMDBP: EMSMDB Provider implementation
6
Copyright (C) Wolfgang Sourdeau 2012
8
This program is free software; you can redistribute it and/or modify
9
it under the terms of the GNU General Public License as published by
10
the Free Software Foundation; either version 3 of the License, or
11
(at your option) any later version.
13
This program is distributed in the hope that it will be useful,
14
but WITHOUT ANY WARRANTY; without even the implied warranty of
15
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
GNU General Public License for more details.
18
You should have received a copy of the GNU General Public License
19
along with this program. If not, see <http://www.gnu.org/licenses/>.
23
\file emsmdbp_provisioning.c
25
\brief Account provisioning
33
#include "dcesrv_exchange_emsmdb.h"
35
#include <gen_ndr/ndr_property.h>
37
_PUBLIC_ enum MAPISTATUS emsmdbp_mailbox_provision_public_freebusy(struct emsmdbp_context *emsmdbp_ctx, const char *EssDN)
40
char *dn_root, *dn_user, *cn_ptr;
41
uint64_t public_fb_fid, group_fid, fb_mid, change_num;
44
struct SRow property_row;
47
mem_ctx = talloc_zero(NULL, TALLOC_CTX);
49
dn_root = talloc_asprintf(mem_ctx, "EX:%s", EssDN);
50
cn_ptr = strstr(dn_root, "/cn");
52
ret = MAPI_E_INVALID_PARAMETER;
56
dn_user = talloc_asprintf(mem_ctx, "USER-%s", cn_ptr);
59
/* convert dn_root to lowercase */
60
max = cn_ptr - dn_root;
61
for (i = 3; i < max; i++) {
62
dn_root[i] = tolower(dn_root[i]);
65
/* convert dn_user to uppercase. Yes, it's stupid like that. */
66
max = strlen(dn_user);
67
for (i = 5; i < max; i++) {
68
dn_user[i] = toupper(dn_user[i]);
71
ret = openchangedb_get_PublicFolderID(emsmdbp_ctx->oc_ctx, EMSMDBP_PF_FREEBUSY, &public_fb_fid);
72
if (ret != MAPI_E_SUCCESS) {
73
DEBUG(5, ("provisioning: freebusy root folder not found in openchange.ldb\n"));
77
ret = openchangedb_get_fid_by_name(emsmdbp_ctx->oc_ctx, public_fb_fid, dn_root, &group_fid);
78
if (ret != MAPI_E_SUCCESS) {
79
openchangedb_get_new_folderID(emsmdbp_ctx->oc_ctx, &group_fid);
80
openchangedb_get_new_changeNumber(emsmdbp_ctx->oc_ctx, &change_num);
81
openchangedb_create_folder(emsmdbp_ctx->oc_ctx, public_fb_fid, group_fid, change_num, NULL, -1);
84
ret = openchangedb_get_mid_by_subject(emsmdbp_ctx->oc_ctx, group_fid, dn_user, false, &fb_mid);
85
if (ret != MAPI_E_SUCCESS) {
86
openchangedb_get_new_folderID(emsmdbp_ctx->oc_ctx, &fb_mid);
87
openchangedb_get_new_changeNumber(emsmdbp_ctx->oc_ctx, &change_num);
88
openchangedb_message_create(mem_ctx, emsmdbp_ctx->oc_ctx, fb_mid, group_fid, false, &message_object);
89
property_row.cValues = 1;
90
property_row.lpProps = talloc_zero(mem_ctx, struct SPropValue);
91
property_row.lpProps[0].ulPropTag = PR_NORMALIZED_SUBJECT_UNICODE;
92
property_row.lpProps[0].value.lpszW = dn_user;
93
openchangedb_message_set_properties(mem_ctx, message_object, &property_row);
94
openchangedb_message_save(message_object, 0);
100
talloc_free(mem_ctx);
105
_PUBLIC_ enum MAPISTATUS emsmdbp_mailbox_provision(struct emsmdbp_context *emsmdbp_ctx, const char *username)
107
/* auto-provisioning:
109
During private logon:
110
- fetch list of available folders from all backends + list of capabilities (handled folder types) + fallback entry
111
- if fallback is not available: FAIL
112
- fetch list of existing folders from openchangedb
113
- if mailbox does not exist:
114
- create basic structure
115
- if certain folders are not available (Inbox, Deleted Items, Spooler Queue, Outbox), use fallback
116
- synchronize list of non-mandatory and secondary folders
117
- update relevant entry ids in relevant objects
118
- ability to leave creation of fallback and other url to the relevant backend
121
folder creation = createfolder + setprops (class) + release
124
* RopLogon entries (mandatory) (autoprovisioning)
126
mailbox (Root): (None)
128
"Common Views": (None) (sogo://wsourdeau:wsourdeau@common-views/) -> fallback
129
"Deferred Action": (None) (sogo://wsourdeau:wsourdeau@deferred-actions/) -> fallback
130
"Search" (Finder): None (sogo://wsourdeau:wsourdeau@search/) -> fallback
131
"Schedule": (None) (sogo://wsourdeau:wsourdeau@schedule/) -> fallback
132
"Shortcuts": (None) (sogo://wsourdeau:wsourdeau@shortcuts/) -> fallback
133
"Spooler Queue": (None) (sogo://wsourdeau:wsourdeau@spooler-queue/) -> fallback
134
"Views": (sogo://wsourdeau:wsourdeau@views/) -> fallback
136
"IPM Subtree" (Top of Personal Folders): (None)
138
* autoprovisioning backend based
140
"Inbox": IPF.Note (sogo://wsourdeau:wsourdeau@inbox/)
141
"Outbox": IPF.Note (sogo://wsourdeau:wsourdeau@outbox/)
142
"Sent Items": IPF.Note (sogo://wsourdeau:wsourdeau@sent-items/)
143
"Deleted Items": IPF.Note (sogo://wsourdeau:wsourdeau@deleted-items/)
145
* additional special folders
146
"Calendar": IPF.Appointment (PidTagIpmAppointmentEntryId)
147
"Contacts": IPF.Contact (PidTagIpmContactEntryId)
148
"Notes": IPF.StickyNote (PidTagIpmNoteEntryId)
149
"Tasks": IPF.Task (PidTagIpmTaskEntryId)
150
"Journal": IPF.Journal (PidTagIpmJournalEntryId)
151
"Drafts": IPF.Note (PidTagIpmDraftsEntryId)
156
"Reminders": Outlook.Reminder (sogo://wsourdeau:wsourdeau@reminders/) (PidTagRemindersOnlineEntryId) -> fallback
158
"Sync Issues": IPF.Note (PidTagAdditionalRenEntryIds)
159
"Junk E-mail": IPF.Note (PidTagAdditionalRenEntryIds)
164
Exchange hierarchy for virgin account:
166
FolderId: 0x67ca828f02000001 Display Name: " "; Container Class: MAPI_E_NOT_FOUND; Message Class: MAPI_E_NOT_FOUND; Has Subfolders: TRUE;
168
FolderId: 0x71ca828f02000001 Display Name: " Common Views"; Container Class: MAPI_E_NOT_FOUND; Message Class: MAPI_E_NOT_FOUND; Has Subfolders: FALSE;
169
FolderId: 0x69ca828f02000001 Display Name: " Deferred Action"; Container Class: MAPI_E_NOT_FOUND; Message Class: MAPI_E_NOT_FOUND; Has Subfolders: FALSE;
170
FolderId: 0x6fca828f02000001 Display Name: " Finder"; Container Class: MAPI_E_NOT_FOUND; Message Class: MAPI_E_NOT_FOUND; Has Subfolders: FALSE;
171
FolderId: 0x72ca828f02000001 Display Name: " Schedule"; Container Class: MAPI_E_NOT_FOUND; Message Class: MAPI_E_NOT_FOUND; Has Subfolders: FALSE;
172
FolderId: 0x73ca828f02000001 Display Name: " Shortcuts"; Container Class: MAPI_E_NOT_FOUND; Message Class: MAPI_E_NOT_FOUND; Has Subfolders: FALSE;
173
FolderId: 0x6aca828f02000001 Display Name: " Spooler Queue"; Container Class: MAPI_E_NOT_FOUND; Message Class: MAPI_E_NOT_FOUND; Has Subfolders: FALSE;
174
FolderId: 0x70ca828f02000001 Display Name: " Views"; Container Class: MAPI_E_NOT_FOUND; Message Class: MAPI_E_NOT_FOUND; Has Subfolders: FALSE;
176
FolderId: 0x68ca828f02000001 Display Name: "Top of Information Store"; Container Class: MAPI_E_NOT_FOUND; Message Class: MAPI_E_NOT_FOUND; Has Subfolders: TRUE;
178
FolderId: 0x6bca828f02000001 Display Name: " Boîte de réception"; Container Class: " IPF.Note"; Message Class: MAPI_E_NOT_FOUND; Has Subfolders: FALSE;
179
FolderId: 0x6cca828f02000001 Display Name: " Boîte d'envoi"; Container Class: " IPF.Note"; Message Class: MAPI_E_NOT_FOUND; Has Subfolders: FALSE;
180
FolderId: 0x67c3828f02000001 Display Name: " Brouillons"; Container Class: " IPF.Note"; Message Class: MAPI_E_NOT_FOUND; Has Subfolders: FALSE;
181
FolderId: 0x65c3828f02000001 Display Name: " Calendrier"; Container Class: " IPF.Appointment"; Message Class: MAPI_E_NOT_FOUND; Has Subfolders: FALSE;
182
FolderId: 0x66c3828f02000001 Display Name: " Contacts"; Container Class: " IPF.Contact"; Message Class: MAPI_E_NOT_FOUND; Has Subfolders: FALSE;
183
FolderId: 0x6dca828f02000001 Display Name: " Éléments envoyés"; Container Class: " IPF.Note"; Message Class: MAPI_E_NOT_FOUND; Has Subfolders: FALSE;
184
FolderId: 0x6eca828f02000001 Display Name: " Éléments supprimés"; Container Class: " IPF.Note"; Message Class: MAPI_E_NOT_FOUND; Has Subfolders: FALSE;
185
FolderId: 0x68c3828f02000001 Display Name: " Journal"; Container Class: " IPF.Journal"; Message Class: MAPI_E_NOT_FOUND; Has Subfolders: FALSE;
186
FolderId: 0x69c3828f02000001 Display Name: " Notes"; Container Class: " IPF.StickyNote"; Message Class: MAPI_E_NOT_FOUND; Has Subfolders: FALSE;
187
FolderId: 0x6ac3828f02000001 Display Name: " Tâches"; Container Class: " IPF.Task"; Message Class: MAPI_E_NOT_FOUND; Has Subfolders: FALSE;
194
enum mapistore_error retval;
195
struct mapistore_contexts_list *contexts_list;
196
struct StringArrayW_r *existing_uris;
197
struct mapistore_contexts_list *main_entries[MAPISTORE_MAX_ROLES], *secondary_entries[MAPISTORE_MAX_ROLES], *next_entry, *current_entry;
198
static const char *folder_names[] = {NULL, "Root", "Deferred Action", "Spooler Queue", "Common Views", "Schedule", "Finder", "Views", "Shortcuts", "Top of Information Store", "Inbox", "Outbox", "Sent Items", "Deleted Items"};
199
static struct emsmdbp_special_folder special_folders[] = {{MAPISTORE_DRAFTS_ROLE, PR_IPM_DRAFTS_ENTRYID, "Drafts"},
200
{MAPISTORE_CALENDAR_ROLE, PR_IPM_APPOINTMENT_ENTRYID, "Calendar"},
201
{MAPISTORE_CONTACTS_ROLE, PR_IPM_CONTACT_ENTRYID, "Contacts"},
202
{MAPISTORE_TASKS_ROLE, PR_IPM_TASK_ENTRYID, "Tasks"},
203
{MAPISTORE_NOTES_ROLE, PR_IPM_NOTE_ENTRYID, "Notes"},
204
{MAPISTORE_JOURNAL_ROLE, PR_IPM_JOURNAL_ENTRYID, "Journal"}};
205
const char **container_classes;
207
uint64_t mailbox_fid = 0, ipm_fid, inbox_fid = 0, current_fid, found_fid, current_cn;
208
char *fallback_url, *entryid_dump;
209
const char *mapistore_url, *current_name, *base_name;
210
struct emsmdbp_special_folder *current_folder;
211
struct SRow property_row;
212
int i, j, nbr_special_folders = sizeof(special_folders) / sizeof(struct emsmdbp_special_folder);
213
DATA_BLOB entryid_data;
214
struct FolderEntryId folder_entryid;
215
struct Binary_r *entryId;
217
void *backend_object;
219
mem_ctx = talloc_zero(NULL, TALLOC_CTX);
221
ldb_transaction_start(emsmdbp_ctx->oc_ctx);
223
/* Retrieve list of folders from backends */
224
retval = mapistore_list_contexts_for_user(emsmdbp_ctx->mstore_ctx, username, mem_ctx, &contexts_list);
225
if (retval != MAPISTORE_SUCCESS) {
226
talloc_free(mem_ctx);
227
return MAPI_E_DISK_ERROR;
230
/* Fix mapistore uris in returned entries */
231
current_entry = contexts_list;
232
while (current_entry) {
233
mapistore_url = current_entry->url;
235
if (mapistore_url[strlen(mapistore_url)-1] != '/') {
236
current_entry->url = talloc_asprintf(mem_ctx, "%s/", mapistore_url);
238
/* DEBUG(5, ("received entry: '%s' (%p)\n", current_entry->url, current_entry)); */
241
DEBUG(5, ("received entry without uri\n"));
244
current_entry = current_entry->next;
247
/* Retrieve list of existing entries */
248
ret = openchangedb_get_MAPIStoreURIs(emsmdbp_ctx->oc_ctx, username, mem_ctx, &existing_uris);
249
if (ret == MAPI_E_SUCCESS) {
250
for (i = 0; i < existing_uris->cValues; i++) {
251
/* DEBUG(5, ("checking entry '%s'\n", existing_uris->lppszW[i])); */
253
mapistore_url = existing_uris->lppszW[i];
254
if (mapistore_url[strlen(mapistore_url)-1] != '/') {
257
current_entry = contexts_list;
258
while (!exists && current_entry) {
259
/* DEBUG(5, (" compare with '%s'\n", current_entry->url)); */
260
if (strcmp(mapistore_url, current_entry->url) == 0) {
261
/* DEBUG(5, (" entry found\n")); */
264
current_entry = current_entry->next;
267
DEBUG(5, (" removing entry '%s'\n", mapistore_url));
268
openchangedb_get_fid(emsmdbp_ctx->oc_ctx, mapistore_url, &found_fid);
269
openchangedb_delete_folder(emsmdbp_ctx->oc_ctx, found_fid);
274
container_classes = talloc_array(mem_ctx, const char *, MAPISTORE_MAX_ROLES);
275
for (i = MAPISTORE_MAIL_ROLE; i < MAPISTORE_MAX_ROLES; i++) {
276
container_classes[i] = "IPF.Note";
278
container_classes[MAPISTORE_CALENDAR_ROLE] = "IPF.Appointment";
279
container_classes[MAPISTORE_CONTACTS_ROLE] = "IPF.Contact";
280
container_classes[MAPISTORE_TASKS_ROLE] = "IPF.Task";
281
container_classes[MAPISTORE_NOTES_ROLE] = "IPF.StickyNote";
282
container_classes[MAPISTORE_JOURNAL_ROLE] = "IPF.Journal";
284
memset(&property_row, 0, sizeof(struct SRow));
285
memset(main_entries, 0, sizeof(struct mapistore_contexts_list *) * MAPISTORE_MAX_ROLES);
286
memset(secondary_entries, 0, sizeof(struct mapistore_contexts_list *) * MAPISTORE_MAX_ROLES);
288
/* Sort them between our main_entries and secondary_entries */
289
current_entry = contexts_list;
290
while (current_entry) {
291
next_entry = current_entry->next;
292
current_entry->next = NULL;
293
current_entry->prev = NULL;
294
if (current_entry->main_folder) {
295
if (main_entries[current_entry->role]) {
296
DEBUG(5, ("duplicate entry for role %d ignored\n existing entry: %s\n current entry: %s\n",
297
current_entry->role, main_entries[current_entry->role]->url, current_entry->url));
300
main_entries[current_entry->role] = current_entry;
304
DLIST_ADD_END(secondary_entries[current_entry->role], current_entry, void);
306
current_entry = next_entry;
309
/* Fallback role MUST exist */
310
if (!main_entries[MAPISTORE_FALLBACK_ROLE]) {
311
DEBUG(5, ("No fallback provisioning role was found while such role is mandatory. Provisiong must be done manually.\n"));
312
talloc_free(mem_ctx);
313
return MAPI_E_DISK_ERROR;
315
fallback_url = main_entries[MAPISTORE_FALLBACK_ROLE]->url;
316
if (fallback_url[strlen(fallback_url)-1] != '/') {
317
fallback_url = talloc_asprintf(mem_ctx, "%s/", fallback_url);
320
/* Mailbox and subfolders */
321
ret = openchangedb_get_SystemFolderID(emsmdbp_ctx->oc_ctx, username, EMSMDBP_MAILBOX_ROOT, &mailbox_fid);
322
if (ret != MAPI_E_SUCCESS) {
323
openchangedb_create_mailbox(emsmdbp_ctx->oc_ctx, username, EMSMDBP_MAILBOX_ROOT, &mailbox_fid);
325
property_row.lpProps = talloc_array(mem_ctx, struct SPropValue, 2); /* allocate max needed until the end of the function */
326
property_row.cValues = 1;
327
property_row.lpProps[0].ulPropTag = PR_DISPLAY_NAME_UNICODE;
328
for (i = EMSMDBP_DEFERRED_ACTION; i < EMSMDBP_TOP_INFORMATION_STORE; i++) {
329
/* TODO: mapistore_tag change */
330
ret = openchangedb_get_SystemFolderID(emsmdbp_ctx->oc_ctx, username, i, ¤t_fid);
331
if (ret != MAPI_E_SUCCESS) {
332
openchangedb_get_new_folderID(emsmdbp_ctx->oc_ctx, ¤t_fid);
333
openchangedb_get_new_changeNumber(emsmdbp_ctx->oc_ctx, ¤t_cn);
334
mapistore_url = talloc_asprintf(mem_ctx, "%s0x%"PRIx64"/", fallback_url, current_fid);
335
openchangedb_create_folder(emsmdbp_ctx->oc_ctx, mailbox_fid, current_fid, current_cn, mapistore_url, i);
336
property_row.lpProps->value.lpszW = folder_names[i];
337
openchangedb_set_folder_properties(emsmdbp_ctx->oc_ctx, current_fid, &property_row);
339
/* instantiate the new folder in the backend to make sure it is initialized properly */
340
retval = mapistore_add_context(emsmdbp_ctx->mstore_ctx, username, mapistore_url, current_fid, &context_id, &backend_object);
341
mapistore_indexing_record_add_fid(emsmdbp_ctx->mstore_ctx, context_id, username, current_fid);
342
mapistore_del_context(emsmdbp_ctx->mstore_ctx, context_id);
346
/* IPM and subfolders */
347
ret = openchangedb_get_SystemFolderID(emsmdbp_ctx->oc_ctx, username, EMSMDBP_TOP_INFORMATION_STORE, &ipm_fid);
348
if (ret != MAPI_E_SUCCESS) {
349
openchangedb_get_new_folderID(emsmdbp_ctx->oc_ctx, &ipm_fid);
350
openchangedb_get_new_changeNumber(emsmdbp_ctx->oc_ctx, ¤t_cn);
351
property_row.cValues = 2;
352
property_row.lpProps[1].ulPropTag = PR_SUBFOLDERS;
353
property_row.lpProps[0].value.lpszW = folder_names[EMSMDBP_TOP_INFORMATION_STORE];
354
property_row.lpProps[1].value.b = true;
355
openchangedb_create_folder(emsmdbp_ctx->oc_ctx, mailbox_fid, ipm_fid, current_cn, NULL, EMSMDBP_TOP_INFORMATION_STORE);
356
openchangedb_set_folder_properties(emsmdbp_ctx->oc_ctx, ipm_fid, &property_row);
357
openchangedb_set_ReceiveFolder(emsmdbp_ctx->oc_ctx, username, "IPC", mailbox_fid);
359
property_row.cValues = 2;
360
property_row.lpProps[1].ulPropTag = PR_CONTAINER_CLASS_UNICODE;
361
property_row.lpProps[1].value.lpszW = "IPF.Note";
362
/* TODO: mapistore_url/mapistore_tag change */
363
for (i = EMSMDBP_INBOX; i < EMSMDBP_MAX_MAILBOX_SYSTEMIDX; i++) {
364
ret = openchangedb_get_SystemFolderID(emsmdbp_ctx->oc_ctx, username, i, ¤t_fid);
365
if (ret == MAPI_E_SUCCESS) {
366
if (i == EMSMDBP_INBOX) {
367
inbox_fid = current_fid;
370
openchangedb_get_new_folderID(emsmdbp_ctx->oc_ctx, ¤t_fid);
371
openchangedb_get_new_changeNumber(emsmdbp_ctx->oc_ctx, ¤t_cn);
372
current_name = folder_names[i];
376
current_entry = main_entries[MAPISTORE_MAIL_ROLE];
377
inbox_fid = current_fid;
380
current_entry = main_entries[MAPISTORE_OUTBOX_ROLE];
382
case EMSMDBP_SENT_ITEMS:
383
current_entry = main_entries[MAPISTORE_SENTITEMS_ROLE];
385
case EMSMDBP_DELETED_ITEMS:
386
current_entry = main_entries[MAPISTORE_DELETEDITEMS_ROLE];
389
current_entry = NULL;
393
if (current_entry->name) {
394
current_name = current_entry->name;
396
mapistore_url = current_entry->url;
399
mapistore_url = talloc_asprintf(mem_ctx, "%s0x%"PRIx64"/", fallback_url, current_fid);
402
/* Ensure the name is unique */
403
base_name = current_name;
405
while (openchangedb_get_fid_by_name(emsmdbp_ctx->oc_ctx, ipm_fid, current_name, &found_fid) == MAPI_E_SUCCESS) {
406
current_name = talloc_asprintf(mem_ctx, "%s (%d)", base_name, j);
410
openchangedb_create_folder(emsmdbp_ctx->oc_ctx, ipm_fid, current_fid, current_cn, mapistore_url, i);
411
property_row.lpProps[0].value.lpszW = current_name;
412
openchangedb_set_folder_properties(emsmdbp_ctx->oc_ctx, current_fid, &property_row);
414
/* instantiate the new folder in the backend to make sure it is initialized properly */
415
retval = mapistore_add_context(emsmdbp_ctx->mstore_ctx, username, mapistore_url, current_fid, &context_id, &backend_object);
416
mapistore_indexing_record_add_fid(emsmdbp_ctx->mstore_ctx, context_id, username, current_fid);
417
mapistore_del_context(emsmdbp_ctx->mstore_ctx, context_id);
419
if (i == EMSMDBP_INBOX) {
420
/* set INBOX as receive folder for "All", "IPM", "Report.IPM" */
421
openchangedb_set_ReceiveFolder(emsmdbp_ctx->oc_ctx, username, "All", inbox_fid);
422
openchangedb_set_ReceiveFolder(emsmdbp_ctx->oc_ctx, username, "IPM", inbox_fid);
423
openchangedb_set_ReceiveFolder(emsmdbp_ctx->oc_ctx, username, "Report.IPM", inbox_fid);
428
/* Main special folders */
429
/* TODO: handle entryId change + mapistore_url/mapistore_tag change */
431
memset(&folder_entryid, 0, sizeof(struct FolderEntryId));
432
openchangedb_get_MailboxGuid(emsmdbp_ctx->oc_ctx, username, &folder_entryid.ProviderUID);
433
folder_entryid.FolderType = eitLTPrivateFolder;
434
openchangedb_get_MailboxReplica(emsmdbp_ctx->oc_ctx, username, NULL, &folder_entryid.FolderDatabaseGuid);
436
for (i = 0; i < nbr_special_folders; i++) {
437
current_folder = special_folders + i;
438
ret = openchangedb_get_folder_property(mem_ctx, emsmdbp_ctx->oc_ctx, current_folder->entryid_property, mailbox_fid, (void **) &entryId);
439
if (ret != MAPI_E_SUCCESS) {
440
property_row.cValues = 2;
441
property_row.lpProps[0].ulPropTag = PR_DISPLAY_NAME_UNICODE;
443
openchangedb_get_new_folderID(emsmdbp_ctx->oc_ctx, ¤t_fid);
444
openchangedb_get_new_changeNumber(emsmdbp_ctx->oc_ctx, ¤t_cn);
446
current_name = current_folder->name;
447
current_entry = main_entries[current_folder->role];
449
if (current_entry->name) {
450
current_name = current_entry->name;
452
mapistore_url = current_entry->url;
455
mapistore_url = talloc_asprintf(mem_ctx, "%s0x%"PRIx64"/", fallback_url, current_fid);
458
/* Ensure the name is unique */
459
base_name = current_name;
461
while (openchangedb_get_fid_by_name(emsmdbp_ctx->oc_ctx, ipm_fid, current_name, &found_fid) == MAPI_E_SUCCESS) {
462
current_name = talloc_asprintf(mem_ctx, "%s (%d)", base_name, j);
466
property_row.lpProps[0].value.lpszW = current_name;
467
property_row.lpProps[1].value.lpszW = container_classes[current_folder->role];
468
openchangedb_create_folder(emsmdbp_ctx->oc_ctx, ipm_fid, current_fid, current_cn, mapistore_url, i);
469
openchangedb_set_folder_properties(emsmdbp_ctx->oc_ctx, current_fid, &property_row);
471
/* instantiate the new folder in the backend to make sure it is initialized properly */
472
retval = mapistore_add_context(emsmdbp_ctx->mstore_ctx, username, mapistore_url, current_fid, &context_id, &backend_object);
473
mapistore_indexing_record_add_fid(emsmdbp_ctx->mstore_ctx, context_id, username, current_fid);
474
mapistore_del_context(emsmdbp_ctx->mstore_ctx, context_id);
476
/* set entryid on mailbox and inbox */
477
folder_entryid.FolderGlobalCounter.value = (current_fid >> 16);
478
ndr_push_struct_blob(&entryid_data, mem_ctx, &folder_entryid, (ndr_push_flags_fn_t)ndr_push_FolderEntryId);
479
property_row.cValues = 1;
480
property_row.lpProps[0].ulPropTag = current_folder->entryid_property;
481
property_row.lpProps[0].value.bin.cb = entryid_data.length;
482
property_row.lpProps[0].value.bin.lpb = entryid_data.data;
484
entryid_dump = ndr_print_struct_string(mem_ctx, (ndr_print_fn_t) ndr_print_FolderEntryId, current_name, &folder_entryid);
485
DEBUG(5, ("%s\n", entryid_dump));
487
openchangedb_set_folder_properties(emsmdbp_ctx->oc_ctx, mailbox_fid, &property_row);
488
openchangedb_set_folder_properties(emsmdbp_ctx->oc_ctx, inbox_fid, &property_row);
491
/* DEBUG(5, ("size of operation: %ld\n", talloc_total_size(mem_ctx))); */
493
/* secondary folders */
494
property_row.cValues = 2;
495
property_row.lpProps[0].ulPropTag = PR_DISPLAY_NAME_UNICODE;
497
for (i = MAPISTORE_MAIL_ROLE; i < MAPISTORE_MAX_ROLES; i++) {
498
/* secondary fallback roles are only used for synchronization */
499
if (i == MAPISTORE_FALLBACK_ROLE) {
503
property_row.lpProps[1].value.lpszW = container_classes[i];
504
current_entry = secondary_entries[i];
505
while (current_entry) {
506
mapistore_url = current_entry->url;
507
if (openchangedb_get_fid(emsmdbp_ctx->oc_ctx, mapistore_url, &found_fid) != MAPI_E_SUCCESS) {
508
/* DEBUG(5, ("creating secondary entry '%s'\n", current_entry->url)); */
509
openchangedb_get_new_folderID(emsmdbp_ctx->oc_ctx, ¤t_fid);
510
openchangedb_get_new_changeNumber(emsmdbp_ctx->oc_ctx, ¤t_cn);
512
current_name = current_entry->name;
513
/* Ensure the name is unique */
514
base_name = current_name;
516
while (openchangedb_get_fid_by_name(emsmdbp_ctx->oc_ctx, ipm_fid, current_name, &found_fid) == MAPI_E_SUCCESS) {
517
current_name = talloc_asprintf(mem_ctx, "%s (%d)", base_name, j);
520
property_row.lpProps[0].value.lpszW = current_name;
522
openchangedb_create_folder(emsmdbp_ctx->oc_ctx, ipm_fid, current_fid, current_cn, mapistore_url, -1);
523
openchangedb_set_folder_properties(emsmdbp_ctx->oc_ctx, current_fid, &property_row);
525
/* instantiate the new folder in the backend to make sure it is initialized properly */
526
retval = mapistore_add_context(emsmdbp_ctx->mstore_ctx, username, mapistore_url, current_fid, &context_id, &backend_object);
527
mapistore_indexing_record_add_fid(emsmdbp_ctx->mstore_ctx, context_id, username, current_fid);
528
mapistore_del_context(emsmdbp_ctx->mstore_ctx, context_id);
531
/* DEBUG(5, ("secondary entry '%s' already exists\n", current_entry->url)); */
533
current_entry = current_entry->next;
537
ldb_transaction_commit(emsmdbp_ctx->oc_ctx);
539
/* TODO: rename/create/delete folders at IPM level */
541
talloc_free(mem_ctx);
543
return MAPI_E_SUCCESS;