1
0
mirror of https://github.com/samba-team/samba.git synced 2025-02-23 09:57:40 +03:00

pyldb: Split text/byte strings for compatibility with Python 3

Compatibility with Python 2, and backwards compatibility on Python 2,
is kept.

Under Python 3, DNs, attribute names, filters, controls are always text
(unicode) strings, encoded to/from UTF-8 for storage.
Attribute values are byte strings.

When creating DNs and attribute values, both text and bytes are accepted.
This allows creating messages from homogeneous dicts.

LDB Messages and MessageElements have a .text attribute, which offers
a text view on the contents: any value retrieved from it will be a text
string. The wrapper is implemented in a new Python module.

Thanks to Stefan Metzmacher for const warning fixes

Signed-off-by: Petr Viktorin <pviktori@redhat.com>
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
This commit is contained in:
Petr Viktorin 2015-06-09 17:44:40 +02:00 committed by Stefan Metzmacher
parent 0b384f60dd
commit d584d5ee2a
4 changed files with 396 additions and 98 deletions

148
lib/ldb/_ldb_text.py Normal file
View File

@ -0,0 +1,148 @@
# Text wrapper for ldb bindings
#
# Copyright (C) 2015 Petr Viktorin <pviktori@redhat.com>
# Published under the GNU LGPLv3 or later
import sys
import functools
import ldb
def _recursive_encode(obj):
if isinstance(obj, bytes):
return obj
elif isinstance(obj, str):
return obj.encode('utf-8')
else:
return [_recursive_encode(o) for o in obj]
class _WrapBase(object):
@classmethod
def _wrap(cls, wrapped):
self = cls.__new__(cls)
self._wrapped = wrapped
return self
def __len__(self):
return len(self._wrapped)
def __eq__(self, other):
if hasattr(other, '_wrapped'):
return self._wrapped == other._wrapped
else:
return self._wrapped == other
def __ne__(self, other):
if hasattr(other, '_wrapped'):
return self._wrapped != other._wrapped
else:
return self._wrapped != other
def __lt__(self, other):
if hasattr(other, '_wrapped'):
return self._wrapped < other._wrapped
else:
return self._wrapped < other
def __le__(self, other):
if hasattr(other, '_wrapped'):
return self._wrapped >= other._wrapped
else:
return self._wrapped >= other
def __gt__(self, other):
if hasattr(other, '_wrapped'):
return self._wrapped > other._wrapped
else:
return self._wrapped > other
def __ge__(self, other):
if hasattr(other, '_wrapped'):
return self._wrapped >= other._wrapped
else:
return self._wrapped >= other
def __repr__(self):
return '%s.text' % repr(self._wrapped)
class MessageElementTextWrapper(_WrapBase):
"""Text interface for a LDB message element"""
def __iter__(self):
for item in self._wrapped:
yield item.decode('utf-8')
def __getitem__(self, key):
result = self._wrapped[key]
if result is None:
return None
else:
return result.decode('utf-8')
@property
def flags(self):
return self._wrapped.flags
@property
def set_flags(self):
return self._wrapped.set_flags
_wrap_element = MessageElementTextWrapper._wrap
class MessageTextWrapper(_WrapBase):
"""Text interface for a LDB message"""
def __getitem__(self, key):
result = self._wrapped[key]
if result is None:
return None
else:
return _wrap_element(result)
def get(self, *args, **kwargs):
result = self._wrapped.get(*args, **kwargs)
if isinstance(result, ldb.MessageElement):
return _wrap_element(result)
elif isinstance(result, bytes):
return result.decode('utf-8')
else:
return result
def __setitem__(self, key, item):
self._wrapped[key] = _recursive_encode(item)
def __delitem__(self, key):
del self._wrapped[key]
def elements(self):
return [_wrap_element(el) for el in self._wrapped.elements()]
def items(self):
return [(attr, _wrap_element(el)) for attr, el in self._wrapped.items()]
@property
def keys(self):
return self._wrapped.keys
@property
def remove(self):
return self._wrapped.remove
@property
def add(self):
return self._wrapped.add
@property
def dn(self):
return self._wrapped.dn
@dn.setter
def dn(self, new_value):
self._wrapped.dn = new_value

View File

