~ubuntu-branches/debian/experimental/openchange/experimental

« back to all changes in this revision

Viewing changes to .pc/debian-changes-1:0.9+svn1970-1/libmapi/emsmdb.c

  • Committer: Bazaar Package Importer
  • Author(s): Jelmer Vernooij, Mathieu Parent, Jelmer Vernooij
  • Date: 2010-06-19 00:14:54 UTC
  • mfrom: (1.2.1 upstream) (4.1.1 sid)
  • Revision ID: james.westby@ubuntu.com-20100619001454-c9qbwzlbv3rgqrir
Tags: 1:0.9+svn1970-1
[ Mathieu Parent ]
* Add Vcs-Browser
* libmapi-dev depends on libndr-standard-dev.
  Fix "Missing dependency on samba4-dev" (Closes: #549012)

[ Jelmer Vernooij ]
* Use source format version 3.
* Bump standards version to 3.8.4.
* New upstream snapshot.
* Add build dependency on zlib1g-dev. Closes: #577330
* Migrate packaging to Bazaar.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
   OpenChange MAPI implementation.
 
3
 
 
4
   Copyright (C) Julien Kerihuel 2005 - 2008.
 
5
   Copyright (C) Jelmer Vernooij 2005.
 
6
 
 
7
   This program is free software; you can redistribute it and/or modify
 
8
   it under the terms of the GNU General Public License as published by
 
9
   the Free Software Foundation; either version 3 of the License, or
 
10
   (at your option) any later version.
 
11
   
 
12
   This program is distributed in the hope that it will be useful,
 
13
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
   GNU General Public License for more details.
 
16
   
 
17
   You should have received a copy of the GNU General Public License
 
18
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
19
 */
 
20
 
 
21
#include <unistd.h>
 
22
#include <fcntl.h>
 
23
#include <libmapi/libmapi.h>
 
24
#include <libmapi/proto_private.h>
 
25
#include <gen_ndr/ndr_exchange.h>
 
26
#include <gen_ndr/ndr_exchange_c.h>
 
27
#include <gen_ndr/ndr_misc.h>
 
28
 
 
29
#include <param.h>
 
30
 
 
31
/**
 
32
   \file emsmdb.c
 
33
 
 
34
   \brief EMSMDB stack functions
 
35
 */
 
36
 
 
37
 
 
38
/**
 
39
   \details Hash a string and returns a unsigned integer hash value
 
40
 
 
41
   \param str the string to hash
 
42
 
 
43
   \return a hash value greater than 0 on success, otherwise 0
 
44
 
 
45
   \note This function is based on the hash algorithm from gdbm and
 
46
   from Samba4 TDB code.
 
47
 */
 
48
static unsigned int emsmdb_hash(const char *str)
 
49
{
 
50
        uint32_t        value;  /* Used to compute the hash value.  */
 
51
        uint32_t        i;      /* Used to cycle through random values. */
 
52
        uint32_t        len;
 
53
 
 
54
        /* Sanity check */
 
55
        if (!str) return 0;
 
56
 
 
57
        len = strlen(str);
 
58
 
 
59
        /* Set the initial value from the key size. */
 
60
        for (value = 0x238F13AF * len, i = 0; i < len; i++)
 
61
                value = (value + (str[i] << (i * 5 % 24)));
 
62
 
 
63
        return (1103515243 * value + 12345);  
 
64
}
 
65
 
 
66
 
 
67
/**
 
68
   \details Establishes a new Session Context with the server on the
 
69
   exchange_emsmdb pipe
 
70
 
 
71
   \param parent_mem_ctx pointer to the memory context
 
72
   \param session pointer to the MAPI session context
 
73
   \param p pointer to the DCERPC pipe
 
74
   \param cred pointer to the user credentials
 
75
   \param return_value pointer on EcDoConnect MAPI return value
 
76
 
 
77
   \return an allocated emsmdb_context on success, otherwise NULL
 
78
 */
 
79
struct emsmdb_context *emsmdb_connect(TALLOC_CTX *parent_mem_ctx, 
 
80
                                      struct mapi_session *session,
 
81
                                      struct dcerpc_pipe *p, 
 
82
                                      struct cli_credentials *cred,
 
83
                                      int *return_value)
 
84
{
 
85
        TALLOC_CTX              *mem_ctx;
 
86
        struct EcDoConnect      r;
 
87
        struct emsmdb_context   *ret;
 
88
        NTSTATUS                status;
 
89
        enum MAPISTATUS         retval;
 
90
        uint32_t                pullTimeStamp = 0;
 
91
 
 
92
        /* Sanity Checks */
 
93
        if (!session) return NULL;
 
94
        if (!p) return NULL;
 
95
        if (!cred) return NULL;
 
96
        if (!return_value) return NULL;
 
97
 
 
98
        mem_ctx = talloc_named(NULL, 0, "emsmdb_connect");
 
99
 
 
100
        ret = talloc_zero(parent_mem_ctx, struct emsmdb_context);
 
101
        ret->rpc_connection = p;
 
102
        ret->mem_ctx = parent_mem_ctx;
 
103
 
 
104
        ret->cache_requests = talloc(parent_mem_ctx, struct EcDoRpc_MAPI_REQ *);
 
105
        ret->info.szDisplayName = NULL;
 
106
        ret->info.szDNPrefix = NULL;
 
107
 
 
108
        r.in.szUserDN = session->profile->mailbox;
 
109
        r.in.ulFlags = 0x00000000;
 
110
        r.in.ulConMod = emsmdb_hash(r.in.szUserDN);
 
111
        r.in.cbLimit = 0x00000000;
 
112
        r.in.ulCpid = session->profile->codepage;
 
113
        r.in.ulLcidString = session->profile->language;
 
114
        r.in.ulLcidSort = session->profile->method;
 
115
        r.in.ulIcxrLink = 0xFFFFFFFF;
 
116
        r.in.usFCanConvertCodePages = 0x1;
 
117
        r.in.rgwClientVersion[0] = 0x000c;
 
118
        r.in.rgwClientVersion[1] = 0x183e;
 
119
        r.in.rgwClientVersion[2] = 0x03e8;
 
120
        r.in.pullTimeStamp = &pullTimeStamp;
 
121
 
 
122
        r.out.handle = &ret->handle;
 
123
        r.out.pcmsPollsMax = &ret->info.pcmsPollsMax;
 
124
        r.out.pcRetry = &ret->info.pcRetry;
 
125
        r.out.pcmsRetryDelay = &ret->info.pcmsRetryDelay;
 
126
        r.out.picxr = &ret->info.picxr;
 
127
        r.out.pullTimeStamp = &pullTimeStamp;
 
128
 
 
129
        status = dcerpc_EcDoConnect(p, mem_ctx, &r);
 
130
        retval = r.out.result;
 
131
        if (!NT_STATUS_IS_OK(status) || retval) {
 
132
                *return_value = retval;
 
133
                mapi_errstr("EcDoConnect", retval);
 
134
                talloc_free(mem_ctx);
 
135
                return NULL;
 
136
        }
 
137
 
 
138
        ret->info.szDisplayName = talloc_strdup(parent_mem_ctx, r.out.szDisplayName);
 
139
        ret->info.szDNPrefix = talloc_strdup(parent_mem_ctx, r.out.szDNPrefix);
 
140
 
 
141
        ret->info.rgwServerVersion[0] = r.out.rgwServerVersion[0];
 
142
        ret->info.rgwServerVersion[1] = r.out.rgwServerVersion[1];
 
143
        ret->info.rgwServerVersion[2] = r.out.rgwServerVersion[2];
 
144
 
 
145
        ret->cred = cred;
 
146
        ret->max_data = 0xFFF0;
 
147
        ret->setup = false;
 
148
 
 
149
        talloc_free(mem_ctx);
 
150
 
 
151
        return ret;
 
152
}
 
153
 
 
154
 
 
155
/**
 
156
   \details Destructor for the EMSMDB context. Call the EcDoDisconnect
 
157
   function.
 
158
 
 
159
   \param data generic pointer to data with mapi_provider information
 
160
 
 
161
   \return MAPI_E_SUCCESS on success, otherwise -1
 
162
 */
 
163
int emsmdb_disconnect_dtor(void *data)
 
164
{
 
165
        struct mapi_provider    *provider = (struct mapi_provider *)data;
 
166
        struct emsmdb_context   *emsmdb_ctx;
 
167
 
 
168
        emsmdb_ctx = (struct emsmdb_context *)provider->ctx;
 
169
        emsmdb_disconnect(provider->ctx);       
 
170
 
 
171
        talloc_free(emsmdb_ctx->cache_requests);
 
172
 
 
173
        if (emsmdb_ctx->info.szDisplayName) {
 
174
                talloc_free(emsmdb_ctx->info.szDisplayName);
 
175
        }
 
176
 
 
177
        if (emsmdb_ctx->info.szDNPrefix) {
 
178
                talloc_free(emsmdb_ctx->info.szDNPrefix);
 
179
        }
 
180
 
 
181
        return 0;
 
182
}
 
183
 
 
184
 
 
185
/**
 
186
   \details Destroy the EMSMDB context handle
 
187
 
 
188
   \param emsmdb_ctx pointer to the EMSMDB context
 
189
 
 
190
   \return MAPI_E_SUCCESS on success, otherwise MAPI error
 
191
 */
 
192
enum MAPISTATUS emsmdb_disconnect(struct emsmdb_context *emsmdb_ctx)
 
193
{
 
194
        NTSTATUS                status;
 
195
        enum MAPISTATUS         retval;
 
196
        struct EcDoDisconnect   r;
 
197
 
 
198
        /* Sanity Checks */
 
199
        OPENCHANGE_RETVAL_IF(!emsmdb_ctx, MAPI_E_NOT_INITIALIZED, NULL);
 
200
 
 
201
        r.in.handle = r.out.handle = &emsmdb_ctx->handle;
 
202
 
 
203
        status = dcerpc_EcDoDisconnect(emsmdb_ctx->rpc_connection, emsmdb_ctx, &r);
 
204
        retval = r.out.result;
 
205
        OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), retval, NULL);
 
