1fabd4b7a184715da1266839fe52b6d1f5e24a6d
[tridge/openchange.git] / branches / plugfest / mapiproxy / libmapiserver / libmapiserver_oxcprpt.c
1 /*
2    libmapiserver - MAPI library for Server side
3
4    OpenChange Project
5
6    Copyright (C) Julien Kerihuel 2009
7
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.
12    
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.
17    
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/>.
20  */
21
22 /**
23    \file libmapiserver_oxcprpt.c
24
25    \brief OXCPRPT ROP Response size calculations
26  */
27
28 #include "libmapiserver.h"
29 #include "libmapi/libmapi.h"
30 #include "libmapi/mapidefs.h"
31 #include "gen_ndr/ndr_exchange.h"
32 #include <util/debug.h>
33
34 /**
35    \details Calculate GetPropertiesSpecific Rop size
36
37    \param request pointer to the GetPropertiesSpecific
38    EcDoRpc_MAPI_REQ structure
39    \param response pointer to the GetPropertiesSpecific
40    EcDoRpc_MAPI_REPL structure
41
42    \return Size of GetPropsSpecific response
43  */
44 _PUBLIC_ uint16_t libmapiserver_RopGetPropertiesSpecific_size(struct EcDoRpc_MAPI_REQ *request,
45                                                               struct EcDoRpc_MAPI_REPL *response)
46 {
47         uint16_t        size = SIZE_DFLT_MAPI_RESPONSE;
48
49         if (!response || response->error_code) {
50                 return size;
51         }
52
53         size += SIZE_DFLT_ROPGETPROPERTIESSPECIFIC;
54         size += response->u.mapi_GetProps.prop_data.length;
55
56         return size;
57 }
58
59
60 /**
61    \details Calculate SetProperties Rop size
62
63    \param response pointer to the SetProperties EcDoRpc_MAPI_REPL
64    structure
65
66    \return Size of SetProperties response
67  */
68 _PUBLIC_ uint16_t libmapiserver_RopSetProperties_size(struct EcDoRpc_MAPI_REPL *response)
69 {
70         uint16_t        size = SIZE_DFLT_MAPI_RESPONSE;
71
72         if (!response || response->error_code) {
73                 return size;
74         }
75
76         size += SIZE_DFLT_ROPSETPROPERTIES;
77
78         if (response->u.mapi_SetProps.PropertyProblemCount) {
79                 size += response->u.mapi_SetProps.PropertyProblemCount * sizeof(struct PropertyProblem);
80         }
81
82         return size;
83 }
84
85
86 /**
87    \details Calculate SetProperties Rop size
88
89    \param response pointer to the SetProperties EcDoRpc_MAPI_REPL
90    structure
91
92    \return Size of SetProperties response
93  */
94 _PUBLIC_ uint16_t libmapiserver_RopDeleteProperties_size(struct EcDoRpc_MAPI_REPL *response)
95 {
96         uint16_t        size = SIZE_DFLT_MAPI_RESPONSE;
97
98         if (!response || response->error_code) {
99                 return size;
100         }
101
102         size += SIZE_DFLT_ROPDELETEPROPERTIES;
103
104         if (response->u.mapi_DeleteProps.PropertyProblemCount) {
105                 size += response->u.mapi_DeleteProps.PropertyProblemCount * sizeof(struct PropertyProblem);
106         }
107
108         return size;
109 }
110
111
112 /**
113    \details Calculate OpenStream Rop size
114
115    \param response pointer to the OpenStream EcDoRpc_MAPI_REPL
116    structure
117
118    \return Size of OpenStream response   
119  */
120 _PUBLIC_ uint16_t libmapiserver_RopOpenStream_size(struct EcDoRpc_MAPI_REPL *response)
121 {
122         uint16_t        size = SIZE_DFLT_MAPI_RESPONSE;
123
124         if (!response || response->error_code) {
125                 return size;
126         }
127
128         size += SIZE_DFLT_ROPOPENSTREAM;
129
130         return size;
131 }
132
133
134 /**
135    \details Calculate ReadStream Rop size
136
137    \param response pointer to the ReadStream EcDoRpc_MAPI_REPL
138    structure
139
140    \return Size of ReadStream response   
141  */
142 _PUBLIC_ uint16_t libmapiserver_RopReadStream_size(struct EcDoRpc_MAPI_REPL *response)
143 {
144         uint16_t        size = SIZE_DFLT_MAPI_RESPONSE;
145
146         if (!response || response->error_code) {
147                 return size;
148         }
149
150         size += SIZE_DFLT_ROPREADSTREAM;
151
152         if (response->u.mapi_ReadStream.data.length) {
153                 size += response->u.mapi_ReadStream.data.length;
154         }
155
156         return size;
157 }
158
159
160 /**
161    \details Calculate WriteStream Rop size
162
163    \param response pointer to the WriteStream EcDoRpc_MAPI_REPL
164    structure
165
166    \return Size of WriteStream response   
167  */
168 _PUBLIC_ uint16_t libmapiserver_RopWriteStream_size(struct EcDoRpc_MAPI_REPL *response)
169 {
170         uint16_t        size = SIZE_DFLT_MAPI_RESPONSE;
171
172         if (!response || response->error_code) {
173                 return size;
174         }
175
176         size += SIZE_DFLT_ROPWRITESTREAM;
177
178         return size;
179 }
180
181
182 /**
183    \details Calculate GetStreamSize Rop size
184
185    \param response pointer to the GetStreamSize
186    EcDoRpc_MAPI_REPL structure
187
188    \return Size of GetStreamSize response
189  */
190 _PUBLIC_ uint16_t libmapiserver_RopGetStreamSize_size(struct EcDoRpc_MAPI_REPL *response)
191 {
192         uint16_t        size = SIZE_DFLT_MAPI_RESPONSE;
193
194         if (!response || response->error_code) {
195                 return size;
196         }
197
198         size += SIZE_DFLT_ROPGETSTREAMSIZE;
199
200         return size;
201 }
202
203
204 /**
205    \details Calculate GetPropertyIdsFromNames Rop size
206
207    \param response pointer to the GetPropertyIdsFromNames
208    EcDoRpc_MAPI_REPL structure
209
210    \return Size of GetPropertyIdsFromNames response
211  */
212 _PUBLIC_ uint16_t libmapiserver_RopGetPropertyIdsFromNames_size(struct EcDoRpc_MAPI_REPL *response)
213 {
214         uint16_t        size = SIZE_DFLT_MAPI_RESPONSE;
215
216         if (!response || response->error_code) {
217                 return size;
218         }
219
220         size += SIZE_DFLT_ROPGETPROPERTYIDSFROMNAMES;
221
222         if (response->u.mapi_GetIDsFromNames.count) {
223                 size += response->u.mapi_GetIDsFromNames.count * sizeof (uint16_t);
224         }
225
226         return size;
227 }
228
229
230 /**
231    \details Calculate DeletePropertiesNoReplicate Rop size
232
233    \param response pointer to the DeletePropertiesNoReplicate
234    EcDoRpc_MAPI_REPL structure
235
236    \return Size of DeletePropertiesNoReplicate response
237  */
238 _PUBLIC_ uint16_t libmapiserver_RopDeletePropertiesNoReplicate_size(struct EcDoRpc_MAPI_REPL *response)
239 {
240         uint16_t        size = SIZE_DFLT_MAPI_RESPONSE;
241
242         if (!response || response->error_code) {
243                 return size;
244         }
245
246         size += SIZE_DFLT_ROPDELETEPROPERTIESNOREPLICATE;
247         size += (response->u.mapi_DeletePropertiesNoReplicate.PropertyProblemCount
248                  * (sizeof(uint16_t) /* PropertyProblem.Index */
249                     + sizeof(uint32_t) /* PropertyProblem.PropertyTag */
250                     + sizeof(uint32_t) /* PropertyProblem.ErrorCode */));
251
252         return size;
253 }
254
255
256 /**
257    \details Add a property value to a DATA blob. This convenient
258    function should be used when creating a GetPropertiesSpecific reply
259    response blob.
260
261    \param mem_ctx pointer to the memory context
262    \param iconv_convenience pointer to the iconv_convenience context
263    \param property the property tag which value is meant to be
264    appended to the blob
265    \param value generic pointer on the property value
266    \param blob the data blob the function uses to return the blob
267    \param layout whether values should be prefixed by a layout
268    \param flagged define if the properties are flagged or not
269
270    \note blob.length must be set to 0 before this function is called
271    the first time. Also the function only supports a limited set of
272    property types at the moment.
273
274    \return 0 on success;
275  */
276 _PUBLIC_ int libmapiserver_push_property(TALLOC_CTX *mem_ctx,
277                                          struct smb_iconv_convenience *iconv_convenience,
278                                          uint32_t property, 
279                                          const void *value, 
280                                          DATA_BLOB *blob,
281                                          uint8_t layout, 
282                                          uint8_t flagged)
283 {
284         struct ndr_push         *ndr;
285         
286         ndr = ndr_push_init_ctx(mem_ctx);
287         ndr_set_flags(&ndr->flags, LIBNDR_FLAG_NOALIGN);
288         ndr->offset = 0;
289         if (blob->length) {
290                 talloc_free(ndr->data);
291                 ndr->data = blob->data;
292                 ndr->offset = blob->length;
293         }
294
295         /* Step 1. Is the property flagged */
296         if (flagged) {
297                 switch (property & 0xFFFF) {
298                 case PT_ERROR:
299                         switch (layout) {
300                         case 0x1:
301                                 ndr_push_uint8(ndr, NDR_SCALARS, layout);
302                                 goto end;
303                         case PT_ERROR:
304                                 ndr_push_uint8(ndr, NDR_SCALARS, PT_ERROR);
305                                 break;
306                         }
307                         break;
308                 default:
309                         ndr_push_uint8(ndr, NDR_SCALARS, 0x0);
310                         break;
311                 }
312         } else {
313                 /* Step 2. Set the layout */
314                 if (layout) {
315                         switch (property & 0xFFFF) {
316                         case PT_ERROR:
317                                 ndr_push_uint8(ndr, NDR_SCALARS, PT_ERROR);
318                                 break;
319                         default:
320                                 ndr_push_uint8(ndr, NDR_SCALARS, 0x0);
321                         }
322                 }
323         }
324
325         /* Step 2. Push property data if supported */
326         switch (property & 0xFFFF) {
327         case PT_I2:
328                 ndr_push_uint16(ndr, NDR_SCALARS, *(uint16_t *) value);
329                 break;
330         case PT_LONG:
331         case PT_ERROR:
332         case PT_OBJECT:
333                 ndr_push_uint32(ndr, NDR_SCALARS, *(uint32_t *) value);
334                 break;
335         case PT_DOUBLE:
336                 ndr_push_double(ndr, NDR_SCALARS, *(double *) value);
337                 break;
338         case PT_I8:
339                 ndr_push_dlong(ndr, NDR_SCALARS, *(uint64_t *) value);
340                 break;
341         case PT_BOOLEAN:
342                 ndr_push_uint8(ndr, NDR_SCALARS, *(uint8_t *) value);
343                 break;
344         case PT_STRING8:
345                 ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM|LIBNDR_FLAG_STR_ASCII);
346                 ndr_push_string(ndr, NDR_SCALARS, (char *) value);
347                 break;
348         case PT_UNICODE:
349                 ndr_set_flags(&ndr->flags, LIBNDR_FLAG_STR_NULLTERM);
350                 ndr_push_string(ndr, NDR_SCALARS, (char *) value);
351                 break;
352         case PT_BINARY:
353                 ndr_push_SBinary_short(ndr, NDR_SCALARS, (struct SBinary_short *) value);
354                 break;
355         case PT_CLSID:
356                 ndr_push_GUID(ndr, NDR_SCALARS, (struct GUID *) value);
357                 break;
358         case PT_SYSTIME:
359                 ndr_push_FILETIME(ndr, NDR_SCALARS, (struct FILETIME *) value);
360                 break;
361         default:
362                 break;
363         }
364 end:
365         /* Step 3. Steal ndr context */
366         blob->data = ndr->data;
367         talloc_steal(mem_ctx, blob->data);
368         blob->length = ndr->offset;
369
370         talloc_free(ndr);
371         return 0;
372 }
373
374
375 /**
376    \details Turn request parameters to SPropValue array. This
377    convenient function should be used among MAPI ROPs that have
378    parameters which can be turned to MAPI properties and are stored
379    within backends.
380
381    \param mem_ctx pointer to the memory context
382    \param request generic pointer to the ROP request
383    \param opnum MAPI opnum identifying ROP contents
384
385    \note Developers must talloc_free returned SRow after they finish
386    using it.
387
388    \return Allocated SRow on success, otherwise NULL
389  */
390 _PUBLIC_ struct SRow *libmapiserver_ROP_request_to_properties(TALLOC_CTX *mem_ctx, 
391                                                               void *request, 
392                                                               uint8_t opnum)
393 {
394         struct SRow                     *aRow;
395         struct CreateFolder_req         *CreateFolder_req;
396
397         aRow = talloc_zero(mem_ctx, struct SRow);
398         aRow->lpProps = talloc_array(aRow, struct SPropValue, 2);
399         aRow->cValues = 0;
400
401         switch (opnum) {
402         case op_MAPI_CreateFolder:
403                 CreateFolder_req = (struct CreateFolder_req *) request;
404                 aRow->lpProps = add_SPropValue(mem_ctx, aRow->lpProps, &(aRow->cValues),
405                                                PR_FOLDER_TYPE, (void *)&(CreateFolder_req->ulFolderType));
406                 switch (CreateFolder_req->ulType) {
407                 case MAPI_FOLDER_ANSI:
408                         aRow->lpProps = add_SPropValue(mem_ctx, aRow->lpProps, &(aRow->cValues),
409                                                        PR_DISPLAY_NAME, (void *)(CreateFolder_req->FolderName.lpszA));
410                         aRow->lpProps = add_SPropValue(mem_ctx, aRow->lpProps, &(aRow->cValues),
411                                                        PR_COMMENT, (void *)(CreateFolder_req->FolderComment.lpszA));
412                         break;
413                 case MAPI_FOLDER_UNICODE:
414                         aRow->lpProps = add_SPropValue(mem_ctx, aRow->lpProps, &(aRow->cValues),
415                                                        PR_DISPLAY_NAME_UNICODE, (void *)(CreateFolder_req->FolderName.lpszW));
416                         aRow->lpProps = add_SPropValue(mem_ctx, aRow->lpProps, &(aRow->cValues),
417                                                        PR_COMMENT_UNICODE, (void *)(CreateFolder_req->FolderComment.lpszW));
418                         break;
419                 }
420                 
421                 break;
422         default:
423                 DEBUG(0, ("[%s:%d]: opnum %d not implemented yet\n", __FUNCTION__, __LINE__, opnum));
424                 talloc_free(aRow);
425                 return NULL;
426         }
427         
428         return aRow;
429 }