server: intialize aux_header buffer to null if the data is missing.
[tridge/openchange.git] / branches / plugfest / doc / examples / multiple_notif.c
1 /*
2    Stand-alone MAPI application
3
4    OpenChange Project
5
6    Copyright (C) Julien Kerihuel 2010
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   This sample code shows how to use multiple sessions in OpenChange
24   and shows notification system works with multiple sessions.
25
26   To use this sample code, run in the console:
27   ./multiple_notification --profileA=XXX --profileB=YYY
28
29   Send an email using any MAPI compliant client (openchangeclient for
30   example) to recipients matching profileA and profileB.
31
32   If everything works properly, you should see the output above:
33   $ ./multiple_notification --profileA=XXX --profileB=YYY
34   profileA: New mail Received
35   profileB: New mail received
36
37   For further example on how to retrieve and analyse 
38  */
39
40 #include <libmapi/libmapi.h>
41 #include <pthread.h> 
42 #include <samba/popt.h>
43
44 #define DEFAULT_PROFDB  "%s/.openchange/profiles.ldb"
45
46 static int callback(uint16_t NotificationType, void *NotificationData, void *private_data)
47 {
48         switch (NotificationType) {
49         case fnevNewMail:
50         case fnevNewMail|fnevMbit:
51                 DEBUG(0, ("%s: New mail Received\n", (const char *)private_data));
52                 break;
53         default:
54                 break;
55         }
56         
57         return (0);
58 }
59
60 void *monitor(void *val)
61 {
62         enum MAPISTATUS retval;
63         mapi_object_t   *obj_store;
64
65         obj_store = (mapi_object_t *) val;
66         retval = MonitorNotification(mapi_object_get_session(obj_store), (void *)obj_store, NULL);
67         if (retval != MAPI_E_SUCCESS) {
68                 mapi_errstr("MonitorNotification", GetLastError());
69                 pthread_exit(NULL);
70         }
71 }
72
73
74 int main(int ac, const char *av[])
75 {
76         enum MAPISTATUS         retval;
77         TALLOC_CTX              *mem_ctx;
78         struct mapi_context     *mapi_ctx;
79         struct mapi_session     *sessionA = NULL;
80         struct mapi_session     *sessionB = NULL;
81         mapi_object_t           obj_storeA;
82         mapi_object_t           obj_storeB;
83         uint32_t                ulConnectionA;
84         uint32_t                ulConnectionB;
85         poptContext             pc;
86         int                     opt;
87         const char              *opt_profdb = NULL;
88         const char              *profileA = NULL;
89         const char              *profileB = NULL;
90         pthread_t               pthreadA;
91         pthread_t               pthreadB;
92
93         enum { OPT_PROFILE_DB=1000, OPT_PROFILEA, OPT_PROFILEB };
94
95         struct poptOption long_options[] = {
96                 POPT_AUTOHELP
97                 {"database", 0, POPT_ARG_STRING, NULL, OPT_PROFILE_DB, "set the profile database path", NULL},
98                 {"profileA", 0, POPT_ARG_STRING, NULL, OPT_PROFILEA, "profile A", NULL},
99                 {"profileB", 0, POPT_ARG_STRING, NULL, OPT_PROFILEB, "profile B", NULL},
100                 {NULL, 0, 0, NULL, 0, NULL, NULL}
101         };
102
103         /* Step 1. Retrieve and parse command line options */
104         mem_ctx = talloc_named(NULL, 0, "multiple_notif");
105
106         pc = poptGetContext("multiple_notif", ac, av, long_options, 0);
107         while ((opt = poptGetNextOpt(pc)) != -1) {
108                 switch (opt) {
109                 case OPT_PROFILE_DB:
110                         opt_profdb = poptGetOptArg(pc);
111                         break;
112                 case OPT_PROFILEA:
113                         profileA = poptGetOptArg(pc);
114                         break;
115                 case OPT_PROFILEB:
116                         profileB = poptGetOptArg(pc);
117                         break;
118                 }
119         }
120
121         if (!opt_profdb) {
122                 opt_profdb = talloc_asprintf(mem_ctx, DEFAULT_PROFDB, getenv("HOME"));
123         }
124
125         if (!profileA || !profileB) {
126                 printf("You need to specify 2 profiles (--profileA and --profileB options\n");
127                 exit (1);
128         }
129
130         /* Step 2. Initialize MAPI subsystem */
131         retval = MAPIInitialize(&mapi_ctx, opt_profdb);
132         if (retval != MAPI_E_SUCCESS) {
133                 mapi_errstr("MAPIInitialize", GetLastError());
134                 exit (1);
135         }
136
137         retval = MapiLogonEx(mapi_ctx, &sessionA, profileA, NULL);
138         if (retval != MAPI_E_SUCCESS) {
139                 mapi_errstr("MapiLogonEx for profileA", GetLastError());
140                 exit (1);
141         }
142
143         retval = MapiLogonEx(mapi_ctx, &sessionB, profileB, NULL);
144         if (retval != MAPI_E_SUCCESS) {
145                 mapi_errstr("MapiLogonEx for profileB", GetLastError());
146                 exit (1);
147         }
148
149         /* Step 3. Open the stores */
150         mapi_object_init(&obj_storeA);
151         retval = OpenMsgStore(sessionA, &obj_storeA);
152         if (retval != MAPI_E_SUCCESS) {
153                 mapi_errstr("OpenMsgStore profileA", GetLastError());
154                 exit (1);
155         }
156         
157         mapi_object_init(&obj_storeB);
158         retval = OpenMsgStore(sessionB, &obj_storeB);
159         if (retval != MAPI_E_SUCCESS) {
160                 mapi_errstr("OpenMsgStore profileB", GetLastError());
161                 exit (1);
162         }
163
164         /* Step 4. Register for notifications */
165         retval = RegisterNotification(sessionA, 0);
166         if (retval != MAPI_E_SUCCESS) {
167                 mapi_errstr("RegisterNotification profileA", GetLastError());
168                 exit (1);
169         }
170
171         retval = RegisterNotification(sessionB, 0);
172         if (retval != MAPI_E_SUCCESS) {
173                 mapi_errstr("RegisterNotification profileB", GetLastError());
174                 exit (1);
175         }
176
177         /* Step 5. Subscribe for newmail notifications */
178         retval = Subscribe(&obj_storeA, &ulConnectionA, fnevNewMail, true, 
179                            (mapi_notify_callback_t)callback, (void *) "profileA");
180         if (retval != MAPI_E_SUCCESS) {
181                 mapi_errstr("Subscribe profileA", GetLastError());
182                 exit (1);
183         }
184
185         retval = Subscribe(&obj_storeB, &ulConnectionB, fnevNewMail, true, 
186                            (mapi_notify_callback_t)callback, (void *) "profileB");
187         if (retval != MAPI_E_SUCCESS) {
188                 mapi_errstr("Subscribe profileB", GetLastError());
189                 exit (1);
190         }
191
192         /* Step 6. Create threads A and B and wait for notifications */
193         if (pthread_create(&pthreadA, NULL, monitor, (void *)&obj_storeA)) { 
194                 mapi_errstr("Thread creation for profile A failed", GetLastError());
195                 exit (1);
196         }
197
198         if (pthread_create(&pthreadB, NULL, monitor, (void *)&obj_storeB)) {
199                 mapi_errstr("Thread creation for profile B failed", GetLastError());
200                 exit (1);
201         }
202
203         sleep(200);
204         pthread_exit(NULL);
205         MAPIUninitialize(mapi_ctx);
206
207         return 0;
208 }