206
        OPENCHANGE_RETVAL_IF(retval, retval, NULL);
 
207
 
 
208
        return MAPI_E_SUCCESS;
 
209
}
 
210
 
 
211
 
 
212
/**
 
213
   \details Send an empty MAPI packet - useful to keep connection up
 
214
   or force notifications.
 
215
 
 
216
   \param emsmdb_ctx pointer to the EMSMDB connection context
 
217
   \param res pointer on pointer to a MAPI response structure
 
218
 
 
219
   \return NT_STATUS_OK on success, otherwise NT status error
 
220
 */
 
221
_PUBLIC_ NTSTATUS emsmdb_transaction_null(struct emsmdb_context *emsmdb_ctx, 
 
222
                                          struct mapi_response **res)
 
223
{
 
224
        struct EcDoRpc          r;
 
225
        struct mapi_request     *mapi_request;
 
226
        struct mapi_response    *mapi_response;
 
227
        NTSTATUS                status;
 
228
        uint16_t                *length;
 
229
 
 
230
        /* Sanity checks */
 
231
        if(!emsmdb_ctx) return NT_STATUS_INVALID_PARAMETER;
 
232
        if (!res) return NT_STATUS_INVALID_PARAMETER;
 
233
 
 
234
        mapi_request = talloc_zero(emsmdb_ctx->mem_ctx, struct mapi_request);
 
235
        mapi_response = talloc_zero(emsmdb_ctx->mem_ctx, struct mapi_response);
 
236
 
 
237
        r.in.mapi_request = mapi_request;
 
238
        r.in.mapi_request->mapi_len = 2;
 
239
        r.in.mapi_request->length = 2;
 
240
 
 
241
        r.in.handle = r.out.handle = &emsmdb_ctx->handle;
 
242
        r.in.size = emsmdb_ctx->max_data;
 
243
        r.in.offset = 0x0;
 
244
        r.in.max_data = emsmdb_ctx->max_data;
 
245
        length = talloc_zero(emsmdb_ctx->mem_ctx, uint16_t);
 
246
        *length = r.in.mapi_request->mapi_len;
 
247
        r.in.length = r.out.length = length;
 
248
 
 
249
        r.out.mapi_response = mapi_response;
 
250
 
 
251
        status = dcerpc_EcDoRpc(emsmdb_ctx->rpc_connection, emsmdb_ctx->mem_ctx, &r);
 
252
        if (!MAPI_STATUS_IS_OK(NT_STATUS_V(status))) {
 
253
                return status;
 
254
        }
 
255
 
 
256
        *res = mapi_response;
 
257
 
 
258
        return status;
 
259
}
 
