Merge in sogo branch changes r3949-3962
[jelmer/openchange.git] / pyopenchange / mapistore / context.c
1 /*
2    OpenChange MAPI implementation.
3
4    Python interface to mapistore context
5
6    Copyright (C) Julien Kerihuel 2010-2011.
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 #include <Python.h>
23 #include <inttypes.h>
24 #include "pyopenchange/mapistore/pymapistore.h"
25
26 static void py_MAPIStoreContext_dealloc(PyObject *_self)
27 {
28         PyMAPIStoreContextObject *self = (PyMAPIStoreContextObject *) _self;
29
30         mapistore_del_context(self->mstore_ctx, self->context_id);
31         Py_XDECREF(self->parent);
32         PyObject_Del(_self);
33 }
34
35 static PyObject *py_MAPIStoreContext_open(PyMAPIStoreContextObject *self, PyObject *args)
36 {
37         PyMAPIStoreFolderObject         *folder;
38
39         folder = PyObject_New(PyMAPIStoreFolderObject, &PyMAPIStoreFolder);
40         
41         folder->context = self;
42         Py_INCREF(folder->context);
43
44         folder->folder_object = self->folder_object;
45         (void) talloc_reference(NULL, folder->folder_object);
46         folder->fid = self->fid;
47         
48         return (PyObject *)folder;
49 }
50
51 static PyObject *py_MAPIStoreContext_register_subscription(PyMAPIStoreContextObject *self, PyObject *args)
52 {
53         int                                             ret;
54         struct mapistore_mgmt_notif                     n;
55         const char                                      *mapistoreURI;
56         bool                                            WholeStore;
57         uint16_t                                        NotificationFlags;
58         uint64_t                                        FolderID;
59         bool                                            softdeleted;
60         struct mapistore_subscription_list              *subscription_list;
61         struct mapistore_subscription                   *subscription;
62         struct mapistore_object_subscription_parameters subscription_params;
63         uint32_t                                        random_int;
64         PyMAPIStoreGlobals                              *globals;
65
66         if (!PyArg_ParseTuple(args, "sbh", &mapistoreURI, &WholeStore, &NotificationFlags)) {
67                 return NULL;
68         }
69
70         n.WholeStore = WholeStore;
71         n.NotificationFlags = NotificationFlags;
72
73         if (WholeStore == true) {
74                 n.FolderID = 0;
75                 n.MessageID = 0;
76                 n.MAPIStoreURI = NULL;
77         } else {
78                 /* Retrieve folderID from mapistoreURI in openchange.ldb */
79
80                 globals = get_PyMAPIStoreGlobals();
81                 ret = openchangedb_get_fid(globals->ocdb_ctx, mapistoreURI, &FolderID);
82                 if (ret != MAPISTORE_SUCCESS) {
83                         /* Try to retrieve URI from user indexing.tdb */
84                         ret = mapistore_indexing_record_get_fmid(self->mstore_ctx, 
85                                                                  self->mstore_ctx->conn_info->username,
86                                                                  mapistoreURI, false, &FolderID, &softdeleted);
87                         if (ret != MAPISTORE_SUCCESS || softdeleted == true) {
88                                 return PyBool_FromLong(false);
89                         }
90                 }
91
92                 n.FolderID = FolderID;
93                 n.MessageID = 0;
94                 n.MAPIStoreURI = mapistoreURI;
95         }
96         
97
98         ret = mapistore_mgmt_interface_register_subscription(self->mstore_ctx->conn_info, &n);
99
100         /* Upon success attach subscription to session object using
101          * existing mapistore_notification.c implementation */
102         if (ret == MAPISTORE_SUCCESS) {
103                 subscription_list = talloc_zero(self->mstore_ctx, struct mapistore_subscription_list);
104                 DLIST_ADD(self->mstore_ctx->subscriptions, subscription_list);
105
106                 subscription_params.folder_id = n.FolderID;
107                 subscription_params.object_id = n.MessageID;
108                 subscription_params.whole_store = n.WholeStore;
109
110                 /* In OpenChange server, we use handle_id of the
111                  * object, just use rand for now in bindings */
112                 random_int = rand();
113
114                 subscription = mapistore_new_subscription(subscription_list, 
115                                                           self->mstore_ctx,
116                                                           self->mstore_ctx->conn_info->username,
117                                                           random_int, n.NotificationFlags, 
118                                                           &subscription_params);
119                 subscription_list->subscription = subscription;
120         }
121
122         return PyInt_FromLong(!ret ? random_int : -1);
123 }
124
125 static PyObject *py_MAPIStoreContext_unregister_subscription(PyMAPIStoreContextObject *self, PyObject *args)
126 {
127         int                                     ret;
128         struct mapistore_mgmt_notif             n;
129         const char                              *mapistoreURI;
130         bool                                    WholeStore;
131         uint16_t                                NotificationFlags;
132         uint64_t                                FolderID;
133         uint32_t                                identifier;
134         PyMAPIStoreGlobals *globals;
135
136         if (!PyArg_ParseTuple(args, "sbhi", &mapistoreURI, &WholeStore, &NotificationFlags, &identifier)) {
137                 return NULL;
138         }
139
140         n.WholeStore = WholeStore;
141         n.NotificationFlags = NotificationFlags;
142
143         if (WholeStore == true) {
144                 n.FolderID = 0;
145                 n.MessageID = 0;
146                 n.MAPIStoreURI = NULL;
147         } else {
148                 /* Retrieve folderID from mapistoreURI in openchange.ldb */
149                 globals = get_PyMAPIStoreGlobals();
150                 ret = openchangedb_get_fid(globals->ocdb_ctx, mapistoreURI, &FolderID);
151                 if (ret != MAPISTORE_SUCCESS) {
152                         /* Try to retrieve URI from user indexing.tdb */
153                 }
154
155                 n.FolderID = FolderID;
156                 n.MessageID = 0;
157                 n.MAPIStoreURI = mapistoreURI;
158         }
159         
160
161         ret = mapistore_mgmt_interface_unregister_subscription(self->mstore_ctx->conn_info, &n);
162
163         /* Remove matching notifications from mapistore_notification system */
164         if (ret == MAPISTORE_SUCCESS) {
165                 ret = mapistore_delete_subscription(self->mstore_ctx, identifier, NotificationFlags);
166         }
167
168         return PyBool_FromLong(!ret ? true : false);
169 }
170
171 static PyObject *py_MAPIStoreContext_get_notifications(PyMAPIStoreContextObject *self, PyObject *args)
172 {
173         int                                     ret;
174         struct mapistore_subscription_list      *sel;
175         struct mapistore_notification_list      *nlist;
176
177         for (sel = self->mstore_ctx->subscriptions; sel; sel = sel->next) {
178                 ret = mapistore_get_queued_notifications(self->mstore_ctx, sel->subscription, &nlist);
179                 if (ret == MAPISTORE_SUCCESS) {
180                         while (nlist) {
181                                 printf("notification FolderID: 0x%"PRIx64"\n", 
182                                        nlist->notification->parameters.object_parameters.folder_id);
183                                 printf("notification MessageID: 0x%"PRIx64"\n", 
184                                        nlist->notification->parameters.object_parameters.object_id);
185                                 nlist = nlist->next;
186                         }
187                         talloc_free(nlist);
188                 }
189         }
190
191         if (ret != MAPISTORE_SUCCESS) {
192                 return Py_None;
193         }
194         return Py_None;
195 }
196
197 static PyMethodDef mapistore_context_methods[] = {
198         { "open", (PyCFunction)py_MAPIStoreContext_open, METH_VARARGS },
199         { "add_subscription", (PyCFunction)py_MAPIStoreContext_register_subscription, METH_VARARGS },
200         { "delete_subscription", (PyCFunction)py_MAPIStoreContext_unregister_subscription, METH_VARARGS },
201         { "get_notifications", (PyCFunction)py_MAPIStoreContext_get_notifications, METH_VARARGS },
202         { NULL },
203 };
204
205 static PyGetSetDef mapistore_context_getsetters[] = {
206         { NULL }
207 };
208
209 PyTypeObject PyMAPIStoreContext = {
210         PyObject_HEAD_INIT(NULL) 0,
211         .tp_name = "mapistore context",
212         .tp_basicsize = sizeof (PyMAPIStoreContextObject),
213         .tp_methods = mapistore_context_methods,
214         .tp_getset = mapistore_context_getsetters,
215         .tp_doc = "mapistore context object",
216         .tp_dealloc = (destructor)py_MAPIStoreContext_dealloc,
217         .tp_flags = Py_TPFLAGS_DEFAULT,
218 };
219
220 void initmapistore_context(PyObject *m)
221 {
222         if (PyType_Ready(&PyMAPIStoreContext) < 0) {
223                 return;
224         }
225         Py_INCREF(&PyMAPIStoreContext);
226 }