[Python-checkins] python/dist/src/Modules binascii.c,2.35,2.36

tim_one@users.sourceforge.net tim_one@users.sourceforge.net
Tue, 02 Jul 2002 15:24:52 -0700


Update of /cvsroot/python/python/dist/src/Modules
In directory usw-pr-cvs1:/tmp/cvs-serv19094/python/Modules

Modified Files:
	binascii.c 
Log Message:
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.


Index: binascii.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Modules/binascii.c,v
retrieving revision 2.35
retrieving revision 2.36
diff -C2 -d -r2.35 -r2.36
*** binascii.c	2 Jul 2002 20:20:08 -0000	2.35
--- binascii.c	2 Jul 2002 22:24:50 -0000	2.36
***************
*** 43,53 ****
  **
  ** Jack Jansen, CWI, July 1995.
! ** 
  ** Added support for quoted-printable encoding, based on rfc 1521 et al
! ** quoted-printable encoding specifies that non printable characters (anything 
  ** 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
! ** in a mail message with little difficulty (maximum line sizes, protecting 
! ** some cases of whitespace, etc).    
  **
  ** Brandon Long, September 2001.
--- 43,53 ----
  **
  ** Jack Jansen, CWI, July 1995.
! **
  ** Added support for quoted-printable encoding, based on rfc 1521 et al
! ** quoted-printable encoding specifies that non printable characters (anything
  ** 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
! ** in a mail message with little difficulty (maximum line sizes, protecting
! ** some cases of whitespace, etc).
  **
  ** Brandon Long, September 2001.
***************
*** 191,195 ****
  	PyObject *rv;
  	int ascii_len, bin_len;
! 	
  	if ( !PyArg_ParseTuple(args, "t#:a2b_uu", &ascii_data, &ascii_len) )
  		return NULL;
--- 191,195 ----
  	PyObject *rv;
  	int ascii_len, bin_len;
! 
  	if ( !PyArg_ParseTuple(args, "t#:a2b_uu", &ascii_data, &ascii_len) )
  		return NULL;
***************
*** 203,207 ****
  		return NULL;
  	bin_data = (unsigned char *)PyString_AsString(rv);
! 	
  	for( ; bin_len > 0 ; ascii_len--, ascii_data++ ) {
  		this_ch = *ascii_data;
--- 203,207 ----
  		return NULL;
  	bin_data = (unsigned char *)PyString_AsString(rv);
! 
  	for( ; bin_len > 0 ; ascii_len--, ascii_data++ ) {
  		this_ch = *ascii_data;
***************
*** 256,260 ****
  
  PyDoc_STRVAR(doc_b2a_uu, "(bin) -> ascii. Uuencode line of data");
! 	
  static PyObject *
  binascii_b2a_uu(PyObject *self, PyObject *args)
--- 256,260 ----
  
  PyDoc_STRVAR(doc_b2a_uu, "(bin) -> ascii. Uuencode line of data");
! 
  static PyObject *
  binascii_b2a_uu(PyObject *self, PyObject *args)
***************
*** 266,270 ****
  	PyObject *rv;
  	int bin_len;
! 	
  	if ( !PyArg_ParseTuple(args, "s#:b2a_uu", &bin_data, &bin_len) )
  		return NULL;
--- 266,270 ----
  	PyObject *rv;
  	int bin_len;
! 
  	if ( !PyArg_ParseTuple(args, "s#:b2a_uu", &bin_data, &bin_len) )
  		return NULL;
***************
*** 282,286 ****
  	/* Store the length */
  	*ascii_data++ = ' ' + (bin_len & 077);
! 	
  	for( ; bin_len > 0 || leftbits != 0 ; bin_len--, bin_data++ ) {
  		/* Shift the data (or padding) into our buffer */
--- 282,286 ----
  	/* Store the length */
  	*ascii_data++ = ' ' + (bin_len & 077);
! 
  	for( ; bin_len > 0 || leftbits != 0 ; bin_len--, bin_data++ ) {
  		/* Shift the data (or padding) into our buffer */
***************
*** 299,303 ****
  	}
  	*ascii_data++ = '\n';	/* Append a courtesy newline */
! 	
  	_PyString_Resize(&rv, (ascii_data -
  			       (unsigned char *)PyString_AsString(rv)));
--- 299,303 ----
  	}
  	*ascii_data++ = '\n';	/* Append a courtesy newline */
! 
  	_PyString_Resize(&rv, (ascii_data -
  			       (unsigned char *)PyString_AsString(rv)));
***************
*** 309,313 ****
  binascii_find_valid(unsigned char *s, int slen, int num)
  {
! 	/* Finds & returns the (num+1)th 
  	** valid character for base64, or -1 if none.
  	*/
--- 309,313 ----
  binascii_find_valid(unsigned char *s, int slen, int num)
  {
! 	/* Finds & returns the (num+1)th
  	** valid character for base64, or -1 if none.
  	*/
***************
*** 343,347 ****
  	int ascii_len, bin_len;
  	int quad_pos = 0;
! 	
  	if ( !PyArg_ParseTuple(args, "t#:a2b_base64", &ascii_data, &ascii_len) )
  		return NULL;
--- 343,347 ----
  	int ascii_len, bin_len;
  	int quad_pos = 0;
! 
  	if ( !PyArg_ParseTuple(args, "t#:a2b_base64", &ascii_data, &ascii_len) )
  		return NULL;
***************
*** 419,423 ****
  
  PyDoc_STRVAR(doc_b2a_base64, "(bin) -> ascii. Base64-code line of data");
! 	
  static PyObject *
  binascii_b2a_base64(PyObject *self, PyObject *args)
--- 419,423 ----
  
  PyDoc_STRVAR(doc_b2a_base64, "(bin) -> ascii. Base64-code line of data");
! 
  static PyObject *
  binascii_b2a_base64(PyObject *self, PyObject *args)
***************
*** 429,433 ****
  	PyObject *rv;
  	int bin_len;
! 	
  	if ( !PyArg_ParseTuple(args, "s#:b2a_base64", &bin_data, &bin_len) )
  		return NULL;
--- 429,433 ----
  	PyObject *rv;
  	int bin_len;
! 
  	if ( !PyArg_ParseTuple(args, "s#:b2a_base64", &bin_data, &bin_len) )
  		return NULL;
***************
*** 436,440 ****
  		return NULL;
  	}
! 	
  	/* We're lazy and allocate too much (fixed up later).
  	   "+3" leaves room for up to two pad characters and a trailing
--- 436,440 ----
  		return NULL;
  	}
! 
  	/* We're lazy and allocate too much (fixed up later).
  	   "+3" leaves room for up to two pad characters and a trailing
***************
*** 463,469 ****
  		*ascii_data++ = table_b2a_base64[(leftchar&0xf) << 2];
  		*ascii_data++ = BASE64_PAD;
! 	} 
  	*ascii_data++ = '\n';	/* Append a courtesy newline */
! 	
  	_PyString_Resize(&rv, (ascii_data -
  			       (unsigned char *)PyString_AsString(rv)));
--- 463,469 ----
  		*ascii_data++ = table_b2a_base64[(leftchar&0xf) << 2];
  		*ascii_data++ = BASE64_PAD;
! 	}
  	*ascii_data++ = '\n';	/* Append a courtesy newline */
! 
  	_PyString_Resize(&rv, (ascii_data -
  			       (unsigned char *)PyString_AsString(rv)));
***************
*** 483,487 ****
  	int len;
  	int done = 0;
! 	
  	if ( !PyArg_ParseTuple(args, "t#:a2b_hqx", &ascii_data, &len) )
  		return NULL;
--- 483,487 ----
  	int len;
  	int done = 0;
! 
  	if ( !PyArg_ParseTuple(args, "t#:a2b_hqx", &ascii_data, &len) )
  		return NULL;
***************
*** 517,521 ****
  		}
  	}
! 	
  	if ( leftbits && !done ) {
  		PyErr_SetString(Incomplete,
--- 517,521 ----
  		}
  	}
! 
  	if ( leftbits && !done ) {
  		PyErr_SetString(Incomplete,
***************
*** 544,548 ****
  	unsigned char ch;
  	int in, inend, len;
! 	
  	if ( !PyArg_ParseTuple(args, "s#:rlecode_hqx", &in_data, &len) )
  		return NULL;
--- 544,548 ----
  	unsigned char ch;
  	int in, inend, len;
! 
  	if ( !PyArg_ParseTuple(args, "s#:rlecode_hqx", &in_data, &len) )
  		return NULL;
***************
*** 552,556 ****
  		return NULL;
  	out_data = (unsigned char *)PyString_AsString(rv);
! 	
  	for( in=0; in<len; in++) {
  		ch = in_data[in];
--- 552,556 ----
  		return NULL;
  	out_data = (unsigned char *)PyString_AsString(rv);
! 
  	for( in=0; in<len; in++) {
  		ch = in_data[in];
***************
*** 583,587 ****
  
  PyDoc_STRVAR(doc_b2a_hqx, "Encode .hqx data");
! 	
  static PyObject *
  binascii_b2a_hqx(PyObject *self, PyObject *args)
--- 583,587 ----
  
  PyDoc_STRVAR(doc_b2a_hqx, "Encode .hqx data");
! 
  static PyObject *
  binascii_b2a_hqx(PyObject *self, PyObject *args)
***************
*** 593,597 ****
  	PyObject *rv;
  	int len;
! 	
  	if ( !PyArg_ParseTuple(args, "s#:b2a_hqx", &bin_data, &len) )
  		return NULL;
--- 593,597 ----
  	PyObject *rv;
  	int len;
! 
  	if ( !PyArg_ParseTuple(args, "s#:b2a_hqx", &bin_data, &len) )
  		return NULL;
***************
*** 601,605 ****
  		return NULL;
  	ascii_data = (unsigned char *)PyString_AsString(rv);
! 	
  	for( ; len > 0 ; len--, bin_data++ ) {
  		/* Shift into our buffer, and output any 6bits ready */
--- 601,605 ----
  		return NULL;
  	ascii_data = (unsigned char *)PyString_AsString(rv);
! 
  	for( ; len > 0 ; len--, bin_data++ ) {
  		/* Shift into our buffer, and output any 6bits ready */
***************
*** 623,627 ****
  
  PyDoc_STRVAR(doc_rledecode_hqx, "Decode hexbin RLE-coded string");
! 	
  static PyObject *
  binascii_rledecode_hqx(PyObject *self, PyObject *args)
--- 623,627 ----
  
  PyDoc_STRVAR(doc_rledecode_hqx, "Decode hexbin RLE-coded string");
! 
  static PyObject *
  binascii_rledecode_hqx(PyObject *self, PyObject *args)
***************
*** 659,663 ****
  		 b = *in_data++; \
  	} while(0)
! 	    
  #define OUTBYTE(b) \
  	do { \
--- 659,663 ----
  		 b = *in_data++; \
  	} while(0)
! 
  #define OUTBYTE(b) \
  	do { \
***************
*** 693,697 ****
  		OUTBYTE(in_byte);
  	}
! 	
  	while( in_len > 0 ) {
  		INBYTE(in_byte);
--- 693,697 ----
  		OUTBYTE(in_byte);
  	}
! 
  	while( in_len > 0 ) {
  		INBYTE(in_byte);
***************
*** 727,731 ****
  	unsigned int crc;
  	int len;
! 	
  	if ( !PyArg_ParseTuple(args, "s#i:crc_hqx", &bin_data, &len, &crc) )
  		return NULL;
--- 727,731 ----
  	unsigned int crc;
  	int len;
! 
  	if ( !PyArg_ParseTuple(args, "s#i:crc_hqx", &bin_data, &len, &crc) )
  		return NULL;
***************
*** 759,805 ****
   Copyright (C) 1986 Gary S. Brown.  You may use this program, or
   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   
!  is what we're using (we're merely optimizing it by doing eight-bit  
!  chunks at a time) shifts bits into the lowest-order term.  In our   
!  implementation, that means shifting towards the right.  Why do we   
!  do it this way?  Because the calculated CRC must be transmitted in  
!  order from highest-order term to lowest-order term.  UARTs transmit 
!  characters in order from LSB to MSB.  By storing the CRC this way,  
!  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:   
!                                                                      
!   1. The table can be generated at runtime if desired; code to do so 
!      is shown later.  It might not be obvious, but the feedback      
!      terms simply represent the results of eight shift/xor opera-    
!      tions for all combinations of data and CRC register values.     
!                                                                      
!   2. The CRC accumulation logic is the same for all CRC polynomials, 
!      be they sixteen or thirty-two bits wide.  You simply choose the 
!      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.                                   
  ********************************************************************/
  
--- 759,805 ----
   Copyright (C) 1986 Gary S. Brown.  You may use this program, or
   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
!  is what we're using (we're merely optimizing it by doing eight-bit
!  chunks at a time) shifts bits into the lowest-order term.  In our
!  implementation, that means shifting towards the right.  Why do we
!  do it this way?  Because the calculated CRC must be transmitted in
!  order from highest-order term to lowest-order term.  UARTs transmit
!  characters in order from LSB to MSB.  By storing the CRC this way,
!  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:
! 
!   1. The table can be generated at runtime if desired; code to do so
!      is shown later.  It might not be obvious, but the feedback
!      terms simply represent the results of eight shift/xor opera-
!      tions for all combinations of data and CRC register values.
! 
!   2. The CRC accumulation logic is the same for all CRC polynomials,
!      be they sixteen or thirty-two bits wide.  You simply choose the
!      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.
  ********************************************************************/
  
***************
*** 866,886 ****
  	int len;
  	long result;
! 	
  	if ( !PyArg_ParseTuple(args, "s#|l:crc32", &bin_data, &len, &crc) )
  		return NULL;
  
! 	crc = crc ^ 0xFFFFFFFFUL;
! 	while(len--)
  		crc = crc_32_tab[(crc ^ *bin_data++) & 0xffUL] ^ (crc >> 8);
  		/* Note:  (crc >> 8) MUST zero fill on left */
  
  	result = (long)(crc ^ 0xFFFFFFFFUL);
! 	/* If long is > 32 bits, extend the sign bit.  This is one way to
! 	 * ensure the result is the same across platforms.  The other way
! 	 * would be to return an unbounded long, but the evidence suggests
! 	 * that lots of code outside this treats the result as if it were
! 	 * a signed 4-byte integer.
  	 */
  	result |= -(result & (1L << 31));
  	return PyInt_FromLong(result);
  }
--- 866,892 ----
  	int len;
  	long result;
! 
  	if ( !PyArg_ParseTuple(args, "s#|l:crc32", &bin_data, &len, &crc) )
  		return NULL;
  
! 	crc = ~ crc;
! #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);
  		/* Note:  (crc >> 8) MUST zero fill on left */
  
  	result = (long)(crc ^ 0xFFFFFFFFUL);
! #if SIZEOF_LONG > 4
! 	/* Extend the sign bit.  This is one way to ensure the result is the
! 	 * same across platforms.  The other way would be to return an
! 	 * unbounded unsigned long, but the evidence suggests that lots of
! 	 * code outside this treats the result as if it were a signed 4-byte
! 	 * integer.
  	 */
  	result |= -(result & (1L << 31));
+ #endif
  	return PyInt_FromLong(result);
  }
***************
*** 930,934 ****
  
  static int
! to_int(int c) 
  {
  	if (isdigit(c))
--- 936,940 ----
  
  static int
! to_int(int c)
  {
  	if (isdigit(c))
***************
*** 1012,1016 ****
  PyDoc_STRVAR(doc_a2b_qp, "Decode a string of qp-encoded data");
  
! static PyObject* 
  binascii_a2b_qp(PyObject *self, PyObject *args, PyObject *kwargs)
  {
--- 1018,1022 ----
  PyDoc_STRVAR(doc_a2b_qp, "Decode a string of qp-encoded data");
  
! static PyObject*
  binascii_a2b_qp(PyObject *self, PyObject *args, PyObject *kwargs)
  {
***************
*** 1023,1027 ****
  	int header = 0;
  
! 	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#|i", kwlist, &data, 
  	      &datalen, &header))
  		return NULL;
--- 1029,1033 ----
  	int header = 0;
  
! 	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#|i", kwlist, &data,
  	      &datalen, &header))
  		return NULL;
***************
*** 1041,1045 ****
  			if (in >= datalen) break;
  			/* Soft line breaks */
! 			if ((data[in] == '\n') || (data[in] == '\r') || 
  			    (data[in] == ' ') || (data[in] == '\t')) {
  				if (data[in] != '\n') {
--- 1047,1051 ----
  			if (in >= datalen) break;
  			/* Soft line breaks */
! 			if ((data[in] == '\n') || (data[in] == '\r') ||
  			    (data[in] == ' ') || (data[in] == '\t')) {
  				if (data[in] != '\n') {
***************
*** 1053,1057 ****
  				in++;
  			}
! 			else if (((data[in] >= 'A' && data[in] <= 'F') || 
  			          (data[in] >= 'a' && data[in] <= 'f') ||
  				  (data[in] >= '0' && data[in] <= '9')) &&
--- 1059,1063 ----
  				in++;
  			}
! 			else if (((data[in] >= 'A' && data[in] <= 'F') ||
  			          (data[in] >= 'a' && data[in] <= 'f') ||
  				  (data[in] >= '0' && data[in] <= '9')) &&
***************
*** 1088,1092 ****
  }
  
! static int 
  to_hex (unsigned char ch, unsigned char *s)
  {
--- 1094,1098 ----
  }
  
! static int
  to_hex (unsigned char ch, unsigned char *s)
  {
***************
*** 1110,1114 ****
   * (mostly) with the quopri module.  It doesn't re-create the quopri
   * module bug where text ending in CRLF has the CR encoded */
! static PyObject* 
  binascii_b2a_qp (PyObject *self, PyObject *args, PyObject *kwargs)
  {
--- 1116,1120 ----
   * (mostly) with the quopri module.  It doesn't re-create the quopri
   * module bug where text ending in CRLF has the CR encoded */
! static PyObject*
  binascii_b2a_qp (PyObject *self, PyObject *args, PyObject *kwargs)
  {
***************
*** 1126,1130 ****
  	unsigned char *p;
  
! 	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#|iii", kwlist, &data, 
  	      &datalen, &quotetabs, &istext, &header))
  		return NULL;
--- 1132,1136 ----
  	unsigned char *p;
  
! 	if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#|iii", kwlist, &data,
  	      &datalen, &quotetabs, &istext, &header))
  		return NULL;
***************
*** 1141,1145 ****
  	in = 0;
  	while (in < datalen) {
! 		if ((data[in] > 126) || 
  		    (data[in] == '=') ||
  		    (header && data[in] == '_') ||
--- 1147,1151 ----
  	in = 0;
  	while (in < datalen) {
! 		if ((data[in] > 126) ||
  		    (data[in] == '=') ||
  		    (header && data[in] == '_') ||
***************
*** 1147,1152 ****
  		    (!istext && ((data[in] == '\r') || (data[in] == '\n'))) ||
  		    ((data[in] == '\t' || data[in] == ' ') && (in + 1 == datalen)) ||
! 		    ((data[in] < 33) && 
! 		     (data[in] != '\r') && (data[in] != '\n') && 
  		     (quotetabs && ((data[in] != '\t') || (data[in] != ' ')))))
  		{
--- 1153,1158 ----
  		    (!istext && ((data[in] == '\r') || (data[in] == '\n'))) ||
  		    ((data[in] == '\t' || data[in] == ' ') && (in + 1 == datalen)) ||
! 		    ((data[in] < 33) &&
! 		     (data[in] != '\r') && (data[in] != '\n') &&
  		     (quotetabs && ((data[in] != '\t') || (data[in] != ' ')))))
  		{
***************
*** 1163,1167 ****
  		}
  		else {
! 		  	if (istext && 
  			    ((data[in] == '\n') ||
  			     ((in+1 < datalen) && (data[in] == '\r') &&
--- 1169,1173 ----
  		}
  		else {
! 		  	if (istext &&
  			    ((data[in] == '\n') ||
  			     ((in+1 < datalen) && (data[in] == '\r') &&
***************
*** 1182,1186 ****
  			}
  			else {
! 				if ((in + 1 != datalen) && 
  				    (data[in+1] != '\n') &&
  				    (linelen + 1) >= MAXLINESIZE) {
--- 1188,1192 ----
  			}
  			else {
! 				if ((in + 1 != datalen) &&
  				    (data[in+1] != '\n') &&
  				    (linelen + 1) >= MAXLINESIZE) {
***************
*** 1207,1211 ****
  	in = out = linelen = 0;
  	while (in < datalen) {
! 		if ((data[in] > 126) || 
  		    (data[in] == '=') ||
  		    (header && data[in] == '_') ||
--- 1213,1217 ----
  	in = out = linelen = 0;
  	while (in < datalen) {
! 		if ((data[in] > 126) ||
  		    (data[in] == '=') ||
  		    (header && data[in] == '_') ||
***************
*** 1213,1218 ****
  		    (!istext && ((data[in] == '\r') || (data[in] == '\n'))) ||
  		    ((data[in] == '\t' || data[in] == ' ') && (in + 1 == datalen)) ||
! 		    ((data[in] < 33) && 
! 		     (data[in] != '\r') && (data[in] != '\n') && 
  		     (quotetabs && ((data[in] != '\t') || (data[in] != ' ')))))
  		{
--- 1219,1224 ----
  		    (!istext && ((data[in] == '\r') || (data[in] == '\n'))) ||
  		    ((data[in] == '\t' || data[in] == ' ') && (in + 1 == datalen)) ||
! 		    ((data[in] < 33) &&
! 		     (data[in] != '\r') && (data[in] != '\n') &&
  		     (quotetabs && ((data[in] != '\t') || (data[in] != ' ')))))
  		{
***************
*** 1230,1234 ****
  		}
  		else {
! 		  	if (istext && 
  			    ((data[in] == '\n') ||
  			     ((in+1 < datalen) && (data[in] == '\r') &&
--- 1236,1240 ----
  		}
  		else {
! 		  	if (istext &&
  			    ((data[in] == '\n') ||
  			     ((in+1 < datalen) && (data[in] == '\r') &&
***************
*** 1243,1247 ****
  					out += 2;
  				}
! 					
  				if (crlf) odata[out++] = '\r';
  				odata[out++] = '\n';
--- 1249,1253 ----
  					out += 2;
  				}
! 
  				if (crlf) odata[out++] = '\r';
  				odata[out++] = '\n';
***************
*** 1252,1256 ****
  			}
  			else {
! 				if ((in + 1 != datalen) && 
  				    (data[in+1] != '\n') &&
  				    (linelen + 1) >= MAXLINESIZE) {
--- 1258,1262 ----
  			}
  			else {
! 				if ((in + 1 != datalen) &&
  				    (data[in+1] != '\n') &&
  				    (linelen + 1) >= MAXLINESIZE) {
***************
*** 1297,1303 ****
  	{"crc_hqx",    binascii_crc_hqx,    METH_VARARGS, doc_crc_hqx},
  	{"crc32",      binascii_crc32,      METH_VARARGS, doc_crc32},
! 	{"a2b_qp", (PyCFunction)binascii_a2b_qp, METH_VARARGS | METH_KEYWORDS, 
  	  doc_a2b_qp},
! 	{"b2a_qp", (PyCFunction)binascii_b2a_qp, METH_VARARGS | METH_KEYWORDS, 
            doc_b2a_qp},
  	{NULL, NULL}			     /* sentinel */
--- 1303,1309 ----
  	{"crc_hqx",    binascii_crc_hqx,    METH_VARARGS, doc_crc_hqx},
  	{"crc32",      binascii_crc32,      METH_VARARGS, doc_crc32},
! 	{"a2b_qp", (PyCFunction)binascii_a2b_qp, METH_VARARGS | METH_KEYWORDS,
  	  doc_a2b_qp},
! 	{"b2a_qp", (PyCFunction)binascii_b2a_qp, METH_VARARGS | METH_KEYWORDS,
            doc_b2a_qp},
  	{NULL, NULL}			     /* sentinel */