260
 
 
261
 
 
262
static int mapi_response_destructor(void *data)
 
263
{
 
264
        struct mapi_response    *mapi_response = (struct mapi_response *)data;
 
265
 
 
266
        if (!mapi_response) return 0;
 
267
 
 
268
        if (mapi_response->mapi_repl) {
 
269
                if (mapi_response->handles) {
 
270
                        talloc_free(mapi_response->handles);
 
271
                }
 
272
 
 
273
                if (!mapi_response->mapi_repl->error_code) {
 
274
                        talloc_free(mapi_response->mapi_repl);
 
275
                }
 
276
        }
 
277
 
 
278
        return 0;
 
279
}
 
280
 
 
281
 
 
282
/**
 
283
   \details Make a EMSMDB transaction.
 
284
 
 
285
   \param emsmdb_ctx pointer to the EMSMDB connection context
 
286
   \param mem_ctx pointer to the memory context
 
287
   \param req pointer to the MAPI request to send
 
288
   \param repl pointer on pointer to the MAPI reply returned by the
 
289
   server
 
290
 
 
291
   \return NT_STATUS_OK on success, otherwise NT status error
 
292
 */
 
293
_PUBLIC_ NTSTATUS emsmdb_transaction(struct emsmdb_context *emsmdb_ctx, 
 
294
                                     TALLOC_CTX *mem_ctx,
 
295
                                     struct mapi_request *req, 
 
296
                                     struct mapi_response **repl)
 
297
{
 
298
        struct EcDoRpc          r;
 
299
        struct mapi_response    *mapi_response;
 
300
        uint16_t                *length;
 
301
        NTSTATUS                status;
 
302
        struct EcDoRpc_MAPI_REQ *multi_req;
 
303
        uint8_t                 i = 0;
 
304
 
 
305
start:
 
306
        r.in.handle = r.out.handle = &emsmdb_ctx->handle;
 
307
        r.in.size = emsmdb_ctx->max_data;
 
308
        r.in.offset = 0x0;
 
309
 
 
310
        mapi_response = talloc_zero(emsmdb_ctx->mem_ctx, struct mapi_response);
 
311
        mapi_response->mapi_repl = NULL;
 
312
        mapi_response->handles = NULL;
 
313
        talloc_set_destructor((void *)mapi_response, (int (*)(void *))mapi_response_destructor);
 
314
        r.out.mapi_response = mapi_response;
 
315
 
 
316
        /* process cached data */
 
317
        if (emsmdb_ctx->cache_count) {
 
318
                multi_req = talloc_array(mem_ctx, struct EcDoRpc_MAPI_REQ, emsmdb_ctx->cache_count + 2);
 
319
                for (i = 0; i < emsmdb_ctx->cache_count; i++) {
 
320
                        multi_req[i] = *emsmdb_ctx->cache_requests[i];
 
321
                }
 
322
                multi_req[i] = req->mapi_req[0];
 
323
                req->mapi_req = multi_req;
 
324
        }
 
325
 
 
326
        req->mapi_req = talloc_realloc(mem_ctx, req->mapi_req, struct EcDoRpc_MAPI_REQ, emsmdb_ctx->cache_count + 2);
 
327
        req->mapi_req[i+1].opnum = 0;
 
328
 
 
329
        r.in.mapi_request = req;
 
330
        r.in.mapi_request->mapi_len += emsmdb_ctx->cache_size;
 
331
        r.in.mapi_request->length += emsmdb_ctx->cache_size;
 
332
        length = talloc_zero(mem_ctx, uint16_t);
 
333
        *length = r.in.mapi_request->mapi_len;
 
334
        r.in.length = r.out.length = length;
 
335
        r.in.max_data = (*length >= 0x4000) ? 0x7FFF : emsmdb_ctx->max_data;
 
336
 
 
337
        status = dcerpc_EcDoRpc(emsmdb_ctx->rpc_connection, mem_ctx, &r);
 
338
        if (!NT_STATUS_IS_OK(status)) {
 
339
                if (emsmdb_ctx->setup == false) {
 
340
                        errno = 0;
 
341
                        emsmdb_ctx->max_data = 0x7FFF;
 
342
                        emsmdb_ctx->setup = true;
 
343
                        talloc_free(mapi_response);
 
344
                        goto start;
 
345
                } else {
 
346
                        talloc_free(mapi_response);
 
347
                        return status;
 
348
                }
 
349
        } else {
 
350
                emsmdb_ctx->setup = true;
 
351
        }
 
352
        emsmdb_ctx->cache_size = emsmdb_ctx->cache_count = 0;
 
353
 
 
354
        if (r.out.mapi_response->mapi_repl && r.out.mapi_response->mapi_repl->error_code) {
 
355
                talloc_set_destructor((void *)mapi_response, NULL);
 
356
                r.out.mapi_response->handles = NULL;
 
357
        }
 
358
 
 
359
        *repl = r.out.mapi_response;
 
360
 
 
361
        return status;
 
362
}
 
