2 OpenChange MAPI implementation.
4 Python interface to mapistore
6 Copyright (C) Julien Kerihuel 2010-2011.
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.
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.
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/>.
23 #include "pyopenchange/mapistore/pymapistore.h"
24 #include "pyopenchange/pymapi.h"
26 /* static PyTypeObject *SPropValue_Type; */
28 void initmapistore(void);
30 /* static struct ldb_context *sam_ldb_ctx = NULL; */
31 static struct ldb_context *openchange_ldb_ctx = NULL;
33 void PyErr_SetMAPIStoreError(uint32_t retval)
35 PyErr_SetObject(PyExc_RuntimeError,
36 Py_BuildValue("(i, s)", retval, mapistore_errstr(retval)));
39 /* static void *sam_ldb_init(TALLOC_CTX *mem_ctx, const char *syspath) */
42 /* struct tevent_context *ev; */
44 /* struct ldb_result *res; */
45 /* struct ldb_dn *tmp_dn = NULL; */
46 /* static const char *attrs[] = { */
47 /* "rootDomainNamingContext", */
48 /* "defaultNamingContext", */
52 /* /\* Sanity checks *\/ */
53 /* if (sam_ldb_ctx) return sam_ldb_ctx; */
55 /* ev = tevent_context_init(talloc_autofree_context()); */
56 /* if (!ev) return NULL; */
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; */
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; */
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; */
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); */
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); */
83 /* return sam_ldb_ctx; */
87 static void *openchange_ldb_init(TALLOC_CTX *mem_ctx, const char *syspath)
90 struct tevent_context *ev;
92 struct ldb_result *res;
93 struct ldb_dn *tmp_dn = NULL;
94 static const char *attrs[] = {
95 "rootDomainNamingContext",
96 "defaultNamingContext",
101 if (openchange_ldb_ctx) return openchange_ldb_ctx;
103 ev = tevent_context_init(talloc_autofree_context());
104 if (!ev) return NULL;
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;
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;
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;
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);
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);
131 return openchange_ldb_ctx;
135 static PyObject *py_MAPIStore_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
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;
147 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|s", kwnames, &syspath, &path)) {
151 mem_ctx = talloc_new(NULL);
152 if (mem_ctx == NULL) {
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);
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);
173 /* Initialize configuration */
174 lp_ctx = loadparm_init(mem_ctx);
175 lpcfg_load_default(lp_ctx);
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);
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;
191 return (PyObject *) msobj;
194 static void py_MAPIStore_dealloc(PyObject *_self)
196 PyMAPIStoreObject *self = (PyMAPIStoreObject *)_self;
198 mapistore_release(self->mstore_ctx);
199 talloc_free(self->mem_ctx);
203 static PyObject *py_MAPIStore_new_mgmt(PyMAPIStoreObject *self, PyObject *args)
205 PyMAPIStoreMGMTObject *obj;
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);
213 obj->mem_ctx = self->mem_ctx;
218 return (PyObject *) obj;
221 static PyObject *py_MAPIStore_add_context(PyMAPIStoreObject *self, PyObject *args)
224 PyMAPIStoreContextObject *context;
225 uint32_t context_id = 0;
227 const char *username;
231 if (!PyArg_ParseTuple(args, "ss", &uri, &username)) {
235 printf("Add context: %s\n", uri);
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)
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)
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)
257 context = PyObject_New(PyMAPIStoreContextObject, &PyMAPIStoreContext);
258 context->mem_ctx = self->mem_ctx;
259 context->mstore_ctx = self->mstore_ctx;
261 context->folder_object = folder_object;
262 context->context_id = context_id;
263 context->parent = self;
265 Py_INCREF(context->parent);
267 return (PyObject *) context;
270 static PyObject *py_MAPIStore_delete_context(PyMAPIStoreObject *self, PyObject *args)
272 PyMAPIStoreContextObject *context;
273 int ret = MAPISTORE_SUCCESS;
275 if (!PyArg_ParseTuple(args, "O", &context)) {
279 mapistore_del_context(context->mstore_ctx, context->context_id);
281 return PyInt_FromLong(ret);
284 /* static PyObject *py_MAPIStore_search_context_by_uri(PyMAPIStoreObject *self, PyObject *args) */
287 /* uint32_t context_id = 0; */
288 /* const char *uri; */
289 /* void *backend_object; */
291 /* if (!PyArg_ParseTuple(args, "s", &uri)) { */
295 /* ret = mapistore_search_context_by_uri(self->mstore_ctx, uri, &context_id, &backend_object); */
296 /* if (ret != MAPISTORE_SUCCESS) { */
300 /* return PyInt_FromLong(context_id); */
303 /* static PyObject *py_MAPIStore_add_context_ref_count(PyMAPIStoreObject *self, PyObject *args) */
305 /* uint32_t context_id = 0; */
307 /* if (!PyArg_ParseTuple(args, "k", &context_id)) { */
311 /* return PyInt_FromLong(mapistore_add_context_ref_count(self->mstore_ctx, context_id)); */
314 /* static PyObject *py_MAPIStore_create_folder(PyMAPIStoreObject *self, PyObject *args) */
316 /* uint32_t context_id; */
317 /* uint64_t parent_fid; */
319 /* PyObject *mod_mapi; */
320 /* PyObject *pySPropValue; */
321 /* PySPropValueObject *SPropValue; */
322 /* struct SRow aRow; */
324 /* mod_mapi = PyImport_ImportModule("openchange.mapi"); */
325 /* if (mod_mapi == NULL) { */
326 /* printf("Can't load module\n"); */
329 /* SPropValue_Type = (PyTypeObject *)PyObject_GetAttrString(mod_mapi, "SPropValue"); */
330 /* if (SPropValue_Type == NULL) { */
334 /* if (!PyArg_ParseTuple(args, "kKKO", &context_id, &parent_fid, &fid, &pySPropValue)) { */
338 /* if (!PyObject_TypeCheck(pySPropValue, SPropValue_Type)) { */
339 /* PyErr_SetString(PyExc_TypeError, "Function require SPropValue object"); */
343 /* SPropValue = (PySPropValueObject *)pySPropValue; */
344 /* aRow.cValues = SPropValue->cValues; */
345 /* aRow.lpProps = SPropValue->SPropValue; */
347 /* return PyInt_FromLong(mapistore_folder_create_folder(self->mstore_ctx, context_id, parent_fid, fid, &aRow)); */
350 /* static PyObject *py_MAPIStore_delete_folder(PyMAPIStoreObject *self, PyObject *args) */
352 /* uint32_t context_id; */
353 /* uint64_t parent_fid; */
357 /* if (!PyArg_ParseTuple(args, "kKKH", &context_id, &parent_fid, &fid, &flags)) { */
361 /* return PyInt_FromLong(mapistore_folder_delete_folder(self->mstore_ctx, context_id, parent_fid, fid, flags)); */
364 /* static PyObject *py_MAPIStore_setprops(PyMAPIStoreObject *self, PyObject *args) */
366 /* uint32_t context_id; */
368 /* uint8_t object_type; */
369 /* PyObject *mod_mapi; */
370 /* PyObject *pySPropValue; */
371 /* PySPropValueObject *SPropValue; */
372 /* struct SRow aRow; */
374 /* mod_mapi = PyImport_ImportModule("openchange.mapi"); */
375 /* if (mod_mapi == NULL) { */
376 /* printf("Can't load module\n"); */
379 /* SPropValue_Type = (PyTypeObject *)PyObject_GetAttrString(mod_mapi, "SPropValue"); */
380 /* if (SPropValue_Type == NULL) { */
384 /* if (!PyArg_ParseTuple(args, "kKbO", &context_id, &fid, &object_type, &pySPropValue)) { */
388 /* if (!PyObject_TypeCheck(pySPropValue, SPropValue_Type)) { */
389 /* PyErr_SetString(PyExc_TypeError, "Function require SPropValue object"); */
393 /* SPropValue = (PySPropValueObject *)pySPropValue; */
394 /* aRow.cValues = SPropValue->cValues; */
395 /* aRow.lpProps = SPropValue->SPropValue; */
397 /* return PyInt_FromLong(mapistore_setprops(self->mstore_ctx, context_id, fid, object_type, &aRow)); */
400 /* static PyObject *py_MAPIStore_get_folder_count(PyMAPIStoreObject *self, PyObject *args) */
402 /* uint32_t context_id; */
404 /* uint8_t object_type; */
405 /* uint32_t RowCount = 0; */
407 /* if (!PyArg_ParseTuple(args, "kKb", &context_id, &fid, &object_type)) { */
411 /* switch (object_type) { */
412 /* case MAPISTORE_FOLDER: */
413 /* mapistore_folder_get_folder_count(self->mstore_ctx, context_id, */
414 /* fid, &RowCount); */
416 /* case MAPISTORE_MESSAGE: */
417 /* mapistore_folder_get_message_count(self->mstore_ctx, context_id, */
418 /* fid, MAPISTORE_MESSAGE_TABLE, &RowCount); */
425 /* return PyInt_FromLong(RowCount); */
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 }, */
441 static PyGetSetDef mapistore_getsetters[] = {
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,
457 static PyObject *py_mapistore_set_mapping_path(PyObject *mod, PyObject *args)
459 const char *mapping_path;
461 if (!PyArg_ParseTuple(args, "s", &mapping_path)) {
465 return PyInt_FromLong(mapistore_set_mapping_path(mapping_path));
468 static PyObject *py_mapistore_errstr(PyObject *mod, PyObject *args)
472 if (!PyArg_ParseTuple(args, "k", &ret)) {
476 return PyString_FromString(mapistore_errstr(ret));
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 },
485 void initmapistore(void)
489 if (PyType_Ready(&PyMAPIStore) < 0) {
493 if (PyType_Ready(&PyMAPIStoreMGMT) < 0) {
497 if (PyType_Ready(&PyMAPIStoreContext) < 0) {
501 if (PyType_Ready(&PyMAPIStoreFolder) < 0) {
505 if (PyType_Ready(&PyMAPIStoreTable) < 0) {
509 m = Py_InitModule3("mapistore", py_mapistore_global_methods,
510 "An interface to OpenChange MAPIStore");
515 PyModule_AddObject(m, "FOLDER_GENERIC", PyInt_FromLong(0x1));
516 PyModule_AddObject(m, "FOLDER_SEARCH", PyInt_FromLong(0x2));
518 PyModule_AddObject(m, "NONE", PyInt_FromLong(0x0));
519 PyModule_AddObject(m, "OPEN_IF_EXISTS", PyInt_FromLong(0x1));
521 Py_INCREF(&PyMAPIStore);
523 PyModule_AddObject(m, "mapistore", (PyObject *)&PyMAPIStore);