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:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user