@ -57,16 +57,35 @@ static struct ldb_message_element *PyObject_AsMessageElement(
unsigned int flags,
const char *attr_name);
/* There's no Py_ssize_t in 2.4, apparently */
#if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 5
typedef int Py_ssize_t;
typedef inquiry lenfunc;
typedef intargfunc ssizeargfunc;
#if PY_MAJOR_VERSION >= 3
#define PyStr_Check PyUnicode_Check
#define PyStr_FromString PyUnicode_FromString
#define PyStr_FromStringAndSize PyUnicode_FromStringAndSize
#define PyStr_FromFormat PyUnicode_FromFormat
#define PyStr_FromFormatV PyUnicode_FromFormatV
#define PyStr_AsUTF8 PyUnicode_AsUTF8
#define PyStr_AsUTF8AndSize PyUnicode_AsUTF8AndSize
#define PyInt_FromLong PyLong_FromLong
#else
#define PyStr_Check PyString_Check
#define PyStr_FromString PyString_FromString
#define PyStr_FromStringAndSize PyString_FromStringAndSize
#define PyStr_FromFormat PyString_FromFormat
#define PyStr_FromFormatV PyString_FromFormatV
#define PyStr_AsUTF8 PyString_AsString
const char *PyStr_AsUTF8AndSize(PyObject *pystr, Py_ssize_t *sizeptr);
const char *
PyStr_AsUTF8AndSize(PyObject *pystr, Py_ssize_t *sizeptr)
{
const char * ret = PyString_AsString(pystr);
if (ret == NULL)
return NULL;
*sizeptr = PyString_Size(pystr);
return ret;
}
#endif
static PyObject *richcmp(int cmp_val, int op)
{
int ret;
@ -93,9 +112,9 @@ static PyObject *py_ldb_control_str(PyLdbControlObject *self)
PyErr_NoMemory();
return NULL;
}
return PyString_FromString(control);
return PyStr_FromString(control);
} else {
return PyString_FromFormat("ldb control");
return PyStr_FromString("ldb control");
}
}
@ -108,9 +127,32 @@ static void py_ldb_control_dealloc(PyLdbControlObject *self)
Py_TYPE(self)->tp_free(self);
}
/* Create a text (rather than bytes) interface for a LDB result object */
static PyObject *wrap_text(const char *type, PyObject *wrapped)
{
PyObject *mod, *cls, *constructor, *inst;
mod = PyImport_ImportModule("_ldb_text");
if (mod == NULL)
return NULL;
cls = PyObject_GetAttrString(mod, type);
Py_DECREF(mod);
if (cls == NULL) {
Py_DECREF(mod);
return NULL;
}
constructor = PyObject_GetAttrString(cls, "_wrap");
Py_DECREF(cls);
if (constructor == NULL) {
return NULL;
}
inst = PyObject_CallFunction(constructor, discard_const_p(char, "O"), wrapped);
Py_DECREF(constructor);
return inst;
}
static PyObject *py_ldb_control_get_oid(PyLdbControlObject *self)
{
return PyString_FromString(self->data->oid);
return PyStr_FromString(self->data->oid);
}
static PyObject *py_ldb_control_get_critical(PyLdbControlObject *self)
@ -208,7 +250,7 @@ static void PyErr_SetLdbError(PyObject *error, int ret, struct ldb_context *ldb_
static PyObject *PyObject_FromLdbValue(const struct ldb_val *val)
{
return PyString_FromStringAndSize((const char *)val->data, val->length);
return PyBytes_FromStringAndSize((const char *)val->data, val->length);
}
/**
@ -334,7 +376,7 @@ static PyObject *PyLdbResult_FromResult(struct ldb_result *result)
}
for (i = 0;result->refs && result->refs[i]; i++) {
PyList_SetItem(referals, i, PyString_FromString(result->refs[i]));
PyList_SetItem(referals, i, PyStr_FromString(result->refs[i]));
}
ret->referals = referals;
return (PyObject *)ret;
@ -392,22 +434,22 @@ static PyObject *py_ldb_dn_is_null(PyLdbDnObject *self)
static PyObject *py_ldb_dn_get_casefold(PyLdbDnObject *self)
{
return PyString_FromString(ldb_dn_get_casefold(self->dn));
return PyStr_FromString(ldb_dn_get_casefold(self->dn));
}
static PyObject *py_ldb_dn_get_linearized(PyLdbDnObject *self)
{
return PyString_FromString(ldb_dn_get_linearized(self->dn));
return PyStr_FromString(ldb_dn_get_linearized(self->dn));
}
static PyObject *py_ldb_dn_canonical_str(PyLdbDnObject *self)
{
return PyString_FromString(ldb_dn_canonical_string(self->dn, self->dn));
return PyStr_FromString(ldb_dn_canonical_string(self->dn, self->dn));
}
static PyObject *py_ldb_dn_canonical_ex_str(PyLdbDnObject *self)
{
return PyString_FromString(ldb_dn_canonical_ex_string(self->dn, self->dn));
return PyStr_FromString(ldb_dn_canonical_ex_string(self->dn, self->dn));
}
static PyObject *py_ldb_dn_extended_str(PyLdbDnObject *self, PyObject *args, PyObject *kwargs)
@ -418,7 +460,7 @@ static PyObject *py_ldb_dn_extended_str(PyLdbDnObject *self, PyObject *args, PyO
discard_const_p(char *, kwnames),
&mode))
return NULL;
return PyString_FromString(ldb_dn_get_extended_linearized(self->dn, self->dn, mode));
return PyStr_FromString(ldb_dn_get_extended_linearized(self->dn, self->dn, mode));
}
static PyObject *py_ldb_dn_get_extended_component(PyLdbDnObject *self, PyObject *args)
@ -433,14 +475,15 @@ static PyObject *py_ldb_dn_get_extended_component(PyLdbDnObject *self, PyObject
Py_RETURN_NONE;
}
return PyString_FromStringAndSize((const char *)val->data, val->length);
return PyBytes_FromStringAndSize((const char *)val->data, val->length);
}
static PyObject *py_ldb_dn_set_extended_component(PyLdbDnObject *self, PyObject *args)
{
char *name;
PyObject *value;
int err;
int err, result;
Py_ssize_t size;
if (!PyArg_ParseTuple(args, "sO", &name, &value))
return NULL;
@ -449,12 +492,12 @@ static PyObject *py_ldb_dn_set_extended_component(PyLdbDnObject *self, PyObject
err = ldb_dn_set_extended_component(self->dn, name, NULL);
} else {
struct ldb_val val;
if (!PyString_Check(value)) {
PyErr_SetString(PyExc_TypeError, "Expected a string argument");
result = PyBytes_AsStringAndSize(value, (char **) &val.data, &size);
val.length = size;
if (result != 0) {
PyErr_SetString(PyExc_TypeError, "Expected a bytestring argument");
return NULL;
}
val.data = (uint8_t *)PyString_AsString(value);
val.length = PyString_Size(value);
err = ldb_dn_set_extended_component(self->dn, name, &val);
}
@ -468,7 +511,19 @@ static PyObject *py_ldb_dn_set_extended_component(PyLdbDnObject *self, PyObject
static PyObject *py_ldb_dn_repr(PyLdbDnObject *self)
{
return PyString_FromFormat("Dn(%s)", PyObject_REPR(PyString_FromString(ldb_dn_get_linearized(self->dn))));
PyObject *str = PyStr_FromString(ldb_dn_get_linearized(self->dn));
PyObject *repr, *result;
if (str == NULL)
return NULL;
repr = PyObject_Repr(str);
if (repr == NULL) {
Py_DECREF(str);
return NULL;
}
result = PyStr_FromFormat("Dn(%s)", PyStr_AsUTF8(repr));
Py_DECREF(str);
Py_DECREF(repr);
return result;
}
static PyObject *py_ldb_dn_check_special(PyLdbDnObject *self, PyObject *args)
@ -589,7 +644,7 @@ static PyObject *py_ldb_dn_get_component_name(PyLdbDnObject *self, PyObject *arg
Py_RETURN_NONE;
}
return PyString_FromString(name);
return PyStr_FromString(name);
}
static PyObject *py_ldb_dn_get_component_value(PyLdbDnObject *self, PyObject *args)
@ -617,18 +672,19 @@ static PyObject *py_ldb_dn_set_component(PyLdbDnObject *self, PyObject *args)
char *name = NULL;
PyObject *value = Py_None;
struct ldb_val val = { NULL, };
int err;
int err, ret;
Py_ssize_t size;
if (!PyArg_ParseTuple(args, "IsO", &num, &name, &value))
return NULL;
if (value != Py_None) {
if (!PyString_Check(value)) {
PyErr_SetString(PyExc_TypeError, "Expected a string argument");
ret = PyBytes_AsStringAndSize(value, (char **) &val.data, &size);
if (ret != 0) {
PyErr_SetString(PyExc_TypeError, "Expected a bytestring argument");
return NULL;
}
val.data = (uint8_t *)PyString_AsString(value);
val.length = PyString_Size(value);
val.length = size;
}
err = ldb_dn_set_component(self->dn, num, name, val);
@ -652,7 +708,7 @@ static PyObject *py_ldb_dn_get_rdn_name(PyLdbDnObject *self)
Py_RETURN_NONE;
}
return PyString_FromString(name);
return PyStr_FromString(name);
}
static PyObject *py_ldb_dn_get_rdn_value(PyLdbDnObject *self)
@ -853,7 +909,7 @@ static void py_ldb_debug(void *context, enum ldb_debug_level level, const char *
static void py_ldb_debug(void *context, enum ldb_debug_level level, const char *fmt, va_list ap)
{
PyObject *fn = (PyObject *)context;
PyObject_CallFunction(fn, discard_const_p(char, "(i,O)"), level, PyString_FromFormatV(fmt, ap));
PyObject_CallFunction(fn, discard_const_p(char, "(i,O)"), level, PyStr_FromFormatV(fmt, ap));
}
static PyObject *py_ldb_debug_func;
@ -950,7 +1006,7 @@ static PyObject *py_ldb_setup_wellknown_attributes(PyLdbObject *self)
static PyObject *py_ldb_repr(PyLdbObject *self)
{
return PyString_FromFormat("<ldb connection>");
return PyStr_FromString("<ldb connection>");
}
static PyObject *py_ldb_get_root_basedn(PyLdbObject *self)
@ -986,8 +1042,8 @@ static PyObject *py_ldb_get_default_basedn(PyLdbObject *self)
return py_ldb_dn_copy(dn);
}
static const char **PyList_AsStringList(TALLOC_CTX *mem_ctx, PyObject *list,
const char *paramname)
static const char **PyList_AsStrList(TALLOC_CTX *mem_ctx, PyObject *list,
const char *paramname)
{
const char **ret;
Py_ssize_t i;
@ -1002,13 +1058,20 @@ static const char **PyList_AsStringList(TALLOC_CTX *mem_ctx, PyObject *list,
}
for (i = 0; i < PyList_Size(list); i++) {
const char *str = NULL;
Py_ssize_t size;
PyObject *item = PyList_GetItem(list, i);
if (!PyString_Check(item)) {
if (!PyStr_Check(item)) {
PyErr_Format(PyExc_TypeError, "%s should be strings", paramname);
talloc_free(ret);
return NULL;
}
ret[i] = talloc_strndup(ret, PyString_AsString(item),
PyString_Size(item));
str = PyStr_AsUTF8AndSize(item, &size);
if (str == NULL) {
talloc_free(ret);
return NULL;
}
ret[i] = talloc_strndup(ret, str, size);
}
ret[i] = NULL;
return ret;
@ -1034,7 +1097,7 @@ static int py_ldb_init(PyLdbObject *self, PyObject *args, PyObject *kwargs)
if (py_options == Py_None) {
options = NULL;
} else {
options = PyList_AsStringList(ldb, py_options, "options");
options = PyList_AsStrList(ldb, py_options, "options");
if (options == NULL)
return -1;
}
@ -1090,7 +1153,7 @@ static PyObject *py_ldb_connect(PyLdbObject *self, PyObject *args, PyObject *kwa
if (py_options == Py_None) {
options = NULL;
} else {
options = PyList_AsStringList(NULL, py_options, "options");
options = PyList_AsStrList(NULL, py_options, "options");
if (options == NULL)
return NULL;
}
@ -1132,7 +1195,7 @@ static PyObject *py_ldb_modify(PyLdbObject *self, PyObject *args, PyObject *kwar
if (py_controls == Py_None) {
parsed_controls = NULL;
} else {
const char **controls = PyList_AsStringList(mem_ctx, py_controls, "controls");
const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
if (controls == NULL) {
talloc_free(mem_ctx);
return NULL;
@ -1159,7 +1222,7 @@ static PyObject *py_ldb_modify(PyLdbObject *self, PyObject *args, PyObject *kwar
ret = ldb_build_mod_req(&req, ldb_ctx, mem_ctx, msg, parsed_controls,
NULL, ldb_op_default_callback, NULL);
if (ret != LDB_SUCCESS) {
if (ret != LDB_SUCCESS) {
PyErr_SetString(PyExc_TypeError, "failed to build request");
talloc_free(mem_ctx);
return NULL;
@ -1236,7 +1299,7 @@ static struct ldb_message *PyDict_AsMessage(TALLOC_CTX *mem_ctx,
}
while (PyDict_Next(py_obj, &dict_pos, &key, &value)) {
char *key_str = PyString_AsString(key);
char *key_str = PyStr_AsUTF8(key);
if (ldb_attr_cmp(key_str, "dn") != 0) {
msg_el = PyObject_AsMessageElement(msg->elements, value,
mod_flags, key_str);
@ -1281,7 +1344,7 @@ static PyObject *py_ldb_add(PyLdbObject *self, PyObject *args, PyObject *kwargs)
if (py_controls == Py_None) {
parsed_controls = NULL;
} else {
const char **controls = PyList_AsStringList(mem_ctx, py_controls, "controls");
const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
if (controls == NULL) {
talloc_free(mem_ctx);
return NULL;
@ -1374,7 +1437,7 @@ static PyObject *py_ldb_delete(PyLdbObject *self, PyObject *args, PyObject *kwar
if (py_controls == Py_None) {
parsed_controls = NULL;
} else {
const char **controls = PyList_AsStringList(mem_ctx, py_controls, "controls");
const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
if (controls == NULL) {
talloc_free(mem_ctx);
return NULL;
@ -1452,7 +1515,7 @@ static PyObject *py_ldb_rename(PyLdbObject *self, PyObject *args, PyObject *kwar
if (py_controls == Py_None) {
parsed_controls = NULL;
} else {
const char **controls = PyList_AsStringList(mem_ctx, py_controls, "controls");
const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
if (controls == NULL) {
talloc_free(mem_ctx);
return NULL;
@ -1577,7 +1640,7 @@ static PyObject *py_ldb_write_ldif(PyLdbObject *self, PyObject *args)
return NULL;
}
ret = PyString_FromString(string);
ret = PyStr_FromString(string);
talloc_free(mem_ctx);
@ -1666,14 +1729,16 @@ static PyObject *py_ldb_schema_format_value(PyLdbObject *self, PyObject *args)
PyObject *ret;
char *element_name;
PyObject *val;
Py_ssize_t size;
int result;
if (!PyArg_ParseTuple(args, "sO", &element_name, &val))
return NULL;
old_val.data = (uint8_t *)PyString_AsString(val);
old_val.length = PyString_Size(val);
result = PyBytes_AsStringAndSize(val, (char **)&old_val.data, &size);
old_val.length = size;
if (old_val.data == NULL) {
if (result != 0) {
PyErr_SetString(PyExc_RuntimeError, "Failed to convert passed value to String");
return NULL;
}
@ -1695,7 +1760,7 @@ static PyObject *py_ldb_schema_format_value(PyLdbObject *self, PyObject *args)
Py_RETURN_NONE;
}
ret = PyString_FromStringAndSize((const char *)new_val.data, new_val.length);
ret = PyBytes_FromStringAndSize((const char *)new_val.data, new_val.length);
talloc_free(mem_ctx);
@ -1737,7 +1802,7 @@ static PyObject *py_ldb_search(PyLdbObject *self, PyObject *args, PyObject *kwar
if (py_attrs == Py_None) {
attrs = NULL;
} else {
attrs = PyList_AsStringList(mem_ctx, py_attrs, "attrs");
attrs = PyList_AsStrList(mem_ctx, py_attrs, "attrs");
if (attrs == NULL) {
talloc_free(mem_ctx);
return NULL;
@ -1756,7 +1821,7 @@ static PyObject *py_ldb_search(PyLdbObject *self, PyObject *args, PyObject *kwar
if (py_controls == Py_None) {
parsed_controls = NULL;
} else {
const char **controls = PyList_AsStringList(mem_ctx, py_controls, "controls");
const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
if (controls == NULL) {
talloc_free(mem_ctx);
return NULL;
@ -2129,7 +2194,7 @@ static PySequenceMethods py_ldb_result_seq = {
static PyObject *py_ldb_result_repr(PyLdbObject *self)
{
return PyString_FromFormat("<ldb result>");
return PyStr_FromString("<ldb result>");
}
@ -2148,13 +2213,13 @@ static PyTypeObject PyLdbResult = {
static PyObject *py_ldb_module_repr(PyLdbModuleObject *self)
{
return PyString_FromFormat("<ldb module '%s'>",
return PyStr_FromFormat("<ldb module '%s'>",
pyldb_Module_AsModule(self)->ops->name);
}
static PyObject *py_ldb_module_str(PyLdbModuleObject *self)
{
return PyString_FromString(pyldb_Module_AsModule(self)->ops->name);
return PyStr_FromString(pyldb_Module_AsModule(self)->ops->name);
}
static PyObject *py_ldb_module_start_transaction(PyLdbModuleObject *self)
@ -2195,7 +2260,7 @@ static PyObject *py_ldb_module_search(PyLdbModuleObject *self, PyObject *args, P
if (py_attrs == Py_None) {
attrs = NULL;
} else {
attrs = PyList_AsStringList(NULL, py_attrs, "attrs");
attrs = PyList_AsStrList(NULL, py_attrs, "attrs");
if (attrs == NULL)
return NULL;
}
@ -2359,6 +2424,9 @@ static struct ldb_message_element *PyObject_AsMessageElement(
const char *attr_name)
{
struct ldb_message_element *me;
const char *msg = NULL;
Py_ssize_t size;
int result;
if (pyldb_MessageElement_Check(set_obj)) {
PyLdbMessageElementObject *set_obj_as_me = (PyLdbMessageElementObject *)set_obj;
@ -2378,28 +2446,58 @@ static struct ldb_message_element *PyObject_AsMessageElement(
me->name = talloc_strdup(me, attr_name);
me->flags = flags;
if (PyString_Check(set_obj)) {
if (PyBytes_Check(set_obj) || PyStr_Check(set_obj)) {
me->num_values = 1;
me->values = talloc_array(me, struct ldb_val, me->num_values);
me->values[0].length = PyString_Size(set_obj);
me->values[0].data = talloc_memdup(me,
(uint8_t *)PyString_AsString(set_obj), me->values[0].length+1);
if (PyBytes_Check(set_obj)) {
char *_msg = NULL;
result = PyBytes_AsStringAndSize(set_obj, &_msg, &size);
if (result != 0) {
talloc_free(me);
return NULL;
}
msg = _msg;
} else {
msg = PyStr_AsUTF8AndSize(set_obj, &size);
if (msg == NULL) {
talloc_free(me);
return NULL;
}
}
me->values[0].data = talloc_memdup(me,
(const uint8_t *)msg,
size+1);
me->values[0].length = size;
} else if (PySequence_Check(set_obj)) {
Py_ssize_t i;
me->num_values = PySequence_Size(set_obj);
me->values = talloc_array(me, struct ldb_val, me->num_values);
for (i = 0; i < me->num_values; i++) {
PyObject *obj = PySequence_GetItem(set_obj, i);
if (!PyString_Check(obj)) {
if (PyBytes_Check(obj)) {
char *_msg = NULL;
result = PyBytes_AsStringAndSize(obj, &_msg, &size);
if (result != 0) {
talloc_free(me);
return NULL;
}
msg = _msg;
} else if (PyStr_Check(obj)) {
msg = PyStr_AsUTF8AndSize(obj, &size);
if (msg == NULL) {
talloc_free(me);
return NULL;
}
} else {
PyErr_Format(PyExc_TypeError,
"Expected string as element %zd in list", i);
talloc_free(me);
return NULL;
}
me->values[i].length = PyString_Size(obj);
me->values[i].data = talloc_memdup(me,
(uint8_t *)PyString_AsString(obj), me->values[i].length+1);
me->values[i].data = talloc_memdup(me,
(const uint8_t *)msg,
size+1);
me->values[i].length = size;
}
} else {
PyErr_Format(PyExc_TypeError,
@ -2477,7 +2575,7 @@ static PyObject *py_ldb_msg_element_find(PyLdbMessageElementObject *self, Py_ssi
PyErr_SetString(PyExc_IndexError, "Out of range");
return NULL;
}
return PyString_FromStringAndSize((char *)el->values[idx].data, el->values[idx].length);
return PyBytes_FromStringAndSize((char *)el->values[idx].data, el->values[idx].length);
}
static PySequenceMethods py_ldb_msg_element_seq = {
@ -2532,6 +2630,9 @@ static PyObject *py_ldb_msg_element_new(PyTypeObject *type, PyObject *args, PyOb
const char * const kwnames[] = { "elements", "flags", "name", NULL };
PyLdbMessageElementObject *ret;
TALLOC_CTX *mem_ctx;
const char *msg = NULL;
Py_ssize_t size;
int result;
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OIs",
discard_const_p(char *, kwnames),
@ -2553,7 +2654,8 @@ static PyObject *py_ldb_msg_element_new(PyTypeObject *type, PyObject *args, PyOb
if (py_elements != NULL) {
Py_ssize_t i;
if (PyString_Check(py_elements)) {
if (PyBytes_Check(py_elements)) {
char *_msg = NULL;
el->num_values = 1;
el->values = talloc_array(el, struct ldb_val, 1);
if (el->values == NULL) {
@ -2561,9 +2663,15 @@ static PyObject *py_ldb_msg_element_new(PyTypeObject *type, PyObject *args, PyOb
PyErr_NoMemory();
return NULL;
}
el->values[0].length = PyString_Size(py_elements);
result = PyBytes_AsStringAndSize(py_elements, &_msg, &size);
if (result != 0) {
talloc_free(mem_ctx);
return NULL;
}
msg = _msg;
el->values[0].data = talloc_memdup(el->values,
(uint8_t *)PyString_AsString(py_elements), el->values[0].length+1);
(const uint8_t *)msg, size + 1);
el->values[0].length = size;
} else if (PySequence_Check(py_elements)) {
el->num_values = PySequence_Size(py_elements);
el->values = talloc_array(el, struct ldb_val, el->num_values);
@ -2578,15 +2686,25 @@ static PyObject *py_ldb_msg_element_new(PyTypeObject *type, PyObject *args, PyOb
talloc_free(mem_ctx);
return NULL;
}
if (!PyString_Check(item)) {
if (PyBytes_Check(item)) {
char *_msg = NULL;
result = PyBytes_AsStringAndSize(item, &_msg, &size);
msg = _msg;
} else if (PyStr_Check(item)) {
msg = PyStr_AsUTF8AndSize(item, &size);
result = (msg == NULL) ? -1 : 0;
} else {
PyErr_Format(PyExc_TypeError,
"Expected string as element %zd in list", i);
result = -1;
}
if (result != 0) {
talloc_free(mem_ctx);
return NULL;
}
el->values[i].length = PyString_Size(item);
el->values[i].data = talloc_memdup(el,
(uint8_t *)PyString_AsString(item), el->values[i].length+1);
(const uint8_t *)msg, size+1);
el->values[i].length = size;
}
} else {
PyErr_SetString(PyExc_TypeError,
@ -2621,17 +2739,17 @@ static PyObject *py_ldb_msg_element_repr(PyLdbMessageElementObject *self)
PyObject *o = py_ldb_msg_element_find(self, i);
repr = PyObject_Repr(o);
if (element_str == NULL)
element_str = talloc_strdup(NULL, PyString_AsString(repr));
element_str = talloc_strdup(NULL, PyStr_AsUTF8(repr));
else
element_str = talloc_asprintf_append(element_str, ",%s", PyString_AsString(repr));
element_str = talloc_asprintf_append(element_str, ",%s", PyStr_AsUTF8(repr));
Py_DECREF(repr);
}
if (element_str != NULL) {
ret = PyString_FromFormat("MessageElement([%s])", element_str);
ret = PyStr_FromFormat("MessageElement([%s])", element_str);
talloc_free(element_str);
} else {
ret = PyString_FromString("MessageElement([])");
ret = PyStr_FromString("MessageElement([])");
}
return ret;
@ -2642,7 +2760,7 @@ static PyObject *py_ldb_msg_element_str(PyLdbMessageElementObject *self)
struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
if (el->num_values == 1)
return PyString_FromStringAndSize((char *)el->values[0].data, el->values[0].length);
return PyStr_FromStringAndSize((char *)el->values[0].data, el->values[0].length);
else
Py_RETURN_NONE;
}
@ -2653,6 +2771,16 @@ static void py_ldb_msg_element_dealloc(PyLdbMessageElementObject *self)
PyObject_Del(self);
}
static PyObject *py_ldb_msg_element_get_text(PyObject *self, void *closure)
{
return wrap_text("MessageElementTextWrapper", self);
}
static PyGetSetDef py_ldb_msg_element_getset[] = {
{ discard_const_p(char, "text"), (getter)py_ldb_msg_element_get_text, NULL, NULL },
{ NULL }
};
static PyTypeObject PyLdbMessageElement = {
.tp_name = "ldb.MessageElement",
.tp_basicsize = sizeof(PyLdbMessageElementObject),
@ -2660,6 +2788,7 @@ static PyTypeObject PyLdbMessageElement = {
.tp_repr = (reprfunc)py_ldb_msg_element_repr,
.tp_str = (reprfunc)py_ldb_msg_element_str,
.tp_methods = py_ldb_msg_element_methods,
.tp_getset = py_ldb_msg_element_getset,
.tp_richcompare = (richcmpfunc)py_ldb_msg_element_richcmp,
.tp_iter = (getiterfunc)py_ldb_msg_element_iter,
.tp_as_sequence = &py_ldb_msg_element_seq,
@ -2729,11 +2858,11 @@ static PyObject *py_ldb_msg_keys(PyLdbMessageObject *self)
Py_ssize_t i, j = 0;
PyObject *obj = PyList_New(msg->num_elements+(msg->dn != NULL?1:0));
if (msg->dn != NULL) {
PyList_SetItem(obj, j, PyString_FromString("dn"));
PyList_SetItem(obj, j, PyStr_FromString("dn"));
j++;
}
for (i = 0; i < msg->num_elements; i++) {
PyList_SetItem(obj, j, PyString_FromString(msg->elements[i].name));
PyList_SetItem(obj, j, PyStr_FromString(msg->elements[i].name));
j++;
}
return obj;
@ -2744,11 +2873,11 @@ static PyObject *py_ldb_msg_getitem_helper(PyLdbMessageObject *self, PyObject *p
struct ldb_message_element *el;
char *name;
struct ldb_message *msg = pyldb_Message_AsMessage(self);
if (!PyString_Check(py_name)) {
name = PyStr_AsUTF8(py_name);
if (name == NULL) {
PyErr_SetNone(PyExc_TypeError);
return NULL;
}
name = PyString_AsString(py_name);
if (!ldb_attr_cmp(name, "dn"))
return pyldb_Dn_FromDn(msg->dn);
el = ldb_msg_find_element(msg, name);
@ -2910,12 +3039,12 @@ static int py_ldb_msg_setitem(PyLdbMessageObject *self, PyObject *name, PyObject
{
char *attr_name;
if (!PyString_Check(name)) {
attr_name = PyStr_AsUTF8(name);
if (attr_name == NULL) {
PyErr_SetNone(PyExc_TypeError);
return -1;
}
attr_name = PyString_AsString(name);
if (value == NULL) {
/* delitem */
ldb_msg_remove_attr(self->msg, attr_name);
@ -3026,8 +3155,14 @@ static int py_ldb_msg_set_dn(PyLdbMessageObject *self, PyObject *value, void *cl
return 0;
}
static PyObject *py_ldb_msg_get_text(PyObject *self, void *closure)
{
return wrap_text("MessageTextWrapper", self);
}
static PyGetSetDef py_ldb_msg_getset[] = {
{ discard_const_p(char, "dn"), (getter)py_ldb_msg_get_dn, (setter)py_ldb_msg_set_dn, NULL },
{ discard_const_p(char, "text"), (getter)py_ldb_msg_get_text, NULL, NULL },
{ NULL }
};
@ -3041,7 +3176,7 @@ static PyObject *py_ldb_msg_repr(PyLdbMessageObject *self)
Py_DECREF(dict);
return NULL;
}
ret = PyString_FromFormat("Message(%s)", PyString_AsString(repr));
ret = PyStr_FromFormat("Message(%s)", PyStr_AsUTF8(repr));
Py_DECREF(repr);
Py_DECREF(dict);
return ret;
@ -3164,7 +3299,7 @@ static int py_module_search(struct ldb_module *mod, struct ldb_request *req)
for (len = 0; req->op.search.attrs[len]; len++);
py_attrs = PyList_New(len);
for (i = 0; i < len; i++)
PyList_SetItem(py_attrs, i, PyString_FromString(req->op.search.attrs[i]));
PyList_SetItem(py_attrs, i, PyStr_FromString(req->op.search.attrs[i]));
}
py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "search"),
@ -3422,7 +3557,7 @@ static PyObject *py_register_module(PyObject *module, PyObject *args)
return NULL;
}
ops->name = talloc_strdup(ops, PyString_AsString(PyObject_GetAttrString(input, discard_const_p(char, "name"))));
ops->name = talloc_strdup(ops, PyStr_AsUTF8(PyObject_GetAttrString(input, discard_const_p(char, "name"))));
Py_INCREF(input);
ops->private_data = input;
@ -3455,7 +3590,7 @@ static PyObject *py_timestring(PyObject *module, PyObject *args)
if (!PyArg_ParseTuple(args, "l", &t_val))
return NULL;
tresult = ldb_timestring(NULL, (time_t) t_val);
ret = PyString_FromString(tresult);
ret = PyStr_FromString(tresult);
talloc_free(tresult);
return ret;
}
@ -3497,7 +3632,7 @@ static PyObject *py_binary_encode(PyObject *self, PyObject *args)
PyErr_SetString(PyExc_TypeError, "unable to encode binary string");
return NULL;
}
ret = PyString_FromString(encoded);
ret = PyStr_FromString(encoded);
talloc_free(encoded);
return ret;
}
@ -3519,7 +3654,7 @@ static PyObject *py_binary_decode(PyObject *self, PyObject *args)
PyErr_SetString(PyExc_TypeError, "unable to decode binary string");
return NULL;
}
ret = Py_BuildValue("s#", val.data, val.length);
ret = PyBytes_FromStringAndSize((const char*)val.data, val.length);
talloc_free(val.data);
return ret;
}

