1
0
mirror of https://github.com/samba-team/samba.git synced 2025-12-07 20:23:50 +03:00

Merge from HEAD:

>Rename unpack_* functions to be consistent
>
>Decode CP850 strings when unpacking
>
>Add variable giving default encoding name
This commit is contained in:
Tim Potter
-
parent fc5774b075
commit de26084f0d

View File

@@ -31,7 +31,7 @@ static PyObject * pytdbpack_number(char ch, PyObject *val_iter, PyObject *packed
static PyObject * pytdbpack_str_850(PyObject *val_iter, PyObject *packed_list);
static PyObject * pytdbpack_buffer(PyObject *val_iter, PyObject *packed_list);
static PyObject *pytdbpack_unpack_item(char, char **pbuf, int *plen, PyObject *);
static PyObject *pytdbunpack_item(char, char **pbuf, int *plen, PyObject *);
static PyObject *pytdbpack_data(const char *format_str,
PyObject *val_seq,
@@ -117,7 +117,7 @@ notes:
";
static char const pytdbpack_unpack_doc[] =
static char const pytdbunpack_doc[] =
"unpack(format, buffer) -> (values, rest)
Unpack Samba binary data according to format string.
@@ -145,6 +145,7 @@ notes:
";
const char *pytdb_string_encoding = "cp850";
/*
@@ -324,7 +325,7 @@ pytdbpack_str_850(PyObject *val_iter, PyObject *packed_list)
val_obj = NULL;
}
if (!(cp850_str = PyUnicode_AsEncodedString(unicode_obj, "cp850", NULL)))
if (!(cp850_str = PyUnicode_AsEncodedString(unicode_obj, pytdb_string_encoding, NULL)))
goto out;
if (!nul_str)
@@ -378,208 +379,6 @@ pytdbpack_buffer(PyObject *val_iter, PyObject *packed_list)
}
#if 0
else if (ch == 'B') {
long size;
char *sval;
if (!PyNumber_Check(val_obj)) {
pytdbpack_bad_type(ch, "Number", val_obj);
return NULL;
}
if (!(val_obj = PyNumber_Long(val_obj)))
return NULL;
size = PyLong_AsLong(val_obj);
pack_le_uint32(size, &packed);
/* Release the new reference created by the cast */
Py_DECREF(val_obj);
val_obj = PySequence_GetItem(val_seq, val_i++);
if (!val_obj)
return NULL;
sval = PyString_AsString(val_obj);
if (!sval)
return NULL;
pack_bytes(size, sval, &packed); /* do not include nul */
}
else {
}
return Py_None;
}
#endif
static PyObject *
pytdbpack_unpack(PyObject *self,
PyObject *args)
{
char *format_str, *packed_str, *ppacked;
PyObject *val_list = NULL, *ret_tuple = NULL;
PyObject *rest_string = NULL;
int format_len, packed_len;
char last_format = '#'; /* invalid */
int i;
/* get arguments */
if (!PyArg_ParseTuple(args, "ss#", &format_str, &packed_str, &packed_len))
return NULL;
format_len = strlen(format_str);
/* Allocate list to hold results. Initially empty, and we append
results as we go along. */
val_list = PyList_New(0);
if (!val_list)
goto failed;
ret_tuple = PyTuple_New(2);
if (!ret_tuple)
goto failed;
/* For every object, unpack. */
for (ppacked = packed_str, i = 0; i < format_len && format_str[i] != '$'; i++) {
last_format = format_str[i];
/* packed_len is reduced in place */
if (!pytdbpack_unpack_item(format_str[i], &ppacked, &packed_len, val_list))
goto failed;
}
/* If the last character was '$', keep going until out of space */
if (format_str[i] == '$') {
if (i == 0) {
PyErr_Format(PyExc_ValueError,
"%s: '$' may not be first character in format",
__FUNCTION__);
return NULL;
}
while (packed_len > 0)
if (!pytdbpack_unpack_item(last_format, &ppacked, &packed_len, val_list))
goto failed;
}
/* save leftovers for next time */
rest_string = PyString_FromStringAndSize(ppacked, packed_len);
if (!rest_string)
goto failed;
/* return (values, rest) tuple; give up references to them */
PyTuple_SET_ITEM(ret_tuple, 0, val_list);
val_list = NULL;
PyTuple_SET_ITEM(ret_tuple, 1, rest_string);
val_list = NULL;
return ret_tuple;
failed:
/* handle failure: deallocate anything. XDECREF forms handle NULL
pointers for objects that haven't been allocated yet. */
Py_XDECREF(val_list);
Py_XDECREF(ret_tuple);
Py_XDECREF(rest_string);
return NULL;
}
#if 0
/*
Internal routine that calculates how many bytes will be required to
encode the values in the format.
Also checks that the value list is the right size for the format list.
Returns number of bytes (may be 0), or -1 if there's something wrong, in
which case a Python exception has been raised.
Arguments:
val_seq: a Fast Sequence (list or tuple), being all the values
*/
static int
pytdbpack_calc_reqd_len(char *format_str,
PyObject *val_seq)
{
int len = 0;
char *p;
int val_i;
int val_len;
val_len = PySequence_Length(val_seq);
if (val_len == -1)
return -1;
for (p = format_str, val_i = 0; *p; p++, val_i++) {
char ch = *p;
if (val_i >= val_len) {
PyErr_Format(PyExc_IndexError,
"%s: value list is too short for format string",
__FUNCTION__);
return -1;
}
/* borrow a reference to the item */
if (ch == 'd' || ch == 'p')
len += 4;
else if (ch == 'w')
len += 2;
else if (ch == 'f' || ch == 'P') {
/* nul-terminated 8-bit string */
int item_len;
PyObject *str_obj;
str_obj = PySequence_GetItem(val_seq, val_i);
if (!str_obj)
return -1;
if (!PyString_Check(str_obj) || ((item_len = PyString_Size(str_obj)) == -1)) {
pytdbpack_bad_type(ch, "String", str_obj);
return -1;
}
len += 1 + item_len;
}
else if (ch == 'B') {
/* length-preceded byte buffer: n bytes, plus a preceding
* word */
PyObject *len_obj;
long len_val;
len_obj = PySequence_GetItem(val_seq, val_i);
val_i++; /* skip over buffer */
if (!PyNumber_Check(len_obj)) {
pytdbpack_bad_type(ch, "Number", len_obj);
return -1;
}
len_val = PyInt_AsLong(len_obj);
if (len_val < 0) {
PyErr_Format(PyExc_ValueError,
"%s: format 'B' requires positive integer", __FUNCTION__);
return -1;
}
len += 4 + len_val;
}
else {
PyErr_Format(PyExc_ValueError,
"%s: format character '%c' is not supported",
__FUNCTION__, ch);
return -1;
}
}
return len;
}
#endif
static PyObject *pytdbpack_bad_type(char ch,
const char *expected,
PyObject *val_obj)
@@ -618,8 +417,78 @@ static void pack_bytes(long len, const char *from,
}
static PyObject *
pytdbunpack(PyObject *self,
PyObject *args)
{
char *format_str, *packed_str, *ppacked;
PyObject *val_list = NULL, *ret_tuple = NULL;
PyObject *rest_string = NULL;
int format_len, packed_len;
char last_format = '#'; /* invalid */
int i;
/* get arguments */
if (!PyArg_ParseTuple(args, "ss#", &format_str, &packed_str, &packed_len))
return NULL;
format_len = strlen(format_str);
/* Allocate list to hold results. Initially empty, and we append
results as we go along. */
val_list = PyList_New(0);
if (!val_list)
goto failed;
ret_tuple = PyTuple_New(2);
if (!ret_tuple)
goto failed;
/* For every object, unpack. */
for (ppacked = packed_str, i = 0; i < format_len && format_str[i] != '$'; i++) {
last_format = format_str[i];
/* packed_len is reduced in place */
if (!pytdbunpack_item(format_str[i], &ppacked, &packed_len, val_list))
goto failed;
}
/* If the last character was '$', keep going until out of space */
if (format_str[i] == '$') {
if (i == 0) {
PyErr_Format(PyExc_ValueError,
"%s: '$' may not be first character in format",
__FUNCTION__);
return NULL;
}
while (packed_len > 0)
if (!pytdbunpack_item(last_format, &ppacked, &packed_len, val_list))
goto failed;
}
/* save leftovers for next time */
rest_string = PyString_FromStringAndSize(ppacked, packed_len);
if (!rest_string)
goto failed;
/* return (values, rest) tuple; give up references to them */
PyTuple_SET_ITEM(ret_tuple, 0, val_list);
val_list = NULL;
PyTuple_SET_ITEM(ret_tuple, 1, rest_string);
val_list = NULL;
return ret_tuple;
failed:
/* handle failure: deallocate anything. XDECREF forms handle NULL
pointers for objects that haven't been allocated yet. */
Py_XDECREF(val_list);
Py_XDECREF(ret_tuple);
Py_XDECREF(rest_string);
return NULL;
}
static void
unpack_err_too_short(void)
pytdbunpack_err_too_short(void)
{
PyErr_Format(PyExc_IndexError,
__FUNCTION__ ": data too short for unpack format");
@@ -627,13 +496,13 @@ unpack_err_too_short(void)
static PyObject *
unpack_uint32(char **pbuf, int *plen)
pytdbunpack_uint32(char **pbuf, int *plen)
{
unsigned long v;
unsigned char *b;
if (*plen < 4) {
unpack_err_too_short();
pytdbunpack_err_too_short();
return NULL;
}
@@ -647,13 +516,13 @@ unpack_uint32(char **pbuf, int *plen)
}
static PyObject *unpack_int16(char **pbuf, int *plen)
static PyObject *pytdbunpack_int16(char **pbuf, int *plen)
{
long v;
unsigned char *b;
if (*plen < 2) {
unpack_err_too_short();
pytdbunpack_err_too_short();
return NULL;
}
@@ -668,7 +537,7 @@ static PyObject *unpack_int16(char **pbuf, int *plen)
static PyObject *
unpack_string(char **pbuf, int *plen)
pytdbunpack_string(char **pbuf, int *plen)
{
int len;
char *nul_ptr, *start;
@@ -677,7 +546,7 @@ unpack_string(char **pbuf, int *plen)
nul_ptr = memchr(start, '\0', *plen);
if (!nul_ptr) {
unpack_err_too_short();
pytdbunpack_err_too_short();
return NULL;
}
@@ -686,12 +555,12 @@ unpack_string(char **pbuf, int *plen)
*pbuf += len + 1; /* skip \0 */
*plen -= len + 1;
return PyString_FromStringAndSize(start, len);
return PyString_Decode(start, len, pytdb_string_encoding, NULL);
}
static PyObject *
unpack_buffer(char **pbuf, int *plen, PyObject *val_list)
pytdbunpack_buffer(char **pbuf, int *plen, PyObject *val_list)
{
/* first get 32-bit len */
long slen;
@@ -700,7 +569,7 @@ unpack_buffer(char **pbuf, int *plen, PyObject *val_list)
PyObject *str_obj = NULL, *len_obj = NULL;
if (*plen < 4) {
unpack_err_too_short();
pytdbunpack_err_too_short();
return NULL;
}
@@ -757,7 +626,7 @@ unpack_buffer(char **pbuf, int *plen, PyObject *val_list)
Returns a reference to None, or NULL for failure.
*/
static PyObject *pytdbpack_unpack_item(char ch,
static PyObject *pytdbunpack_item(char ch,
char **pbuf,
int *plen,
PyObject *val_list)
@@ -765,17 +634,17 @@ static PyObject *pytdbpack_unpack_item(char ch,
PyObject *result;
if (ch == 'w') { /* 16-bit int */
result = unpack_int16(pbuf, plen);
result = pytdbunpack_int16(pbuf, plen);
}
else if (ch == 'd' || ch == 'p') { /* 32-bit int */
/* pointers can just come through as integers */
result = unpack_uint32(pbuf, plen);
result = pytdbunpack_uint32(pbuf, plen);
}
else if (ch == 'f' || ch == 'P') { /* nul-term string */
result = unpack_string(pbuf, plen);
result = pytdbunpack_string(pbuf, plen);
}
else if (ch == 'B') { /* length, buffer */
return unpack_buffer(pbuf, plen, val_list);
return pytdbunpack_buffer(pbuf, plen, val_list);
}
else {
PyErr_Format(PyExc_ValueError,
@@ -801,7 +670,7 @@ static PyObject *pytdbpack_unpack_item(char ch,
static PyMethodDef pytdbpack_methods[] = {
{ "pack", pytdbpack, METH_VARARGS, (char *) pytdbpack_doc },
{ "unpack", pytdbpack_unpack, METH_VARARGS, (char *) pytdbpack_unpack_doc },
{ "unpack", pytdbunpack, METH_VARARGS, (char *) pytdbunpack_doc },
};
DL_EXPORT(void)