363
 
 
364
 
 
365
/**
 
366
   \details Initialize the notify context structure and bind a local
 
367
   UDP port to receive notifications from the server
 
368
 
 
369
   \param mem_ctx pointer to the memory context
 
370
 
 
371
   \return an allocated mapi_notify_ctx structure on success,
 
372
   otherwise NULL
 
373
 */
 
374
struct mapi_notify_ctx *emsmdb_bind_notification(TALLOC_CTX *mem_ctx)
 
375
{
 
376
        struct interface        *ifaces;
 
377
        struct mapi_notify_ctx  *notify_ctx = NULL;
 
378
        unsigned short          port = DFLT_NOTIF_PORT;
 
379
        const char              *ipaddr = NULL;
 
380
        uint32_t                try = 0;
 
381
 
 
382
        /* Sanity Checks */
 
383
        if (!global_mapi_ctx) return NULL;
 
384
        if (!global_mapi_ctx->session) return NULL;
 
385
        if (!global_mapi_ctx->session->profile) return NULL;
 
386
 
 
387
        notify_ctx = talloc_zero(mem_ctx, struct mapi_notify_ctx);
 
388
 
 
389
        notify_ctx->notifications = talloc_zero((TALLOC_CTX *)notify_ctx, struct notifications);
 
390
        notify_ctx->notifications->prev = NULL;
 
391
        notify_ctx->notifications->next = NULL;
 
392
 
 
393
        load_interfaces(mem_ctx, lp_interfaces(global_mapi_ctx->lp_ctx), &ifaces);
 
394
        ipaddr = iface_best_ip(ifaces, global_mapi_ctx->session->profile->server);
 
395
        if (!ipaddr) {
 
396
                talloc_free(notify_ctx->notifications);
 
397
                talloc_free(notify_ctx);
 
398
                return NULL;
 
399
        }
 
400
        notify_ctx->addr = talloc_zero(mem_ctx, struct sockaddr);
 
401
        notify_ctx->addr->sa_family = AF_INET;
 
402
        ((struct sockaddr_in *)(notify_ctx->addr))->sin_addr.s_addr = inet_addr(ipaddr);
 
403
retry:
 
404
        if (try) port++;
 
405
        ((struct sockaddr_in *)(notify_ctx->addr))->sin_port = htons(port);
 
406
 
 
407
        notify_ctx->fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
 
408
        if (notify_ctx->fd == -1) {
 
409
                talloc_free(notify_ctx->notifications);
 
410
                talloc_free(notify_ctx->addr);
 
411
                talloc_free(notify_ctx);
 
412
                return NULL;
 
413
        }
 
414
 
 
415
        fcntl(notify_ctx->fd, F_SETFL, O_NONBLOCK);
 
416
 
 
417
        if (bind(notify_ctx->fd, notify_ctx->addr, sizeof(struct sockaddr)) == -1) {
 
418
                shutdown(notify_ctx->fd, SHUT_RDWR);
 
419
                close(notify_ctx->fd);
 
420
                if (try < 3) {
 
421
                        try++;
 
422
                        errno = 0;
 
423
                        goto retry;
 
424
                }
 
425
 
 
426
                talloc_free(notify_ctx->notifications);
 
427
                talloc_free(notify_ctx->addr);
 
428
                talloc_free(notify_ctx);
 
429
                return NULL;
 
430
        }
 
431
 
 
432
        return notify_ctx;
 
433
}
 
434
 
 
435
 
 
436
/**
 
437
   \details Register for notifications on the server
 
438
   
 
439
   \param session Pointer to the current MAPI session
 
440
   \param notifkey The opaque client-generated context data
 
441
   \param ulEventMask Notification flags. Exchange completely ignores
 
442
   this value and it should be set to 0
 
443
 
 
444
   \return NTSTATUS_OK on success, otherwise NT status error
 
445
 */
 
446
NTSTATUS emsmdb_register_notification(struct mapi_session *session,
 
447
                                      struct NOTIFKEY *notifkey, 
 
448
                                      uint16_t ulEventMask)
 
