Added base64 support
This commit is contained in:
parent
5a49ffca5e
commit
84bbc2e3e3
|
@ -35,6 +35,11 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
** ASCII encoding method is "excess-space": 000000 is encoded as ' ', etc.
|
||||
** short binary data is zero-extended (so the bits are always in the
|
||||
** right place), this does *not* reflect in the length.
|
||||
** base64:
|
||||
** Line breaks are insignificant, but lines are at most 76 chars
|
||||
** each char encodes 6 bits, in similar order as uucode/hqx. Encoding
|
||||
** is done via a table.
|
||||
** Short binary data is filled (in ASCII) with '='.
|
||||
** hqx:
|
||||
** File starts with introductory text, real data starts and ends
|
||||
** with colons.
|
||||
|
@ -133,6 +138,25 @@ static unsigned char table_a2b_hqx[256] = {
|
|||
static unsigned char table_b2a_hqx[] =
|
||||
"!\"#$%&'()*+,-012345689@ABCDEFGHIJKLMNPQRSTUVXYZ[`abcdefhijklmpqr";
|
||||
|
||||
static char table_a2b_base64[] = {
|
||||
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
|
||||
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
|
||||
-1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63,
|
||||
52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1, 0,-1,-1, /* Note PAD->0 */
|
||||
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14,
|
||||
15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1,
|
||||
-1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40,
|
||||
41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1
|
||||
};
|
||||
|
||||
#define BASE64_PAD '='
|
||||
#define BASE64_MAXBIN 57 /* Max binary chunk size (76 char line) */
|
||||
|
||||
static unsigned char table_b2a_base64[] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
|
||||
|
||||
static unsigned short crctab_hqx[256] = {
|
||||
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
|
||||
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
|
||||
|
@ -290,6 +314,119 @@ binascii_b2a_uu(self, args)
|
|||
return rv;
|
||||
}
|
||||
|
||||
static char doc_a2b_base64[] = "(ascii) -> bin. Decode a line of base64 data";
|
||||
|
||||
static PyObject *
|
||||
binascii_a2b_base64(self, args)
|
||||
PyObject *self;
|
||||
PyObject *args;
|
||||
{
|
||||
unsigned char *ascii_data, *bin_data;
|
||||
int leftbits = 0;
|
||||
unsigned char this_ch;
|
||||
unsigned int leftchar = 0;
|
||||
int npad = 0;
|
||||
PyObject *rv;
|
||||
int ascii_len, bin_len;
|
||||
|
||||
if ( !PyArg_ParseTuple(args, "s#", &ascii_data, &ascii_len) )
|
||||
return NULL;
|
||||
|
||||
bin_len = ((ascii_len+3)/4)*3; /* Upper bound, corrected later */
|
||||
|
||||
/* Allocate the buffer */
|
||||
if ( (rv=PyString_FromStringAndSize(NULL, bin_len)) == NULL )
|
||||
return NULL;
|
||||
bin_data = (unsigned char *)PyString_AsString(rv);
|
||||
bin_len = 0;
|
||||
for( ; ascii_len > 0 ; ascii_len--, ascii_data++ ) {
|
||||
/*
|
||||
** XXXX I don't do any checks on the chars, ignoring
|
||||
** any illegal chars. Hope this is correct...
|
||||
*/
|
||||
this_ch = (*ascii_data & 0x7f);
|
||||
if ( this_ch == BASE64_PAD )
|
||||
npad++;
|
||||
this_ch = table_a2b_base64[(*ascii_data) & 0x7f];
|
||||
if ( this_ch == -1 ) continue;
|
||||
/*
|
||||
** Shift it in on the low end, and see if there's
|
||||
** a byte ready for output.
|
||||
*/
|
||||
leftchar = (leftchar << 6) | (this_ch);
|
||||
leftbits += 6;
|
||||
if ( leftbits >= 8 ) {
|
||||
leftbits -= 8;
|
||||
*bin_data++ = (leftchar >> leftbits) & 0xff;
|
||||
leftchar &= ((1 << leftbits) - 1);
|
||||
bin_len++;
|
||||
}
|
||||
}
|
||||
/* Check that no bits are left */
|
||||
if ( leftbits ) {
|
||||
PyErr_SetString(Error, "Incorrect padding");
|
||||
Py_DECREF(rv);
|
||||
return NULL;
|
||||
}
|
||||
/* and remove any padding */
|
||||
bin_len -= npad;
|
||||
/* and set string size correctly */
|
||||
_PyString_Resize(&rv, bin_len);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static char doc_b2a_base64[] = "(bin) -> ascii. Base64-code line of data";
|
||||
|
||||
static PyObject *
|
||||
binascii_b2a_base64(self, args)
|
||||
PyObject *self;
|
||||
PyObject *args;
|
||||
{
|
||||
unsigned char *ascii_data, *bin_data;
|
||||
int leftbits = 0;
|
||||
unsigned char this_ch;
|
||||
unsigned int leftchar = 0;
|
||||
PyObject *rv;
|
||||
int bin_len;
|
||||
|
||||
if ( !PyArg_ParseTuple(args, "s#", &bin_data, &bin_len) )
|
||||
return NULL;
|
||||
if ( bin_len > BASE64_MAXBIN ) {
|
||||
PyErr_SetString(Error, "Too much data for base64 line");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* We're lazy and allocate to much (fixed up later) */
|
||||
if ( (rv=PyString_FromStringAndSize(NULL, bin_len*2)) == NULL )
|
||||
return NULL;
|
||||
ascii_data = (unsigned char *)PyString_AsString(rv);
|
||||
|
||||
for( ; bin_len > 0 ; bin_len--, bin_data++ ) {
|
||||
/* Shift the data into our buffer */
|
||||
leftchar = (leftchar << 8) | *bin_data;
|
||||
leftbits += 8;
|
||||
|
||||
/* See if there are 6-bit groups ready */
|
||||
while ( leftbits >= 6 ) {
|
||||
this_ch = (leftchar >> (leftbits-6)) & 0x3f;
|
||||
leftbits -= 6;
|
||||
*ascii_data++ = table_b2a_base64[this_ch];
|
||||
}
|
||||
}
|
||||
if ( leftbits == 2 ) {
|
||||
*ascii_data++ = table_b2a_base64[(leftchar&3) << 4];
|
||||
*ascii_data++ = BASE64_PAD;
|
||||
*ascii_data++ = BASE64_PAD;
|
||||
} else if ( leftbits == 4 ) {
|
||||
*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)));
|
||||
return rv;
|
||||
}
|
||||
|
||||
static char doc_a2b_hqx[] = "ascii -> bin, done. Decode .hqx coding";
|
||||
|
||||
static PyObject *
|
||||
|
@ -562,6 +699,10 @@ binascii_crc_hqx(self, args)
|
|||
static struct PyMethodDef binascii_module_methods[] = {
|
||||
{"a2b_uu", binascii_a2b_uu, 1, doc_a2b_uu},
|
||||
{"b2a_uu", binascii_b2a_uu, 1, doc_b2a_uu},
|
||||
{"a2b_base64", binascii_a2b_base64, 1,
|
||||
doc_a2b_base64},
|
||||
{"b2a_base64", binascii_b2a_base64, 1,
|
||||
doc_b2a_base64},
|
||||
{"a2b_hqx", binascii_a2b_hqx, 1, doc_a2b_hqx},
|
||||
{"b2a_hqx", binascii_b2a_hqx, 1, doc_b2a_hqx},
|
||||
{"rlecode_hqx", binascii_rlecode_hqx, 1,
|
||||
|
|
Loading…
Reference in New Issue