View File

@ -29,11 +29,12 @@
static PyObject *ldb_module = NULL;
/* There's no Py_ssize_t in 2.4, apparently */
#if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 5
typedef int Py_ssize_t;
typedef inquiry lenfunc;
typedef intargfunc ssizeargfunc;
#if PY_MAJOR_VERSION >= 3
#define PyStr_Check PyUnicode_Check
#define PyStr_AsUTF8 PyUnicode_AsUTF8
#else
#define PyStr_Check PyString_Check
#define PyStr_AsUTF8 PyString_AsString
#endif
/**
@ -69,8 +70,14 @@ bool pyldb_Object_AsDn(TALLOC_CTX *mem_ctx, PyObject *object,
struct ldb_dn *odn;
PyTypeObject *PyLdb_Dn_Type;
if (ldb_ctx != NULL && PyString_Check(object)) {
odn = ldb_dn_new(mem_ctx, ldb_ctx, PyString_AsString(object));
if (ldb_ctx != NULL && PyStr_Check(object)) {
odn = ldb_dn_new(mem_ctx, ldb_ctx, PyStr_AsUTF8(object));
*dn = odn;
return true;
}
if (ldb_ctx != NULL && PyBytes_Check(object)) {
odn = ldb_dn_new(mem_ctx, ldb_ctx, PyBytes_AsString(object));
*dn = odn;
return true;
}

View File

@ -133,6 +133,14 @@ def build(bld):
abi_directory='ABI',
abi_match='pyldb_*')
if not bld.env.disable_python:
for env in bld.gen_python_environments(['PKGCONFIGDIR']):
bld.SAMBA_SCRIPT('_ldb_text.py',
pattern='_ldb_text.py',
installdir='python')
bld.INSTALL_FILES('${PYTHONARCHDIR}', '_ldb_text.py')
if not bld.CONFIG_SET('USING_SYSTEM_LDB'):
if Options.is_install:
modules_dir = bld.EXPAND_VARIABLES('${LDB_MODULESDIR}')