449
{
 
450
        struct EcRRegisterPushNotification      request;
 
451
        NTSTATUS                                status;
 
452
        enum MAPISTATUS                         retval;
 
453
        TALLOC_CTX                              *mem_ctx;
 
454
        struct emsmdb_context                   *emsmdb_ctx;
 
455
        struct mapi_notify_ctx                  *notify_ctx;
 
456
        struct policy_handle                    handle;
 
457
        uint32_t                                hNotification = 0;
 
458
 
 
459
        /* Sanity Checks*/
 
460
        if (!global_mapi_ctx) return NT_STATUS_INVALID_PARAMETER;
 
461
        if (!global_mapi_ctx->session) return NT_STATUS_INVALID_PARAMETER;
 
462
        if (!global_mapi_ctx->session->emsmdb) return NT_STATUS_INVALID_PARAMETER;
 
463
        if (!global_mapi_ctx->session->emsmdb->ctx) return NT_STATUS_INVALID_PARAMETER;
 
464
        if (!notifkey) return NT_STATUS_INVALID_PARAMETER;
 
465
 
 
466
        emsmdb_ctx = (struct emsmdb_context *)session->emsmdb->ctx;
 
467
        notify_ctx = (struct mapi_notify_ctx *)session->notify_ctx;
 
468
        mem_ctx = talloc_named(NULL, 0, "emsmdb_register_notification");
 
469
 
 
470
        request.in.handle = &emsmdb_ctx->handle;
 
471
        request.in.ulEventMask = ulEventMask;
 
472
        request.in.cbContext = notifkey->cb;
 
473
        request.in.rgbContext = talloc_array(mem_ctx, uint8_t, request.in.cbContext);
 
474
        memcpy(request.in.rgbContext, notifkey->ab, request.in.cbContext);
 
475
        request.in.grbitAdviseBits = 0xffffffff;
 
476
        request.in.rgCallbackAddress = talloc_array(mem_ctx, uint8_t, sizeof (struct sockaddr));
 
477
        /* cp address family and length */
 
478
        request.in.rgCallbackAddress[0] = (notify_ctx->addr->sa_family & 0xFF);
 
479
        request.in.rgCallbackAddress[1] = (notify_ctx->addr->sa_family & 0xFF00) >> 8;
 
480
        memcpy(&request.in.rgCallbackAddress[2], notify_ctx->addr->sa_data, 14);
 
481
        request.in.cbCallbackAddress = sizeof (struct sockaddr);
 
482
 
 
483
        request.out.handle = &handle;
 
484
        request.out.hNotification = &hNotification;
 
485
 
 
486
        status = dcerpc_EcRRegisterPushNotification(emsmdb_ctx->rpc_connection, emsmdb_ctx->mem_ctx, &request);
 
487
        retval = request.out.result;
 
488
        if (!NT_STATUS_IS_OK(status) || retval) {
 
489
                talloc_free(mem_ctx);
 
490
                return status;
 
491
        }
 
492
 
 
493
        talloc_free(mem_ctx);
 
494
 
 
495
        return status;
 
496
}
 
497
 
 
498
 
 
499
/**
 
500
   \details Retrieves the EMSMDB context server information structure
 
501
 
 
502
   \param session pointer to the MAPI session context
 
503
 
 
504
   \return the server info structure on success, otherwise NULL
 
505
 */
 
506
_PUBLIC_ struct emsmdb_info *emsmdb_get_info(struct mapi_session *session)
 
507
{
 
508
        if (!global_mapi_ctx || !session->emsmdb->ctx) {
 
509
                return NULL;
 
510
        }
 
511
 
 
512
        return &((struct emsmdb_context *)session->emsmdb->ctx)->info;
 
513
}
 
514
 
 
515
 
 
516
/**
 
517
   \details Free property values retrieved with pull_emsmdb_property
 
518
 
 
519
   \param lpProp pointer to SPropValue structure
 
520
   \param data generic pointer to associated lpProp data
 
521
 
 
522
 */
 
523
void free_emsmdb_property(struct SPropValue *lpProp, void *data)
 
524
{
 
525
        if (!data) return;
 
526
        if (!lpProp) return;
 
527
 
 
528
        switch (lpProp->ulPropTag & 0xFFFF) {
 
529
        case PT_I2:
 
530
                talloc_free((uint16_t *)data);
 
531
                break;
 
532
        case PT_ERROR:
 
533
        case PT_LONG:
 
534
                talloc_free((uint32_t *)data);
 
535
                break;
 
536
        case PT_I8:
 
537
                talloc_free((uint64_t *)data);
 
538
                break;
 
539
        case PT_BOOLEAN:
 
540
                talloc_free((uint8_t *)data);
 
541
                break;
 
542
        default:
 
543
                break;
 
544
                
 
545
        }
 
546
}
 
547
 
 
548
 
 
549
/**
 
550
   \details Retrieves a property value from a DATA blob
 
551
 
 
552
   \param mem_ctx pointer to the memory context
 
553
   \param lp_ctx pointer to the loadparm context
 
554
   \param offset pointer on pointer to the current offset
 
555
   \param tag the property tag which value is to be retrieved
 
556
   \param data pointer to the data
 
557
 
 
558
   \return pointer on constant generic data on success, otherwise NULL
 
559
 */
 
560
const void *pull_emsmdb_property(TALLOC_CTX *mem_ctx,
 
561
                                 struct loadparm_context *lp_ctx,
 
562
                                 uint32_t *offset, 
 
563
                                 enum MAPITAGS tag, 
 
564
                                 DATA_BLOB *data)
 
