Another stab at SF 576327: zipfile when sizeof(long) == 8

binascii_crc32():  The previous patch forced this to return the same
result across platforms.  This patch deals with that, on a 64-bit box,
the *entry* value may have "unexpected" bits in the high four bytes.

Bugfix candidate.
This commit is contained in:
Tim Peters 2002-07-02 22:24:50 +00:00
parent aab713bdf7
commit 934c1a1c6b

View file

@ -42,13 +42,13 @@
** does make the performance sub-optimal. Oh well, too bad... ** does make the performance sub-optimal. Oh well, too bad...
** **
** Jack Jansen, CWI, July 1995. ** Jack Jansen, CWI, July 1995.
** **
** Added support for quoted-printable encoding, based on rfc 1521 et al ** Added support for quoted-printable encoding, based on rfc 1521 et al
** quoted-printable encoding specifies that non printable characters (anything ** quoted-printable encoding specifies that non printable characters (anything
** below 32 and above 126) be encoded as =XX where XX is the hexadecimal value ** below 32 and above 126) be encoded as =XX where XX is the hexadecimal value
** of the character. It also specifies some other behavior to enable 8bit data ** of the character. It also specifies some other behavior to enable 8bit data
** in a mail message with little difficulty (maximum line sizes, protecting ** in a mail message with little difficulty (maximum line sizes, protecting
** some cases of whitespace, etc). ** some cases of whitespace, etc).
** **
** Brandon Long, September 2001. ** Brandon Long, September 2001.
*/ */
@ -190,7 +190,7 @@ binascii_a2b_uu(PyObject *self, PyObject *args)
unsigned int leftchar = 0; unsigned int leftchar = 0;
PyObject *rv; PyObject *rv;
int ascii_len, bin_len; int ascii_len, bin_len;
if ( !PyArg_ParseTuple(args, "t#:a2b_uu", &ascii_data, &ascii_len) ) if ( !PyArg_ParseTuple(args, "t#:a2b_uu", &ascii_data, &ascii_len) )
return NULL; return NULL;
@ -202,7 +202,7 @@ binascii_a2b_uu(PyObject *self, PyObject *args)
if ( (rv=PyString_FromStringAndSize(NULL, bin_len)) == NULL ) if ( (rv=PyString_FromStringAndSize(NULL, bin_len)) == NULL )
return NULL; return NULL;
bin_data = (unsigned char *)PyString_AsString(rv); bin_data = (unsigned char *)PyString_AsString(rv);
for( ; bin_len > 0 ; ascii_len--, ascii_data++ ) { for( ; bin_len > 0 ; ascii_len--, ascii_data++ ) {
this_ch = *ascii_data; this_ch = *ascii_data;
if ( this_ch == '\n' || this_ch == '\r' || ascii_len <= 0) { if ( this_ch == '\n' || this_ch == '\r' || ascii_len <= 0) {
@ -255,7 +255,7 @@ binascii_a2b_uu(PyObject *self, PyObject *args)
} }
PyDoc_STRVAR(doc_b2a_uu, "(bin) -> ascii. Uuencode line of data"); PyDoc_STRVAR(doc_b2a_uu, "(bin) -> ascii. Uuencode line of data");
static PyObject * static PyObject *
binascii_b2a_uu(PyObject *self, PyObject *args) binascii_b2a_uu(PyObject *self, PyObject *args)
{ {
@ -265,7 +265,7 @@ binascii_b2a_uu(PyObject *self, PyObject *args)
unsigned int leftchar = 0; unsigned int leftchar = 0;
PyObject *rv; PyObject *rv;
int bin_len; int bin_len;
if ( !PyArg_ParseTuple(args, "s#:b2a_uu", &bin_data, &bin_len) ) if ( !PyArg_ParseTuple(args, "s#:b2a_uu", &bin_data, &bin_len) )
return NULL; return NULL;
if ( bin_len > 45 ) { if ( bin_len > 45 ) {
@ -281,7 +281,7 @@ binascii_b2a_uu(PyObject *self, PyObject *args)
/* Store the length */ /* Store the length */
*ascii_data++ = ' ' + (bin_len & 077); *ascii_data++ = ' ' + (bin_len & 077);
for( ; bin_len > 0 || leftbits != 0 ; bin_len--, bin_data++ ) { for( ; bin_len > 0 || leftbits != 0 ; bin_len--, bin_data++ ) {
/* Shift the data (or padding) into our buffer */ /* Shift the data (or padding) into our buffer */
if ( bin_len > 0 ) /* Data */ if ( bin_len > 0 ) /* Data */
@ -298,7 +298,7 @@ binascii_b2a_uu(PyObject *self, PyObject *args)
} }
} }
*ascii_data++ = '\n'; /* Append a courtesy newline */ *ascii_data++ = '\n'; /* Append a courtesy newline */
_PyString_Resize(&rv, (ascii_data - _PyString_Resize(&rv, (ascii_data -
(unsigned char *)PyString_AsString(rv))); (unsigned char *)PyString_AsString(rv)));
return rv; return rv;
@ -308,7 +308,7 @@ binascii_b2a_uu(PyObject *self, PyObject *args)
static int static int
binascii_find_valid(unsigned char *s, int slen, int num) binascii_find_valid(unsigned char *s, int slen, int num)
{ {
/* Finds & returns the (num+1)th /* Finds & returns the (num+1)th
** valid character for base64, or -1 if none. ** valid character for base64, or -1 if none.
*/ */
@ -342,7 +342,7 @@ binascii_a2b_base64(PyObject *self, PyObject *args)
PyObject *rv; PyObject *rv;
int ascii_len, bin_len; int ascii_len, bin_len;
int quad_pos = 0; int quad_pos = 0;
if ( !PyArg_ParseTuple(args, "t#:a2b_base64", &ascii_data, &ascii_len) ) if ( !PyArg_ParseTuple(args, "t#:a2b_base64", &ascii_data, &ascii_len) )
return NULL; return NULL;
@ -418,7 +418,7 @@ binascii_a2b_base64(PyObject *self, PyObject *args)
} }
PyDoc_STRVAR(doc_b2a_base64, "(bin) -> ascii. Base64-code line of data"); PyDoc_STRVAR(doc_b2a_base64, "(bin) -> ascii. Base64-code line of data");
static PyObject * static PyObject *
binascii_b2a_base64(PyObject *self, PyObject *args) binascii_b2a_base64(PyObject *self, PyObject *args)
{ {
@ -428,14 +428,14 @@ binascii_b2a_base64(PyObject *self, PyObject *args)
unsigned int leftchar = 0; unsigned int leftchar = 0;
PyObject *rv; PyObject *rv;
int bin_len; int bin_len;
if ( !PyArg_ParseTuple(args, "s#:b2a_base64", &bin_data, &bin_len) ) if ( !PyArg_ParseTuple(args, "s#:b2a_base64", &bin_data, &bin_len) )
return NULL; return NULL;
if ( bin_len > BASE64_MAXBIN ) { if ( bin_len > BASE64_MAXBIN ) {
PyErr_SetString(Error, "Too much data for base64 line"); PyErr_SetString(Error, "Too much data for base64 line");
return NULL; return NULL;
} }
/* We're lazy and allocate too much (fixed up later). /* We're lazy and allocate too much (fixed up later).
"+3" leaves room for up to two pad characters and a trailing "+3" leaves room for up to two pad characters and a trailing
newline. Note that 'b' gets encoded as 'Yg==\n' (1 in, 5 out). */ newline. Note that 'b' gets encoded as 'Yg==\n' (1 in, 5 out). */
@ -462,9 +462,9 @@ binascii_b2a_base64(PyObject *self, PyObject *args)
} else if ( leftbits == 4 ) { } else if ( leftbits == 4 ) {
*ascii_data++ = table_b2a_base64[(leftchar&0xf) << 2]; *ascii_data++ = table_b2a_base64[(leftchar&0xf) << 2];
*ascii_data++ = BASE64_PAD; *ascii_data++ = BASE64_PAD;
} }
*ascii_data++ = '\n'; /* Append a courtesy newline */ *ascii_data++ = '\n'; /* Append a courtesy newline */
_PyString_Resize(&rv, (ascii_data - _PyString_Resize(&rv, (ascii_data -
(unsigned char *)PyString_AsString(rv))); (unsigned char *)PyString_AsString(rv)));
return rv; return rv;
@ -482,7 +482,7 @@ binascii_a2b_hqx(PyObject *self, PyObject *args)
PyObject *rv; PyObject *rv;
int len; int len;
int done = 0; int done = 0;
if ( !PyArg_ParseTuple(args, "t#:a2b_hqx", &ascii_data, &len) ) if ( !PyArg_ParseTuple(args, "t#:a2b_hqx", &ascii_data, &len) )
return NULL; return NULL;
@ -516,7 +516,7 @@ binascii_a2b_hqx(PyObject *self, PyObject *args)
leftchar &= ((1 << leftbits) - 1); leftchar &= ((1 << leftbits) - 1);
} }
} }
if ( leftbits && !done ) { if ( leftbits && !done ) {
PyErr_SetString(Incomplete, PyErr_SetString(Incomplete,
"String has incomplete number of bytes"); "String has incomplete number of bytes");
@ -543,7 +543,7 @@ binascii_rlecode_hqx(PyObject *self, PyObject *args)
PyObject *rv; PyObject *rv;
unsigned char ch; unsigned char ch;
int in, inend, len; int in, inend, len;
if ( !PyArg_ParseTuple(args, "s#:rlecode_hqx", &in_data, &len) ) if ( !PyArg_ParseTuple(args, "s#:rlecode_hqx", &in_data, &len) )
return NULL; return NULL;
@ -551,7 +551,7 @@ binascii_rlecode_hqx(PyObject *self, PyObject *args)
if ( (rv=PyString_FromStringAndSize(NULL, len*2)) == NULL ) if ( (rv=PyString_FromStringAndSize(NULL, len*2)) == NULL )
return NULL; return NULL;
out_data = (unsigned char *)PyString_AsString(rv); out_data = (unsigned char *)PyString_AsString(rv);
for( in=0; in<len; in++) { for( in=0; in<len; in++) {
ch = in_data[in]; ch = in_data[in];
if ( ch == RUNCHAR ) { if ( ch == RUNCHAR ) {
@ -582,7 +582,7 @@ binascii_rlecode_hqx(PyObject *self, PyObject *args)
} }
PyDoc_STRVAR(doc_b2a_hqx, "Encode .hqx data"); PyDoc_STRVAR(doc_b2a_hqx, "Encode .hqx data");
static PyObject * static PyObject *
binascii_b2a_hqx(PyObject *self, PyObject *args) binascii_b2a_hqx(PyObject *self, PyObject *args)
{ {
@ -592,7 +592,7 @@ binascii_b2a_hqx(PyObject *self, PyObject *args)
unsigned int leftchar = 0; unsigned int leftchar = 0;
PyObject *rv; PyObject *rv;
int len; int len;
if ( !PyArg_ParseTuple(args, "s#:b2a_hqx", &bin_data, &len) ) if ( !PyArg_ParseTuple(args, "s#:b2a_hqx", &bin_data, &len) )
return NULL; return NULL;
@ -600,7 +600,7 @@ binascii_b2a_hqx(PyObject *self, PyObject *args)
if ( (rv=PyString_FromStringAndSize(NULL, len*2)) == NULL ) if ( (rv=PyString_FromStringAndSize(NULL, len*2)) == NULL )
return NULL; return NULL;
ascii_data = (unsigned char *)PyString_AsString(rv); ascii_data = (unsigned char *)PyString_AsString(rv);
for( ; len > 0 ; len--, bin_data++ ) { for( ; len > 0 ; len--, bin_data++ ) {
/* Shift into our buffer, and output any 6bits ready */ /* Shift into our buffer, and output any 6bits ready */
leftchar = (leftchar << 8) | *bin_data; leftchar = (leftchar << 8) | *bin_data;
@ -622,7 +622,7 @@ binascii_b2a_hqx(PyObject *self, PyObject *args)
} }
PyDoc_STRVAR(doc_rledecode_hqx, "Decode hexbin RLE-coded string"); PyDoc_STRVAR(doc_rledecode_hqx, "Decode hexbin RLE-coded string");
static PyObject * static PyObject *
binascii_rledecode_hqx(PyObject *self, PyObject *args) binascii_rledecode_hqx(PyObject *self, PyObject *args)
{ {
@ -658,7 +658,7 @@ binascii_rledecode_hqx(PyObject *self, PyObject *args)
} \ } \
b = *in_data++; \ b = *in_data++; \
} while(0) } while(0)
#define OUTBYTE(b) \ #define OUTBYTE(b) \
do { \ do { \
if ( --out_len_left < 0 ) { \ if ( --out_len_left < 0 ) { \
@ -692,7 +692,7 @@ binascii_rledecode_hqx(PyObject *self, PyObject *args)
} else { } else {
OUTBYTE(in_byte); OUTBYTE(in_byte);
} }
while( in_len > 0 ) { while( in_len > 0 ) {
INBYTE(in_byte); INBYTE(in_byte);
@ -726,7 +726,7 @@ binascii_crc_hqx(PyObject *self, PyObject *args)
unsigned char *bin_data; unsigned char *bin_data;
unsigned int crc; unsigned int crc;
int len; int len;
if ( !PyArg_ParseTuple(args, "s#i:crc_hqx", &bin_data, &len, &crc) ) if ( !PyArg_ParseTuple(args, "s#i:crc_hqx", &bin_data, &len, &crc) )
return NULL; return NULL;
@ -758,49 +758,49 @@ PyDoc_STRVAR(doc_crc32,
Copyright (C) 1986 Gary S. Brown. You may use this program, or Copyright (C) 1986 Gary S. Brown. You may use this program, or
code or tables extracted from it, as desired without restriction. code or tables extracted from it, as desired without restriction.
First, the polynomial itself and its table of feedback terms. The
polynomial is
X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0
Note that we take it "backwards" and put the highest-order term in
the lowest-order bit. The X^32 term is "implied"; the LSB is the
X^31 term, etc. The X^0 term (usually shown as "+1") results in
the MSB being 1.
Note that the usual hardware shift register implementation, which First, the polynomial itself and its table of feedback terms. The
is what we're using (we're merely optimizing it by doing eight-bit polynomial is
chunks at a time) shifts bits into the lowest-order term. In our X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0
implementation, that means shifting towards the right. Why do we Note that we take it "backwards" and put the highest-order term in
do it this way? Because the calculated CRC must be transmitted in the lowest-order bit. The X^32 term is "implied"; the LSB is the
order from highest-order term to lowest-order term. UARTs transmit X^31 term, etc. The X^0 term (usually shown as "+1") results in
characters in order from LSB to MSB. By storing the CRC this way, the MSB being 1.
we hand it to the UART in the order low-byte to high-byte; the UART
sends each low-bit to hight-bit; and the result is transmission bit
by bit from highest- to lowest-order term without requiring any bit
shuffling on our part. Reception works similarly.
The feedback terms table consists of 256, 32-bit entries. Notes: Note that the usual hardware shift register implementation, which
is what we're using (we're merely optimizing it by doing eight-bit
1. The table can be generated at runtime if desired; code to do so chunks at a time) shifts bits into the lowest-order term. In our
is shown later. It might not be obvious, but the feedback implementation, that means shifting towards the right. Why do we
terms simply represent the results of eight shift/xor opera- do it this way? Because the calculated CRC must be transmitted in
tions for all combinations of data and CRC register values. order from highest-order term to lowest-order term. UARTs transmit
characters in order from LSB to MSB. By storing the CRC this way,
2. The CRC accumulation logic is the same for all CRC polynomials, we hand it to the UART in the order low-byte to high-byte; the UART
be they sixteen or thirty-two bits wide. You simply choose the sends each low-bit to hight-bit; and the result is transmission bit
appropriate table. Alternatively, because the table can be by bit from highest- to lowest-order term without requiring any bit
generated at runtime, you can start by generating the table for shuffling on our part. Reception works similarly.
the polynomial in question and use exactly the same "updcrc",
if your application needn't simultaneously handle two CRC The feedback terms table consists of 256, 32-bit entries. Notes:
polynomials. (Note, however, that XMODEM is strange.)
1. The table can be generated at runtime if desired; code to do so
3. For 16-bit CRCs, the table entries need be only 16 bits wide; is shown later. It might not be obvious, but the feedback
of course, 32-bit entries work OK if the high 16 bits are zero. terms simply represent the results of eight shift/xor opera-
tions for all combinations of data and CRC register values.
4. The values must be right-shifted by eight bits by the "updcrc"
logic; the shift must be unsigned (bring in zeroes). On some 2. The CRC accumulation logic is the same for all CRC polynomials,
hardware you could probably optimize the shift in assembler by be they sixteen or thirty-two bits wide. You simply choose the
using byte-swap instructions. appropriate table. Alternatively, because the table can be
generated at runtime, you can start by generating the table for
the polynomial in question and use exactly the same "updcrc",
if your application needn't simultaneously handle two CRC
polynomials. (Note, however, that XMODEM is strange.)
3. For 16-bit CRCs, the table entries need be only 16 bits wide;
of course, 32-bit entries work OK if the high 16 bits are zero.
4. The values must be right-shifted by eight bits by the "updcrc"
logic; the shift must be unsigned (bring in zeroes). On some
hardware you could probably optimize the shift in assembler by
using byte-swap instructions.
********************************************************************/ ********************************************************************/
static unsigned long crc_32_tab[256] = { static unsigned long crc_32_tab[256] = {
@ -865,23 +865,29 @@ binascii_crc32(PyObject *self, PyObject *args)
unsigned long crc = 0UL; /* initial value of CRC */ unsigned long crc = 0UL; /* initial value of CRC */
int len; int len;
long result; long result;
if ( !PyArg_ParseTuple(args, "s#|l:crc32", &bin_data, &len, &crc) ) if ( !PyArg_ParseTuple(args, "s#|l:crc32", &bin_data, &len, &crc) )
return NULL; return NULL;
crc = crc ^ 0xFFFFFFFFUL; crc = ~ crc;
while(len--) #if SIZEOF_LONG > 4
/* only want the trailing 32 bits */
crc &= 0xFFFFFFFFUL;
#endif
while (len--)
crc = crc_32_tab[(crc ^ *bin_data++) & 0xffUL] ^ (crc >> 8); crc = crc_32_tab[(crc ^ *bin_data++) & 0xffUL] ^ (crc >> 8);
/* Note: (crc >> 8) MUST zero fill on left */ /* Note: (crc >> 8) MUST zero fill on left */
result = (long)(crc ^ 0xFFFFFFFFUL); result = (long)(crc ^ 0xFFFFFFFFUL);
/* If long is > 32 bits, extend the sign bit. This is one way to #if SIZEOF_LONG > 4
* ensure the result is the same across platforms. The other way /* Extend the sign bit. This is one way to ensure the result is the
* would be to return an unbounded long, but the evidence suggests * same across platforms. The other way would be to return an
* that lots of code outside this treats the result as if it were * unbounded unsigned long, but the evidence suggests that lots of
* a signed 4-byte integer. * code outside this treats the result as if it were a signed 4-byte
* integer.
*/ */
result |= -(result & (1L << 31)); result |= -(result & (1L << 31));
#endif
return PyInt_FromLong(result); return PyInt_FromLong(result);
} }
@ -929,7 +935,7 @@ This function is also available as \"hexlify()\".");
static int static int
to_int(int c) to_int(int c)
{ {
if (isdigit(c)) if (isdigit(c))
return c - '0'; return c - '0';
@ -1011,7 +1017,7 @@ static int table_hex[128] = {
PyDoc_STRVAR(doc_a2b_qp, "Decode a string of qp-encoded data"); PyDoc_STRVAR(doc_a2b_qp, "Decode a string of qp-encoded data");
static PyObject* static PyObject*
binascii_a2b_qp(PyObject *self, PyObject *args, PyObject *kwargs) binascii_a2b_qp(PyObject *self, PyObject *args, PyObject *kwargs)
{ {
unsigned int in, out; unsigned int in, out;
@ -1022,7 +1028,7 @@ binascii_a2b_qp(PyObject *self, PyObject *args, PyObject *kwargs)
static char *kwlist[] = {"data", "header", NULL}; static char *kwlist[] = {"data", "header", NULL};
int header = 0; int header = 0;
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#|i", kwlist, &data, if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#|i", kwlist, &data,
&datalen, &header)) &datalen, &header))
return NULL; return NULL;
@ -1040,7 +1046,7 @@ binascii_a2b_qp(PyObject *self, PyObject *args, PyObject *kwargs)
in++; in++;
if (in >= datalen) break; if (in >= datalen) break;
/* Soft line breaks */ /* Soft line breaks */
if ((data[in] == '\n') || (data[in] == '\r') || if ((data[in] == '\n') || (data[in] == '\r') ||
(data[in] == ' ') || (data[in] == '\t')) { (data[in] == ' ') || (data[in] == '\t')) {
if (data[in] != '\n') { if (data[in] != '\n') {
while (in < datalen && data[in] != '\n') in++; while (in < datalen && data[in] != '\n') in++;
@ -1052,7 +1058,7 @@ binascii_a2b_qp(PyObject *self, PyObject *args, PyObject *kwargs)
odata[out++] = '='; odata[out++] = '=';
in++; in++;
} }
else if (((data[in] >= 'A' && data[in] <= 'F') || else if (((data[in] >= 'A' && data[in] <= 'F') ||
(data[in] >= 'a' && data[in] <= 'f') || (data[in] >= 'a' && data[in] <= 'f') ||
(data[in] >= '0' && data[in] <= '9')) && (data[in] >= '0' && data[in] <= '9')) &&
((data[in+1] >= 'A' && data[in+1] <= 'F') || ((data[in+1] >= 'A' && data[in+1] <= 'F') ||
@ -1087,7 +1093,7 @@ binascii_a2b_qp(PyObject *self, PyObject *args, PyObject *kwargs)
return rv; return rv;
} }
static int static int
to_hex (unsigned char ch, unsigned char *s) to_hex (unsigned char ch, unsigned char *s)
{ {
unsigned int uvalue = ch; unsigned int uvalue = ch;
@ -1109,7 +1115,7 @@ both encoded. When quotetabs is set, space and tabs are encoded.");
/* XXX: This is ridiculously complicated to be backward compatible /* XXX: This is ridiculously complicated to be backward compatible
* (mostly) with the quopri module. It doesn't re-create the quopri * (mostly) with the quopri module. It doesn't re-create the quopri
* module bug where text ending in CRLF has the CR encoded */ * module bug where text ending in CRLF has the CR encoded */
static PyObject* static PyObject*
binascii_b2a_qp (PyObject *self, PyObject *args, PyObject *kwargs) binascii_b2a_qp (PyObject *self, PyObject *args, PyObject *kwargs)
{ {
unsigned int in, out; unsigned int in, out;
@ -1125,7 +1131,7 @@ binascii_b2a_qp (PyObject *self, PyObject *args, PyObject *kwargs)
int crlf = 0; int crlf = 0;
unsigned char *p; unsigned char *p;
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#|iii", kwlist, &data, if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#|iii", kwlist, &data,
&datalen, &quotetabs, &istext, &header)) &datalen, &quotetabs, &istext, &header))
return NULL; return NULL;
@ -1140,14 +1146,14 @@ binascii_b2a_qp (PyObject *self, PyObject *args, PyObject *kwargs)
/* First, scan to see how many characters need to be encoded */ /* First, scan to see how many characters need to be encoded */
in = 0; in = 0;
while (in < datalen) { while (in < datalen) {
if ((data[in] > 126) || if ((data[in] > 126) ||
(data[in] == '=') || (data[in] == '=') ||
(header && data[in] == '_') || (header && data[in] == '_') ||
((data[in] == '.') && (linelen == 1)) || ((data[in] == '.') && (linelen == 1)) ||
(!istext && ((data[in] == '\r') || (data[in] == '\n'))) || (!istext && ((data[in] == '\r') || (data[in] == '\n'))) ||
((data[in] == '\t' || data[in] == ' ') && (in + 1 == datalen)) || ((data[in] == '\t' || data[in] == ' ') && (in + 1 == datalen)) ||
((data[in] < 33) && ((data[in] < 33) &&
(data[in] != '\r') && (data[in] != '\n') && (data[in] != '\r') && (data[in] != '\n') &&
(quotetabs && ((data[in] != '\t') || (data[in] != ' '))))) (quotetabs && ((data[in] != '\t') || (data[in] != ' ')))))
{ {
if ((linelen + 3) >= MAXLINESIZE) { if ((linelen + 3) >= MAXLINESIZE) {
@ -1162,7 +1168,7 @@ binascii_b2a_qp (PyObject *self, PyObject *args, PyObject *kwargs)
in++; in++;
} }
else { else {
if (istext && if (istext &&
((data[in] == '\n') || ((data[in] == '\n') ||
((in+1 < datalen) && (data[in] == '\r') && ((in+1 < datalen) && (data[in] == '\r') &&
(data[in+1] == '\n')))) (data[in+1] == '\n'))))
@ -1181,7 +1187,7 @@ binascii_b2a_qp (PyObject *self, PyObject *args, PyObject *kwargs)
in++; in++;
} }
else { else {
if ((in + 1 != datalen) && if ((in + 1 != datalen) &&
(data[in+1] != '\n') && (data[in+1] != '\n') &&
(linelen + 1) >= MAXLINESIZE) { (linelen + 1) >= MAXLINESIZE) {
linelen = 0; linelen = 0;
@ -1206,14 +1212,14 @@ binascii_b2a_qp (PyObject *self, PyObject *args, PyObject *kwargs)
in = out = linelen = 0; in = out = linelen = 0;
while (in < datalen) { while (in < datalen) {
if ((data[in] > 126) || if ((data[in] > 126) ||
(data[in] == '=') || (data[in] == '=') ||
(header && data[in] == '_') || (header && data[in] == '_') ||
((data[in] == '.') && (linelen == 1)) || ((data[in] == '.') && (linelen == 1)) ||
(!istext && ((data[in] == '\r') || (data[in] == '\n'))) || (!istext && ((data[in] == '\r') || (data[in] == '\n'))) ||
((data[in] == '\t' || data[in] == ' ') && (in + 1 == datalen)) || ((data[in] == '\t' || data[in] == ' ') && (in + 1 == datalen)) ||
((data[in] < 33) && ((data[in] < 33) &&
(data[in] != '\r') && (data[in] != '\n') && (data[in] != '\r') && (data[in] != '\n') &&
(quotetabs && ((data[in] != '\t') || (data[in] != ' '))))) (quotetabs && ((data[in] != '\t') || (data[in] != ' ')))))
{ {
if ((linelen + 3 )>= MAXLINESIZE) { if ((linelen + 3 )>= MAXLINESIZE) {
@ -1229,7 +1235,7 @@ binascii_b2a_qp (PyObject *self, PyObject *args, PyObject *kwargs)
linelen += 3; linelen += 3;
} }
else { else {
if (istext && if (istext &&
((data[in] == '\n') || ((data[in] == '\n') ||
((in+1 < datalen) && (data[in] == '\r') && ((in+1 < datalen) && (data[in] == '\r') &&
(data[in+1] == '\n')))) (data[in+1] == '\n'))))
@ -1242,7 +1248,7 @@ binascii_b2a_qp (PyObject *self, PyObject *args, PyObject *kwargs)
to_hex(ch, &odata[out]); to_hex(ch, &odata[out]);
out += 2; out += 2;
} }
if (crlf) odata[out++] = '\r'; if (crlf) odata[out++] = '\r';
odata[out++] = '\n'; odata[out++] = '\n';
if (data[in] == '\r') if (data[in] == '\r')
@ -1251,7 +1257,7 @@ binascii_b2a_qp (PyObject *self, PyObject *args, PyObject *kwargs)
in++; in++;
} }
else { else {
if ((in + 1 != datalen) && if ((in + 1 != datalen) &&
(data[in+1] != '\n') && (data[in+1] != '\n') &&
(linelen + 1) >= MAXLINESIZE) { (linelen + 1) >= MAXLINESIZE) {
odata[out++] = '='; odata[out++] = '=';
@ -1296,9 +1302,9 @@ static struct PyMethodDef binascii_module_methods[] = {
doc_rledecode_hqx}, doc_rledecode_hqx},
{"crc_hqx", binascii_crc_hqx, METH_VARARGS, doc_crc_hqx}, {"crc_hqx", binascii_crc_hqx, METH_VARARGS, doc_crc_hqx},
{"crc32", binascii_crc32, METH_VARARGS, doc_crc32}, {"crc32", binascii_crc32, METH_VARARGS, doc_crc32},
{"a2b_qp", (PyCFunction)binascii_a2b_qp, METH_VARARGS | METH_KEYWORDS, {"a2b_qp", (PyCFunction)binascii_a2b_qp, METH_VARARGS | METH_KEYWORDS,
doc_a2b_qp}, doc_a2b_qp},
{"b2a_qp", (PyCFunction)binascii_b2a_qp, METH_VARARGS | METH_KEYWORDS, {"b2a_qp", (PyCFunction)binascii_b2a_qp, METH_VARARGS | METH_KEYWORDS,
doc_b2a_qp}, doc_b2a_qp},
{NULL, NULL} /* sentinel */ {NULL, NULL} /* sentinel */
}; };