Fix pymapistore.c warning
[jelmer/openchange-proposed.git/.git] / pyopenchange / mapistore / pymapistore.c
1 /*
2    OpenChange MAPI implementation.
3
4    Python interface to mapistore
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 "pyopenchange/mapistore/pymapistore.h"
24 #include "pyopenchange/pymapi.h"
25
26 /* static PyTypeObject *SPropValue_Type; */
27
28 void initmapistore(void);
29
30 /* static struct ldb_context    *sam_ldb_ctx = NULL; */
31 static struct ldb_context       *openchange_ldb_ctx = NULL;
32
33 void PyErr_SetMAPIStoreError(uint32_t retval)
34 {
35         PyErr_SetObject(PyExc_RuntimeError,
36                         Py_BuildValue("(i, s)", retval, mapistore_errstr(retval)));
37 }
38
39 /* static void *sam_ldb_init(TALLOC_CTX *mem_ctx, const char *syspath) */
40 /* { */
41 /*      char                    *ldb_path; */
42 /*      struct tevent_context   *ev; */
43 /*      int                     ret; */
44 /*      struct ldb_result       *res; */
45 /*      struct ldb_dn           *tmp_dn = NULL; */
46 /*      static const char       *attrs[] = { */
47 /*              "rootDomainNamingContext", */
48 /*              "defaultNamingContext", */
49 /*              NULL */
50 /*      }; */
51
52 /*      /\* Sanity checks *\/ */
53 /*      if (sam_ldb_ctx) return sam_ldb_ctx; */
54
55 /*      ev = tevent_context_init(talloc_autofree_context()); */
56 /*      if (!ev) return NULL; */
57
58 /*      /\* Step 1. Retrieve a LDB context pointer on sam.ldb database *\/ */
59 /*      ldb_path = talloc_asprintf(mem_ctx, "%s/sam.ldb", syspath); */
60 /*      sam_ldb_ctx = ldb_init(mem_ctx, ev); */
61 /*      if (!sam_ldb_ctx) return NULL; */
62
63 /*      /\* Step 2. Connect to the database *\/ */
64 /*      ret = ldb_connect(sam_ldb_ctx, ldb_path, 0, NULL); */
65 /*      talloc_free(ldb_path); */
66 /*      if (ret != LDB_SUCCESS) return NULL; */
67
68 /*      /\* Step 3. Search for rootDSE record *\/ */
69 /*      ret = ldb_search(sam_ldb_ctx, mem_ctx, &res, ldb_dn_new(mem_ctx, sam_ldb_ctx, "@ROOTDSE"), */
70 /*                       LDB_SCOPE_BASE, attrs, NULL); */
71 /*      if (ret != LDB_SUCCESS) return NULL; */
72 /*      if (res->count != 1) return NULL; */
73
74 /*      /\* Step 4. Set opaque naming *\/ */
75 /*      tmp_dn = ldb_msg_find_attr_as_dn(sam_ldb_ctx, sam_ldb_ctx, */
76 /*                                       res->msgs[0], "rootDomainNamingContext"); */
77 /*      ldb_set_opaque(sam_ldb_ctx, "rootDomainNamingContext", tmp_dn); */
78         
79 /*      tmp_dn = ldb_msg_find_attr_as_dn(sam_ldb_ctx, sam_ldb_ctx, */
80 /*                                       res->msgs[0], "defaultNamingContext"); */
81 /*      ldb_set_opaque(sam_ldb_ctx, "defaultNamingContext", tmp_dn); */
82
83 /*      return sam_ldb_ctx; */
84
85 /* } */
86
87 static void *openchange_ldb_init(TALLOC_CTX *mem_ctx, const char *syspath)
88 {
89         char                    *ldb_path;
90         struct tevent_context   *ev;
91         int                     ret;
92         struct ldb_result       *res;
93         struct ldb_dn           *tmp_dn = NULL;
94         static const char       *attrs[] = {
95                 "rootDomainNamingContext",
96                 "defaultNamingContext",
97                 NULL
98         };
99
100         /* Sanity checks */
101         if (openchange_ldb_ctx) return openchange_ldb_ctx;
102
103         ev = tevent_context_init(talloc_autofree_context());
104         if (!ev) return NULL;
105
106         /* Step 1. Retrieve a LDB context pointer on openchange.ldb database */
107         ldb_path = talloc_asprintf(mem_ctx, "%s/openchange.ldb", syspath);
108         openchange_ldb_ctx = ldb_init(mem_ctx, ev);
109         if (!openchange_ldb_ctx) return NULL;
110
111         /* Step 2. Connect to the database */
112         ret = ldb_connect(openchange_ldb_ctx, ldb_path, 0, NULL);
113         talloc_free(ldb_path);
114         if (ret != LDB_SUCCESS) return NULL;
115
116         /* Step 3. Search for rootDSE record */
117         ret = ldb_search(openchange_ldb_ctx, mem_ctx, &res, ldb_dn_new(mem_ctx, openchange_ldb_ctx, "@ROOTDSE"),
118                          LDB_SCOPE_BASE, attrs, NULL);
119         if (ret != LDB_SUCCESS) return NULL;
120         if (res->count != 1) return NULL;
121
122         /* Step 4. Set opaque naming */
123         tmp_dn = ldb_msg_find_attr_as_dn(openchange_ldb_ctx, openchange_ldb_ctx, 
124                                          res->msgs[0], "rootDomainNamingContext");
125         ldb_set_opaque(openchange_ldb_ctx, "rootDomainNamingContext", tmp_dn);
126         
127         tmp_dn = ldb_msg_find_attr_as_dn(openchange_ldb_ctx, openchange_ldb_ctx,
128                                          res->msgs[0], "defaultNamingContext");
129         ldb_set_opaque(openchange_ldb_ctx, "defaultNamingContext", tmp_dn);
130
131         return openchange_ldb_ctx;
132
133 }
134
135 static PyObject *py_MAPIStore_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
136 {
137         TALLOC_CTX                      *mem_ctx;
138         struct loadparm_context         *lp_ctx;
139         struct mapistore_context        *mstore_ctx;
140         PyMAPIStoreObject               *msobj;
141         char                            *kwnames[] = { "syspath", "path", NULL };
142         const char                      *path = NULL;
143         const char                      *syspath = NULL;
144         struct ldb_context              *samdb_ctx = NULL;
145         struct ldb_context              *ocdb_ctx = NULL;
146
147         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|s", kwnames, &syspath, &path)) {
148                 return NULL;
149         }
150
151         mem_ctx = talloc_new(NULL);
152         if (mem_ctx == NULL) {
153                 PyErr_NoMemory();
154                 return NULL;
155         }
156
157         /* Initialize ldb context on sam.ldb */
158 /*      samdb_ctx = sam_ldb_init(mem_ctx, syspath);
159         if (samdb_ctx == NULL) {
160                 printf("Error in sam_ldb_init\n");
161                 talloc_free(mem_ctx);
162                 return NULL;
163         }
164 */
165         /* Initialize ldb context on openchange.ldb */
166         ocdb_ctx = openchange_ldb_init(mem_ctx, syspath);
167         if (ocdb_ctx == NULL) {
168                 printf("Error in openchange_ldb_init\n");
169                 talloc_free(mem_ctx);
170                 return NULL;
171         }
172
173         /* Initialize configuration */
174         lp_ctx = loadparm_init(mem_ctx);
175         lpcfg_load_default(lp_ctx);
176
177         /* Initialize mapistore */
178         mstore_ctx = mapistore_init(mem_ctx, lp_ctx, path);
179         if (mstore_ctx == NULL) {
180                 printf("Error in mapistore_init\n");
181                 talloc_free(mem_ctx);
182                 return NULL;
183         }
184
185         msobj = PyObject_New(PyMAPIStoreObject, &PyMAPIStore);
186         msobj->mem_ctx = mem_ctx;
187         msobj->mstore_ctx = mstore_ctx;
188         msobj->samdb_ctx = samdb_ctx;
189         msobj->ocdb_ctx = ocdb_ctx;
190
191         return (PyObject *) msobj;
192 }
193
194 static void py_MAPIStore_dealloc(PyObject *_self)
195 {
196         PyMAPIStoreObject *self = (PyMAPIStoreObject *)_self;
197
198         mapistore_release(self->mstore_ctx);
199         talloc_free(self->mem_ctx);
200         PyObject_Del(_self);
201 }
202
203 static PyObject *py_MAPIStore_new_mgmt(PyMAPIStoreObject *self, PyObject *args)
204 {
205         PyMAPIStoreMGMTObject   *obj;
206
207         obj = PyObject_New(PyMAPIStoreMGMTObject, &PyMAPIStoreMGMT);
208         obj->mgmt_ctx = mapistore_mgmt_init(self->mstore_ctx);
209         if (obj->mgmt_ctx == NULL) {
210                 PyErr_MAPIStore_IS_ERR_RAISE(MAPISTORE_ERR_NOT_INITIALIZED);
211                 return NULL;
212         }
213         obj->mem_ctx = self->mem_ctx;
214         obj->parent = self;
215
216         Py_INCREF(self);
217
218         return (PyObject *) obj;
219 }
220
221 static PyObject *py_MAPIStore_add_context(PyMAPIStoreObject *self, PyObject *args)
222 {
223         int                             ret;
224         PyMAPIStoreContextObject        *context;
225         uint32_t                        context_id = 0;
226         const char                      *uri;
227         const char                      *username;
228         void                            *folder_object;
229         uint64_t                        fid = 0;
230
231         if (!PyArg_ParseTuple(args, "ss", &uri, &username)) {
232                 return NULL;
233         }
234
235         printf("Add context: %s\n", uri);
236
237         /* Initialize connection info */
238         ret = mapistore_set_connection_info(self->mstore_ctx, self->samdb_ctx, self->ocdb_ctx, username);
239         if (ret != MAPISTORE_SUCCESS) {
240                 PyErr_MAPIStore_IS_ERR_RAISE(ret)
241                 return NULL;
242         }
243
244         /* Get FID given mapistore_uri and username */
245         ret = openchangedb_get_fid(self->ocdb_ctx, uri, &fid);
246         if (ret != MAPISTORE_SUCCESS) {
247                 PyErr_MAPIStore_IS_ERR_RAISE(ret)
248                 return NULL;
249         }
250
251         ret = mapistore_add_context(self->mstore_ctx, username, uri, fid, &context_id, &folder_object);
252         if (ret != MAPISTORE_SUCCESS) {
253                 PyErr_MAPIStore_IS_ERR_RAISE(ret)
254                 return NULL;
255         }
256
257         context = PyObject_New(PyMAPIStoreContextObject, &PyMAPIStoreContext);
258         context->mem_ctx = self->mem_ctx;
259         context->mstore_ctx = self->mstore_ctx;
260         context->fid = fid;
261         context->folder_object = folder_object;
262         context->context_id = context_id;
263         context->parent = self;
264
265         Py_INCREF(context->parent);
266
267         return (PyObject *) context;
268 }
269
270 static PyObject *py_MAPIStore_delete_context(PyMAPIStoreObject *self, PyObject *args)
271 {
272         PyMAPIStoreContextObject        *context;
273         int                             ret = MAPISTORE_SUCCESS;
274
275         if (!PyArg_ParseTuple(args, "O", &context)) {
276                 return NULL;
277         }
278
279         mapistore_del_context(context->mstore_ctx, context->context_id);
280         Py_CLEAR(context);
281         return PyInt_FromLong(ret);
282 }
283
284 /* static PyObject *py_MAPIStore_search_context_by_uri(PyMAPIStoreObject *self, PyObject *args) */
285 /* { */
286 /*      int             ret; */
287 /*      uint32_t        context_id = 0; */
288 /*      const char      *uri; */
289 /*      void            *backend_object; */
290
291 /*      if (!PyArg_ParseTuple(args, "s", &uri)) { */
292 /*              return NULL; */
293 /*      } */
294
295 /*      ret = mapistore_search_context_by_uri(self->mstore_ctx, uri, &context_id, &backend_object); */
296 /*      if (ret != MAPISTORE_SUCCESS) { */
297 /*              return NULL; */
298 /*      } */
299
300 /*      return PyInt_FromLong(context_id); */
301 /* } */
302
303 /* static PyObject *py_MAPIStore_add_context_ref_count(PyMAPIStoreObject *self, PyObject *args) */
304 /* { */
305 /*      uint32_t        context_id = 0; */
306
307 /*      if (!PyArg_ParseTuple(args, "k", &context_id)) { */
308 /*              return NULL; */
309 /*      } */
310
311 /*      return PyInt_FromLong(mapistore_add_context_ref_count(self->mstore_ctx, context_id)); */
312 /* } */
313
314 /* static PyObject *py_MAPIStore_create_folder(PyMAPIStoreObject *self, PyObject *args) */
315 /* { */
316 /*      uint32_t                context_id; */
317 /*      uint64_t                parent_fid; */
318 /*      uint64_t                fid; */
319 /*      PyObject                *mod_mapi; */
320 /*      PyObject                *pySPropValue; */
321 /*      PySPropValueObject      *SPropValue; */
322 /*      struct SRow             aRow; */
323
324 /*      mod_mapi = PyImport_ImportModule("openchange.mapi"); */
325 /*      if (mod_mapi == NULL) { */
326 /*              printf("Can't load module\n"); */
327 /*              return NULL; */
328 /*      } */
329 /*      SPropValue_Type = (PyTypeObject *)PyObject_GetAttrString(mod_mapi, "SPropValue"); */
330 /*      if (SPropValue_Type == NULL) { */
331 /*              return NULL; */
332 /*      } */
333
334 /*      if (!PyArg_ParseTuple(args, "kKKO", &context_id, &parent_fid, &fid, &pySPropValue)) { */
335 /*              return NULL; */
336 /*      } */
337
338 /*      if (!PyObject_TypeCheck(pySPropValue, SPropValue_Type)) { */
339 /*              PyErr_SetString(PyExc_TypeError, "Function require SPropValue object"); */
340 /*              return NULL; */
341 /*      } */
342
343 /*      SPropValue = (PySPropValueObject *)pySPropValue; */
344 /*      aRow.cValues = SPropValue->cValues; */
345 /*      aRow.lpProps = SPropValue->SPropValue; */
346
347 /*      return PyInt_FromLong(mapistore_folder_create_folder(self->mstore_ctx, context_id, parent_fid, fid, &aRow)); */
348 /* } */
349
350 /* static PyObject *py_MAPIStore_delete_folder(PyMAPIStoreObject *self, PyObject *args) */
351 /* { */
352 /*      uint32_t        context_id; */
353 /*      uint64_t        parent_fid; */
354 /*      uint64_t        fid; */
355 /*      uint8_t         flags; */
356
357 /*      if (!PyArg_ParseTuple(args, "kKKH", &context_id, &parent_fid, &fid, &flags)) { */
358 /*              return NULL; */
359 /*      } */
360
361 /*      return PyInt_FromLong(mapistore_folder_delete_folder(self->mstore_ctx, context_id, parent_fid, fid, flags)); */
362 /* } */
363
364 /* static PyObject *py_MAPIStore_setprops(PyMAPIStoreObject *self, PyObject *args) */
365 /* { */
366 /*      uint32_t                context_id; */
367 /*      uint64_t                fid; */
368 /*      uint8_t                 object_type; */
369 /*      PyObject                *mod_mapi; */
370 /*      PyObject                *pySPropValue; */
371 /*      PySPropValueObject      *SPropValue; */
372 /*      struct SRow             aRow; */
373
374 /*      mod_mapi = PyImport_ImportModule("openchange.mapi"); */
375 /*      if (mod_mapi == NULL) { */
376 /*              printf("Can't load module\n"); */
377 /*              return NULL; */
378 /*      } */
379 /*      SPropValue_Type = (PyTypeObject *)PyObject_GetAttrString(mod_mapi, "SPropValue"); */
380 /*      if (SPropValue_Type == NULL) { */
381 /*              return NULL; */
382 /*      } */
383
384 /*      if (!PyArg_ParseTuple(args, "kKbO", &context_id, &fid, &object_type, &pySPropValue)) { */
385 /*              return NULL; */
386 /*      } */
387
388 /*      if (!PyObject_TypeCheck(pySPropValue, SPropValue_Type)) { */
389 /*              PyErr_SetString(PyExc_TypeError, "Function require SPropValue object"); */
390 /*              return NULL; */
391 /*      } */
392
393 /*      SPropValue = (PySPropValueObject *)pySPropValue; */
394 /*      aRow.cValues = SPropValue->cValues; */
395 /*      aRow.lpProps = SPropValue->SPropValue; */
396
397 /*      return PyInt_FromLong(mapistore_setprops(self->mstore_ctx, context_id, fid, object_type, &aRow)); */
398 /* } */
399
400 /* static PyObject *py_MAPIStore_get_folder_count(PyMAPIStoreObject *self, PyObject *args) */
401 /* { */
402 /*      uint32_t                context_id; */
403 /*      uint64_t                fid; */
404 /*      uint8_t                 object_type; */
405 /*      uint32_t                RowCount = 0; */
406
407 /*      if (!PyArg_ParseTuple(args, "kKb", &context_id, &fid, &object_type)) { */
408 /*              return NULL; */
409 /*      } */
410
411 /*      switch (object_type) { */
412 /*      case MAPISTORE_FOLDER: */
413 /*              mapistore_folder_get_folder_count(self->mstore_ctx, context_id,  */
414 /*                                                fid, &RowCount); */
415 /*              break; */
416 /*      case MAPISTORE_MESSAGE: */
417 /*              mapistore_folder_get_message_count(self->mstore_ctx, context_id,  */
418 /*                                                 fid, MAPISTORE_MESSAGE_TABLE, &RowCount); */
419 /*              break; */
420 /*      default: */
421 /*              RowCount = 0; */
422 /*              break; */
423 /*      } */
424
425 /*      return PyInt_FromLong(RowCount); */
426 /* } */
427
428 static PyMethodDef mapistore_methods[] = {
429         { "management", (PyCFunction)py_MAPIStore_new_mgmt, METH_VARARGS },
430         { "add_context", (PyCFunction)py_MAPIStore_add_context, METH_VARARGS },
431         { "delete_context", (PyCFunction)py_MAPIStore_delete_context, METH_VARARGS },
432         /* { "search_context_by_uri", (PyCFunction)py_MAPIStore_search_context_by_uri, METH_VARARGS }, */
433         /* { "add_context_ref_count", (PyCFunction)py_MAPIStore_add_context_ref_count, METH_VARARGS }, */
434         /* { "create_folder", (PyCFunction)py_MAPIStore_create_folder, METH_VARARGS }, */
435         /* { "delete_folder", (PyCFunction)py_MAPIStore_delete_folder, METH_VARARGS }, */
436         /* { "setprops", (PyCFunction)py_MAPIStore_setprops, METH_VARARGS }, */
437         /* { "get_folder_count", (PyCFunction)py_MAPIStore_get_folder_count, METH_VARARGS }, */
438         { NULL },
439 };
440
441 static PyGetSetDef mapistore_getsetters[] = {
442         { NULL }
443 };
444
445 PyTypeObject PyMAPIStore = {
446         PyObject_HEAD_INIT(NULL) 0,
447         .tp_name = "mapistore",
448         .tp_basicsize = sizeof (PyMAPIStoreObject),
449         .tp_methods = mapistore_methods,
450         .tp_getset = mapistore_getsetters,
451         .tp_doc = "mapistore object",
452         .tp_new = py_MAPIStore_new,
453         .tp_dealloc = (destructor)py_MAPIStore_dealloc,
454         .tp_flags = Py_TPFLAGS_DEFAULT,
455 };
456
457 static PyObject *py_mapistore_set_mapping_path(PyObject *mod, PyObject *args)
458 {
459         const char      *mapping_path;
460         
461         if (!PyArg_ParseTuple(args, "s", &mapping_path)) {
462                 return NULL;
463         }
464
465         return PyInt_FromLong(mapistore_set_mapping_path(mapping_path));
466 }
467
468 static PyObject *py_mapistore_errstr(PyObject *mod, PyObject *args)
469 {
470         int             ret;
471
472         if (!PyArg_ParseTuple(args, "k", &ret)) {
473                 return NULL;
474         }
475
476         return PyString_FromString(mapistore_errstr(ret));
477 }
478
479 static PyMethodDef py_mapistore_global_methods[] = {
480         { "set_mapping_path", (PyCFunction)py_mapistore_set_mapping_path, METH_VARARGS },
481         { "errstr", (PyCFunction)py_mapistore_errstr, METH_VARARGS },
482         { NULL },
483 };
484
485 void initmapistore(void)
486 {
487         PyObject        *m;
488
489         if (PyType_Ready(&PyMAPIStore) < 0) {
490                 return;
491         }
492
493         if (PyType_Ready(&PyMAPIStoreMGMT) < 0) {
494                 return;
495         }
496
497         if (PyType_Ready(&PyMAPIStoreContext) < 0) {
498                 return;
499         }
500
501         if (PyType_Ready(&PyMAPIStoreFolder) < 0) {
502                 return;
503         }
504
505         if (PyType_Ready(&PyMAPIStoreTable) < 0) {
506                 return;
507         }
508
509         m = Py_InitModule3("mapistore", py_mapistore_global_methods,
510                            "An interface to OpenChange MAPIStore");
511         if (m == NULL) {
512                 return;
513         }
514
515         PyModule_AddObject(m, "FOLDER_GENERIC", PyInt_FromLong(0x1));
516         PyModule_AddObject(m, "FOLDER_SEARCH", PyInt_FromLong(0x2));
517
518         PyModule_AddObject(m, "NONE", PyInt_FromLong(0x0));
519         PyModule_AddObject(m, "OPEN_IF_EXISTS", PyInt_FromLong(0x1));
520
521         Py_INCREF(&PyMAPIStore);
522
523         PyModule_AddObject(m, "mapistore", (PyObject *)&PyMAPIStore);
524 }