565
{
 
566
        struct ndr_pull                 *ndr;
 
567
        const char                      *pt_string8;
 
568
        const char                      *pt_unicode;
 
569
        uint16_t                        *pt_i2;
 
570
        uint64_t                        *pt_i8;
 
571
        uint32_t                        *pt_long;
 
572
        uint8_t                         *pt_boolean;
 
573
        double                          *pt_double;
 
574
        struct FILETIME                 *pt_filetime;
 
575
        struct GUID                     *pt_clsid;
 
576
        struct SBinary_short            pt_binary;
 
577
        struct Binary_r                 *sbin;
 
578
        struct mapi_SLPSTRArray         pt_slpstr;
 
579
        struct StringArray_r            *slpstr;
 
580
        struct mapi_MV_LONG_STRUCT      pt_MVl;
 
581
        struct LongArray_r              *MVl;
 
582
        struct mapi_SBinaryArray        pt_MVbin;
 
583
        struct BinaryArray_r            *MVbin;
 
584
        uint32_t                        i;
 
585
 
 
586
        ndr = talloc_zero(mem_ctx, struct ndr_pull);
 
587
        ndr->offset = *offset;
 
588
        ndr->data = data->data;
 
589
        ndr->data_size = data->length;
 
590
        ndr_set_flags(&ndr->flags, LIBNDR_FLAG_NOALIGN);
 
591
        ndr->iconv_convenience = lp_iconv_convenience(lp_ctx);
 
592
 
 
593
        switch(tag & 0xFFFF) {
 
594
        case PT_I2:
 
595
                pt_i2 = talloc_zero(mem_ctx, uint16_t);
 
596
                ndr_pull_uint16(ndr, NDR_SCALARS, pt_i2);
 
597
                *offset = ndr->offset;
 
598
                talloc_free(ndr);
 
599
                return (const void *) pt_i2;
 
600
        case PT_ERROR:
 
601
        case PT_LONG:
 
602
                pt_long = talloc_zero(mem_ctx, uint32_t);
 
603
                ndr_pull_uint32(ndr, NDR_SCALARS, pt_long);
 
604
                *offset = ndr->offset;
 
605
                talloc_free(ndr);
 
606
                return (const void *) pt_long;
 
607
        case PT_BOOLEAN:
 
608
                pt_boolean = talloc_zero(mem_ctx, uint8_t);
 
609
                ndr_pull_uint8(ndr, NDR_SCALARS, pt_boolean);
 
610
                *offset = ndr->offset;
 
611
                talloc_free(ndr);
 
612
                return (const void *) pt_boolean;
 
613
        case PT_I8:
 
614
                pt_i8 = talloc_zero(mem_ctx, uint64_t);
 
615
                ndr_pull_hyper(ndr, NDR_SCALARS, pt_i8);
 
616
                *offset = ndr->offset;
 
617
                talloc_free(ndr);
 
618
                return (const void *) pt_i8;
 
619
        case PT_DOUBLE:
 
620
                pt_double = talloc_zero(mem_ctx, double);
 
621
                ndr_pull_double(ndr, NDR_SCALARS, pt_double);
 
622
                *offset = ndr->offset;
 
623
                talloc_free(ndr);
 
624
                return (const void *) pt_double;
 
625
        case PT_UNICODE:
 
626
                ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
 
627
                ndr_pull_string(ndr, NDR_SCALARS, &pt_unicode);
 
628
                *offset = ndr->offset;
 
629
                talloc_free(ndr);
 
630
                return (const void *) pt_unicode;
 
631
        case PT_STRING8:
 
632
                ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_ASCII|LIBNDR_FLAG_STR_NULLTERM);
 
633
                ndr_pull_string(ndr, NDR_SCALARS, &pt_string8);
 
634
                *offset = ndr->offset;
 
635
                talloc_free(ndr);
 
636
                return (const void *) pt_string8;
 
637
        case PT_SYSTIME:
 
638
                pt_filetime = talloc_zero(mem_ctx, struct FILETIME);
 
639
                ndr_pull_hyper(ndr, NDR_SCALARS, (uint64_t *) pt_filetime);
 
640
                *offset = ndr->offset;
 
641
                talloc_free(ndr);
 
642
                return (const void *) pt_filetime;
 
643
        case PT_CLSID:
 
644
                pt_clsid = talloc_zero(mem_ctx, struct GUID);
 
645
                ndr_pull_GUID(ndr, NDR_SCALARS, pt_clsid);
 
646
                *offset = ndr->offset;
 
647
                talloc_free(ndr);
 
648
                return (const void *) pt_clsid;
 
649
        case 0xFB:
 
650
        case PT_BINARY:
 
651
                ndr_pull_SBinary_short(ndr, NDR_SCALARS, &pt_binary);
 
652
                *offset = ndr->offset;
 
653
                sbin = talloc_zero(mem_ctx, struct Binary_r);
 
654
                sbin->cb = pt_binary.cb;
 
655
                sbin->lpb = talloc_memdup(sbin, pt_binary.lpb, pt_binary.cb);
 
656
                talloc_free(ndr);
 
657
                return (const void *) sbin;
 
658
        case PT_MV_LONG:
 
659
                ndr_pull_mapi_MV_LONG_STRUCT(ndr, NDR_SCALARS, &pt_MVl);
 
660
                *offset = ndr->offset;
 
661
                MVl = talloc_zero(mem_ctx, struct LongArray_r);
 
662
                MVl->cValues = pt_MVl.cValues;
 
663
                MVl->lpl = talloc_array(mem_ctx, uint32_t, pt_MVl.cValues);
 
664
                for (i = 0; i < MVl->cValues; i++) {
 
665
                        MVl->lpl[i] = pt_MVl.lpl[i];
 
666
                }
 
667
                talloc_free(ndr);
 
668
                return (const void *) MVl;
 
669
        case PT_MV_STRING8:
 
670
                ndr_pull_mapi_SLPSTRArray(ndr, NDR_SCALARS, &pt_slpstr);
 
671
                *offset = ndr->offset;
 
672
                slpstr = talloc_zero(mem_ctx, struct StringArray_r);
 
673
                slpstr->cValues = pt_slpstr.cValues;
 
674
                slpstr->lppszA = talloc_array(mem_ctx, const char *, pt_slpstr.cValues);
 
675
                for (i = 0; i < slpstr->cValues; i++) {
 
676
                        slpstr->lppszA[i] = talloc_strdup(mem_ctx, pt_slpstr.strings[i].lppszA);
 
677
                }
 
678
                talloc_free(ndr);
 
679
                return (const void *) slpstr;
 
680
        case PT_MV_BINARY:
 
681
                ndr_pull_mapi_SBinaryArray(ndr, NDR_SCALARS, &pt_MVbin);
 
682
                *offset = ndr->offset;
 
683
                MVbin = talloc_zero(mem_ctx, struct BinaryArray_r);
 
684
                MVbin->cValues = pt_MVbin.cValues;
 
685
                MVbin->lpbin = talloc_array(mem_ctx, struct Binary_r, pt_MVbin.cValues);
 
686
                for (i = 0; i < MVbin->cValues; i++) {
 
687
                        MVbin->lpbin[i].cb = pt_MVbin.bin[i].cb;
 
688
                        MVbin->lpbin[i].lpb = talloc_size(mem_ctx, MVbin->lpbin[i].cb);
 
689
                        memcpy(MVbin->lpbin[i].lpb, pt_MVbin.bin[i].lpb, MVbin->lpbin[i].cb);
 
690
                }
 
691
                talloc_free(ndr);
 
692
                return (const void *) MVbin;
 
693
        default:
 
694
                fprintf (stderr, "unhandled type case in pull_emsmdb_property(): 0x%x\n", (tag & 0xFFFF));
 
695
                return NULL;
 
696
        }
 
