fad4e85a1bf13b2f4c96b2e3628eb4a02e559b60
[jelmer/openchange.git] / torture / mapi_common.c
1 /*
2    OpenChange MAPI torture suite implementation.
3
4    Common MAPI and torture related operations
5
6    Copyright (C) Julien Kerihuel 2007.
7    Copyright (C) Fabien Le Mentec 2007.
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  */
22
23 #include <libmapi/libmapi.h>
24 #include <torture/mapi_torture.h>
25 #include <torture.h>
26 #include <torture/torture_proto.h>
27 #include <torture/mapi_torture.h>
28 #include <param.h>
29
30 const char *get_filename(const char *filename)
31 {
32         const char *substr;
33
34         substr = rindex(filename, '/');
35         if (substr) return substr;
36
37         return filename;
38 }
39
40 const char **get_cmdline_recipients(TALLOC_CTX *mem_ctx, const char *type)
41 {
42         const char      **usernames;
43         const char      *recipients;
44         char            *tmp = NULL;
45         uint32_t        j = 0;
46
47         if (!type) {
48                 return 0;
49         }
50
51         recipients = lp_parm_string(global_mapi_ctx->lp_ctx, NULL, "mapi", type);
52
53         /* no recipients */
54         if (recipients == 0) {
55                 printf("no recipients specified for %s\n", type);
56                 return 0;
57         }
58
59         if ((tmp = strtok((char *)recipients, ",")) == NULL) {
60                 DEBUG(2, ("Invalid mapi:%s string format\n", type));
61                 return NULL;
62         }
63         
64         usernames = talloc_array(mem_ctx, const char *, 2);
65         usernames[0] = strdup(tmp);
66         
67         for (j = 1; (tmp = strtok(NULL, ",")) != NULL; j++) {
68                 usernames = talloc_realloc(mem_ctx, usernames, const char *, j+2);
69                 usernames[j] = strdup(tmp);
70         }
71         usernames[j] = 0;
72
73         return usernames;
74 }
75
76 const char **collapse_recipients(TALLOC_CTX *mem_ctx, const char **to, const char **cc, const char **bcc)
77 {
78         uint32_t        count;
79         uint32_t        i;
80         const char      **usernames;
81
82         if (!to && !cc && !bcc) return NULL;
83
84         count = 0;
85         for (i = 0; to && to[i]; i++,  count++);
86         for (i = 0; cc && cc[i]; i++,  count++);
87         for (i = 0; bcc && bcc[i]; i++, count++);
88
89         usernames = talloc_array(mem_ctx, const char *, count + 1);
90         count = 0;
91
92         for (i = 0; to && to[i]; i++, count++) {
93                 usernames[count] = talloc_strdup(mem_ctx, to[i]);
94         }
95
96         for (i = 0; cc && cc[i]; i++, count++) {
97                 usernames[count] = talloc_strdup(mem_ctx, cc[i]);
98         }
99
100         for (i = 0; bcc && bcc[i]; i++, count++) {
101                 usernames[count] = talloc_strdup(mem_ctx, bcc[i]);
102         }
103
104         usernames[count++] = 0;
105
106         return usernames;
107 }
108
109 static bool set_external_recipients(TALLOC_CTX *mem_ctx, struct SRowSet *SRowSet, const char *username, enum ulRecipClass RecipClass)
110 {
111         uint32_t                last;
112         struct SPropValue       SPropValue;
113
114         SRowSet->aRow = talloc_realloc(mem_ctx, SRowSet->aRow, struct SRow, SRowSet->cRows + 2);
115         last = SRowSet->cRows;
116         SRowSet->aRow[last].cValues = 0;
117         SRowSet->aRow[last].lpProps = talloc_zero(mem_ctx, struct SPropValue);
118         
119         /* PR_OBJECT_TYPE */
120         SPropValue.ulPropTag = PR_OBJECT_TYPE;
121         SPropValue.value.l = MAPI_MAILUSER;
122         SRow_addprop(&(SRowSet->aRow[last]), SPropValue);
123
124         /* PR_DISPLAY_TYPE */
125         SPropValue.ulPropTag = PR_DISPLAY_TYPE;
126         SPropValue.value.l = 0;
127         SRow_addprop(&(SRowSet->aRow[last]), SPropValue);
128
129         /* PR_GIVEN_NAME */
130         SPropValue.ulPropTag = PR_GIVEN_NAME;
131         SPropValue.value.lpszA = username;
132         SRow_addprop(&(SRowSet->aRow[last]), SPropValue);
133
134         /* PR_DISPLAY_NAME */
135         SPropValue.ulPropTag = PR_DISPLAY_NAME;
136         SPropValue.value.lpszA = username;
137         SRow_addprop(&(SRowSet->aRow[last]), SPropValue);
138
139         /* PR_7BIT_DISPLAY_NAME */
140         SPropValue.ulPropTag = PR_7BIT_DISPLAY_NAME;
141         SPropValue.value.lpszA = username;
142         SRow_addprop(&(SRowSet->aRow[last]), SPropValue);
143
144         /* PR_SMTP_ADDRESS */
145         SPropValue.ulPropTag = PR_SMTP_ADDRESS;
146         SPropValue.value.lpszA = username;
147         SRow_addprop(&(SRowSet->aRow[last]), SPropValue);
148
149         /* PR_ADDRTYPE */
150         SPropValue.ulPropTag = PR_ADDRTYPE;
151         SPropValue.value.lpszA = "SMTP";
152         SRow_addprop(&(SRowSet->aRow[last]), SPropValue);
153
154         SetRecipientType(&(SRowSet->aRow[last]), RecipClass);
155
156         SRowSet->cRows += 1;
157         return true;
158 }
159
160 bool set_usernames_RecipientType(TALLOC_CTX *mem_ctx, uint32_t *index, struct SRowSet *rowset, 
161                                         const char **usernames, struct SPropTagArray *flaglist,
162                                         enum ulRecipClass RecipClass)
163 {
164         uint32_t        i;
165         uint32_t        count = *index;
166         static uint32_t counter = 0;
167
168         if (count == 0) counter = 0;
169         if (!usernames) return false;
170
171         for (i = 0; usernames[i]; i++) {
172                 if (flaglist->aulPropTag[count] == MAPI_UNRESOLVED) {
173                         set_external_recipients(mem_ctx, rowset, usernames[i], RecipClass);
174                 }
175                 if (flaglist->aulPropTag[count] == MAPI_RESOLVED) {
176                         SetRecipientType(&(rowset->aRow[counter]), RecipClass);
177                         counter++;
178                 }
179                 count++;
180         }
181         
182         *index = count;
183         
184         return true;
185 }
186
187 /**
188  * Initialize MAPI and Load Profile
189  *
190  */
191 enum MAPISTATUS torture_load_profile(TALLOC_CTX *mem_ctx, 
192                                      struct loadparm_context *lp_ctx,
193                                      struct mapi_session **s)
194 {
195         enum MAPISTATUS         retval;
196         const char              *profdb;
197         const char              *profname;
198         struct mapi_session     *session = NULL;
199
200         profdb = lp_parm_string(lp_ctx, NULL, "mapi", "profile_store");
201         if (!profdb) {
202                 profdb = talloc_asprintf(mem_ctx, DEFAULT_PROFDB_PATH, getenv("HOME"));
203                 if (!profdb) {
204                         DEBUG(0, ("Specify a valid MAPI profile store\n"));
205                         return MAPI_E_NOT_FOUND;
206                 }
207         }
208
209         retval = MAPIInitialize(profdb);
210         mapi_errstr("MAPIInitialize", GetLastError());
211         MAPI_RETVAL_IF(retval, retval, NULL);
212
213         profname = lp_parm_string(lp_ctx, NULL, "mapi", "profile");
214         if (!profname) {
215                 retval = GetDefaultProfile(&profname);
216                 MAPI_RETVAL_IF(retval, retval, NULL);
217         }
218
219         /* MapiLogonProvider returns MAPI_E_NO_SUPPORT: reset errno */
220         retval = MapiLogonProvider(&session, profname, NULL, PROVIDER_ID_NSPI);
221         errno = 0;
222
223         retval = LoadProfile(session->profile);
224         MAPI_RETVAL_IF(retval, retval, NULL);
225
226         *s = session;
227
228         return MAPI_E_SUCCESS;
229 }
230
231 /**
232  * Initialize MAPI and logs on the EMSMDB pipe with the default
233  * profile
234  */
235
236 struct mapi_session *torture_init_mapi(TALLOC_CTX *mem_ctx, 
237                                        struct loadparm_context *lp_ctx)
238 {
239         enum MAPISTATUS         retval;
240         struct mapi_session     *session;
241         const char              *profdb;
242         const char              *profname;
243         const char              *password;
244
245         profdb = lp_parm_string(lp_ctx, NULL, "mapi", "profile_store");
246         if (!profdb) {
247                 profdb = talloc_asprintf(mem_ctx, DEFAULT_PROFDB_PATH, getenv("HOME"));
248                 if (!profdb) {
249                         DEBUG(0, ("Specify a valid MAPI profile store\n"));
250                         return NULL;
251                 }
252         }
253
254         retval = MAPIInitialize(profdb);
255         mapi_errstr("MAPIInitialize", GetLastError());
256         if (retval != MAPI_E_SUCCESS) return NULL;
257
258
259         profname = lp_parm_string(lp_ctx, NULL, "mapi", "profile");
260         if (!profname) {
261                 retval = GetDefaultProfile(&profname);
262                 if (retval != MAPI_E_SUCCESS) {
263                         DEBUG(0, ("Please specify a valid profile\n"));
264                         return NULL;
265                 }
266         }
267
268         password = lp_parm_string(lp_ctx, NULL, "mapi", "password");
269         retval = MapiLogonEx(&session, profname, password);
270         mapi_errstr("MapiLogonEx", GetLastError());
271         if (retval != MAPI_E_SUCCESS) return NULL;
272
273         return session;
274 }
275
276 enum MAPISTATUS torture_simplemail_fromme(struct loadparm_context *lp_ctx,
277                                           mapi_object_t *obj_parent, 
278                                           const char *subject, const char *body,
279                                           uint32_t flags)
280 {
281         TALLOC_CTX              *mem_ctx;
282         enum MAPISTATUS         retval;
283         mapi_object_t           obj_message;
284         struct SPropTagArray    *SPropTagArray = NULL;
285         struct SPropValue       SPropValue;
286         struct SRowSet          *SRowSet = NULL;
287         struct SPropTagArray    *flaglist = NULL;
288         struct SPropValue       props[3];
289         struct mapi_session     *session = NULL;
290         const char              **usernames;
291         uint32_t                index = 0;
292
293         mem_ctx = talloc_init("torture_simplemail");
294
295         session = mapi_object_get_session(obj_parent);
296         MAPI_RETVAL_IF(!session, MAPI_E_NOT_INITIALIZED, NULL);
297
298         mapi_object_init(&obj_message);
299         retval = CreateMessage(obj_parent, &obj_message);
300         MAPI_RETVAL_IF(retval, retval, mem_ctx);
301
302         SPropTagArray  = set_SPropTagArray(mem_ctx, 0x6,
303                                            PR_OBJECT_TYPE,
304                                            PR_DISPLAY_TYPE,
305                                            PR_7BIT_DISPLAY_NAME,
306                                            PR_DISPLAY_NAME,
307                                            PR_SMTP_ADDRESS,
308                                            PR_GIVEN_NAME);
309
310         lp_set_cmdline(lp_ctx, "mapi:to", session->profile->username);
311         usernames = get_cmdline_recipients(mem_ctx, "to");
312
313         retval = ResolveNames(session, usernames, SPropTagArray, &SRowSet, &flaglist, 0);
314         MAPI_RETVAL_IF(retval, retval, mem_ctx);
315
316         if (!SRowSet) {
317                 SRowSet = talloc_zero(mem_ctx, struct SRowSet);
318         }
319
320         set_usernames_RecipientType(mem_ctx, &index, SRowSet, usernames, flaglist, MAPI_TO);
321
322         SPropValue.ulPropTag = PR_SEND_INTERNET_ENCODING;
323         SPropValue.value.l = 0;
324         SRowSet_propcpy(mem_ctx, SRowSet, SPropValue);
325
326         retval = ModifyRecipients(&obj_message, SRowSet);
327         MAPI_RETVAL_IF(retval, retval, mem_ctx);
328
329         retval = MAPIFreeBuffer(SRowSet);
330         MAPI_RETVAL_IF(retval, retval, mem_ctx);
331         retval = MAPIFreeBuffer(flaglist);
332         MAPI_RETVAL_IF(retval, retval, mem_ctx);
333
334         set_SPropValue_proptag(&props[0], PR_SUBJECT, (const void *)subject);
335         set_SPropValue_proptag(&props[1], PR_BODY, (const void *)body);
336         set_SPropValue_proptag(&props[2], PR_MESSAGE_FLAGS, (const void *)&flags);
337         retval = SetProps(&obj_message, props, 3);
338         MAPI_RETVAL_IF(retval, retval, mem_ctx);
339
340         retval = SaveChangesMessage(obj_parent, &obj_message, KeepOpenReadOnly);
341         MAPI_RETVAL_IF(retval, retval, mem_ctx);
342
343         mapi_object_release(&obj_message);
344
345         talloc_free(mem_ctx);
346         return MAPI_E_SUCCESS;
347 }
348
349 uint32_t get_permission_from_name(const char *role)
350 {
351         if (!role) return -1;
352
353         if (!strncasecmp(role, "RightsNone", strlen(role))) return 0x0;
354         if (!strncasecmp(role, "RightsReadItems", strlen(role))) return 0x1;
355         if (!strncasecmp(role, "RightsCreateItems", strlen(role))) return 0x2;
356         if (!strncasecmp(role, "RightsEditOwn", strlen(role))) return 0x8;
357         if (!strncasecmp(role, "RightsDeleteOwn", strlen(role))) return 0x10;
358         if (!strncasecmp(role, "RightsEditAll", strlen(role))) return 0x20;
359         if (!strncasecmp(role, "RightsDeleteAll", strlen(role))) return 0x40;
360         if (!strncasecmp(role, "RightsCreateSubfolders", strlen(role))) return 0x80;
361         if (!strncasecmp(role, "RightsFolderOwner", strlen(role))) return 0x100;
362         if (!strncasecmp(role, "RightsFolderContact", strlen(role))) return 0x200;
363         if (!strncasecmp(role, "RoleNone", strlen(role))) return 0x400;
364         if (!strncasecmp(role, "RoleReviewer", strlen(role))) return 0x401;
365         if (!strncasecmp(role, "RoleContributor", strlen(role))) return 0x402;
366         if (!strncasecmp(role, "RoleNoneditingAuthor", strlen(role))) return 0x413;
367         if (!strncasecmp(role, "RoleAuthor", strlen(role))) return 0x41B;
368         if (!strncasecmp(role, "RoleEditor", strlen(role))) return 0x47B;
369         if (!strncasecmp(role, "RolePublishAuthor", strlen(role))) return 0x49B;
370         if (!strncasecmp(role, "RolePublishEditor", strlen(role))) return 0x4FB;
371         if (!strncasecmp(role, "RightsAll", strlen(role))) return 0x5FB;
372         if (!strncasecmp(role, "RoleOwner", strlen(role))) return 0x7FB;
373
374         return -1;
375 }