697
}
 
698
 
 
699
 
 
700
/**
 
701
   \details Get a SPropValue array from a DATA blob
 
702
 
 
703
   \param mem_ctx pointer to the memory context
 
704
   \param lp_ctx pointer to the loadparm context
 
705
   \param content pointer to the DATA blob content
 
706
   \param tags pointer to a list of property tags to lookup
 
707
   \param propvals pointer on pointer to the returned SPropValues
 
708
   \param cn_propvals pointer to the number of propvals
 
709
   \param flag describes the type data
 
710
 
 
711
   \return MAPI_E_SUCCESS on success
 
712
 */
 
713
enum MAPISTATUS emsmdb_get_SPropValue(TALLOC_CTX *mem_ctx,
 
714
                                      struct loadparm_context *lp_ctx,
 
715
                                      DATA_BLOB *content,
 
716
                                      struct SPropTagArray *tags,
 
717
                                      struct SPropValue **propvals, 
 
718
                                      uint32_t *cn_propvals,
 
719
                                      uint8_t flag)
 
720
{
 
721
        struct SPropValue       *p_propval;
 
722
        uint32_t                i_propval;
 
723
        uint32_t                i_tag;
 
724
        uint32_t                cn_tags;
 
725
        uint32_t                offset = 0;
 
726
        const void              *data;
 
727
 
 
728
        i_propval = 0;
 
729
        cn_tags = tags->cValues;
 
730
        *cn_propvals = 0;
 
731
        *propvals = talloc_array(mem_ctx, struct SPropValue, cn_tags + 1);
 
732
 
 
733
        for (i_tag = 0; i_tag < cn_tags; i_tag++) {
 
734
                if (flag) { 
 
735
                        if (((uint8_t)(*(content->data + offset))) == PT_ERROR) {
 
736
                                tags->aulPropTag[i_tag] &= 0xFFFF0000;
 
737
                                tags->aulPropTag[i_tag] |= PT_ERROR;
 
738
                        }
 
739
                        offset += sizeof (uint8_t);
 
740
                }
 
741
 
 
742
                data = pull_emsmdb_property(mem_ctx, lp_ctx, &offset, tags->aulPropTag[i_tag], content);
 
743
                if (data) {
 
744
                        data = talloc_steal(*propvals, data);
 
745
                        p_propval = &((*propvals)[i_propval]);
 
746
                        p_propval->ulPropTag = tags->aulPropTag[i_tag];
 
747
                        p_propval->dwAlignPad = 0x0;
 
748
 
 
749
                        set_SPropValue(p_propval, data);
 
750
                        free_emsmdb_property(p_propval, (void *) data);
 
751
                        i_propval++;
 
752
                }
 
753
        }
 
754
 
 
755
        (*propvals)[i_propval].ulPropTag = 0x0;
 
756
        *cn_propvals = i_propval;
 
757
        return MAPI_E_SUCCESS;
 
758
}
 
759
 
 
760
 
 
761
/**
 
762
   \details Get a SRowSet from a DATA blob
 
763
 
 
764
   \param mem_ctx pointer on the memory context
 
765
   \param lp_ctx pointer on the loadparm context
 
766
   \param rowset pointer on the returned SRowSe
 
767
   \param proptags pointer on a list of property tags to lookup
 
768
   \param content pointer on the DATA blob content
 
769
 
 
770
   \return MAPI_E_SUCCESS on success
 
771
 
 
772
   \note TODO: this doesn't yet handle the TypedPropertyValue and
 
773
   FlaggedPropertyValueWithTypeSpecified variants
 
774
 */
 
775
_PUBLIC_ void emsmdb_get_SRowSet(TALLOC_CTX *mem_ctx,
 
776
                                 struct loadparm_context *lp_ctx,
 
777
                                 struct SRowSet *rowset, 
 
778
                                 struct SPropTagArray *proptags, 
 
779
                                 DATA_BLOB *content)
 
780
{
 
781
        struct SRow             *rows;
 
782
        struct SPropValue       *lpProps;
 
783
        uint32_t                idx;
 
784
        uint32_t                prop;
 
785
        uint32_t                offset = 0;
 
786
        const void              *data;
 
787
        uint32_t                row_count;
 
788
        bool                    is_FlaggedPropertyRow = false;
 
789
        bool                    havePropertyValue;
 
790
        uint8_t                 flag;
 
791
 
 
792
        /* caller allocated */
 
793
        rows = rowset->aRow;
 
794
        row_count = rowset->cRows;
 
795
 
 
796
        for (idx = 0; idx < row_count; idx++) {
 
797
                if (0x1 == *(content->data + offset)) {
 
798
                        is_FlaggedPropertyRow = true;
 
799
                } else {
 
800
                        is_FlaggedPropertyRow = false;
 
801
                }
 
802
                ++offset;
 
803
 
 
804
                lpProps = talloc_array(mem_ctx, struct SPropValue, proptags->cValues);
 
805
                for (prop = 0; prop < proptags->cValues; prop++) {
 
806
                        havePropertyValue = true;
 
807
                        lpProps[prop].ulPropTag = proptags->aulPropTag[prop];
 
808
                        if (is_FlaggedPropertyRow) {
 
809
                                flag = (uint8_t)(*(content->data + offset));
 
810
                                ++offset; /* advance offset for the flag */
 
811
                                switch (flag) {
 
812
                                case 0x0:
 
813
                                        /* Property Value is valid */
 
814
                                        break;
 
815
                                case 0x1:
 
816
                                        /* Property Value is not present */
 
817
                                        havePropertyValue = false;
 
818
                                        break;
 
819
                                case PT_ERROR:
 
820
                                        lpProps[prop].ulPropTag = proptags->aulPropTag[prop];
 
821
                                        lpProps[prop].ulPropTag &= 0xFFFF0000;
 
822
                                        lpProps[prop].ulPropTag |= PT_ERROR;
 
823
                                        break;
 
824
                                default:
 
825
                                        /* unknown FlaggedPropertyValue flag */
 
826
                                        break;
 
827
 
 
828
                                }
 
829
                        }
 
830
                        if (havePropertyValue) {
 
831
                                lpProps[prop].dwAlignPad = 0x0;
 
832
                                data = pull_emsmdb_property(mem_ctx, lp_ctx, &offset, lpProps[prop].ulPropTag, content);
 
833
                                talloc_steal(lpProps, data);
 
834
                                set_SPropValue(&lpProps[prop], data);
 
835
                                free_emsmdb_property(&lpProps[prop], (void *) data);
 
836
                        }
 
837
                }
 
838
 
 
839
                rows[idx].ulAdrEntryPad = 0;
 
840
                rows[idx].cValues = proptags->cValues;
 
841
                rows[idx].lpProps = lpProps;
 
842
        }
 
843
}
 
844
 
 
845
 
 
846
/**
 
847
   \details Get a SRow from a DATA blob
 
848
 
 
849
   \param mem_ctx pointer on the memory context
 
850
   \param lp_ctx pointer on the loadparm context
 
851
   \param aRow pointer on the returned SRow
 
852
   \param proptags pointer on a list of property tags to lookup
 
853
   \param propcount number of SPropValue entries in aRow
 
854
   \param content pointer on the DATA blob content
 
855
   \param flag the type data
 
856
   \param align alignment pad
 
857
 
 
858
   \return MAPI_E_SUCCESS on success
 
859
 
 
860
   \note TODO: We shouldn't have any alignment pad here
 
861
 */
 
862
void emsmdb_get_SRow(TALLOC_CTX *mem_ctx,
 
863
                     struct loadparm_context *lp_ctx,
 
864
                     struct SRow *aRow, 
 
865
                     struct SPropTagArray *proptags, 
 
866
                     uint16_t propcount, 
 
867
                     DATA_BLOB *content, 
 
868
                     uint8_t flag, 
 
869
                     uint8_t align)
 
870
{
 
871
        uint32_t                i;
 
872
        uint32_t                offset = 0;
 
873
        uint32_t                aulPropTag = 0;
 
874
        const void              *data;
 
875
 
 
876
        aRow->cValues = propcount;
 
877
        aRow->lpProps = talloc_array(mem_ctx, struct SPropValue, propcount);
 
878
 
 
879
        for (i = 0; i < propcount; i++) {
 
880
                aulPropTag = proptags->aulPropTag[i];
 
881
                if (flag) {
 
882
                        if (((uint8_t)(*(content->data + offset))) == PT_ERROR) {
 
883
                                aulPropTag &= 0xFFFF0000;
 
884
                                aulPropTag |= 0xA;                      
 
885
                        }
 
886
                        offset += align;
 
887
                } 
 
888
 
 
889
                data = pull_emsmdb_property(mem_ctx, lp_ctx, &offset, aulPropTag, content);
 
890
                talloc_steal(aRow->lpProps, data);
 
891
                aRow->lpProps[i].ulPropTag = aulPropTag;
 
892
                aRow->lpProps[i].dwAlignPad = 0x0;
 
893
                set_SPropValue(&(aRow->lpProps[i]), data);
 
894
                free_emsmdb_property(&aRow->lpProps[i], (void *) data);
 
895
        }
 
896
        if (align) {
 
897
                offset += align;
 
898
        }
 
899
}