blob: 8d4784033afe00c4b4bba2f53db9718bb29952cb [file] [log] [blame]
Jack Jansen72781191995-08-07 14:34:15 +00001/***********************************************************
2Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
3Amsterdam, The Netherlands.
4
5 All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI not be used in advertising or publicity pertaining to
13distribution of the software without specific, written prior permission.
14
15STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23******************************************************************/
24
25/*
26** Routines to represent binary data in ASCII and vice-versa
27**
28** This module currently supports the following encodings:
29** uuencode:
30** each line encodes 45 bytes (except possibly the last)
31** First char encodes (binary) length, rest data
32** each char encodes 6 bits, as follows:
33** binary: 01234567 abcdefgh ijklmnop
34** ascii: 012345 67abcd efghij klmnop
35** ASCII encoding method is "excess-space": 000000 is encoded as ' ', etc.
36** short binary data is zero-extended (so the bits are always in the
37** right place), this does *not* reflect in the length.
Jack Jansen84bbc2e1995-10-04 16:38:44 +000038** base64:
39** Line breaks are insignificant, but lines are at most 76 chars
40** each char encodes 6 bits, in similar order as uucode/hqx. Encoding
41** is done via a table.
42** Short binary data is filled (in ASCII) with '='.
Jack Jansen72781191995-08-07 14:34:15 +000043** hqx:
44** File starts with introductory text, real data starts and ends
45** with colons.
46** Data consists of three similar parts: info, datafork, resourcefork.
47** Each part is protected (at the end) with a 16-bit crc
48** The binary data is run-length encoded, and then ascii-fied:
49** binary: 01234567 abcdefgh ijklmnop
50** ascii: 012345 67abcd efghij klmnop
51** ASCII encoding is table-driven, see the code.
52** Short binary data results in the runt ascii-byte being output with
53** the bits in the right place.
54**
55** While I was reading dozens of programs that encode or decode the formats
56** here (documentation? hihi:-) I have formulated Jansen's Observation:
57**
58** Programs that encode binary data in ASCII are written in
59** such a style that they are as unreadable as possible. Devices used
60** include unnecessary global variables, burying important tables
61** in unrelated sourcefiles, putting functions in include files,
62** using seemingly-descriptive variable names for different purposes,
63** calls to empty subroutines and a host of others.
64**
65** I have attempted to break with this tradition, but I guess that that
66** does make the performance sub-optimal. Oh well, too bad...
67**
68** Jack Jansen, CWI, July 1995.
69*/
70
71
72#include "Python.h"
73
74static PyObject *Error;
75static PyObject *Incomplete;
76
77/*
78** hqx lookup table, ascii->binary.
79*/
80
81#define RUNCHAR 0x90
82
83#define DONE 0x7F
84#define SKIP 0x7E
85#define FAIL 0x7D
86
87static unsigned char table_a2b_hqx[256] = {
88/* ^@ ^A ^B ^C ^D ^E ^F ^G */
89/* 0*/ FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
90/* \b \t \n ^K ^L \r ^N ^O */
91/* 1*/ FAIL, FAIL, SKIP, FAIL, FAIL, SKIP, FAIL, FAIL,
92/* ^P ^Q ^R ^S ^T ^U ^V ^W */
93/* 2*/ FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
94/* ^X ^Y ^Z ^[ ^\ ^] ^^ ^_ */
95/* 3*/ FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
96/* ! " # $ % & ' */
97/* 4*/ FAIL, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
98/* ( ) * + , - . / */
99/* 5*/ 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, FAIL, FAIL,
100/* 0 1 2 3 4 5 6 7 */
101/* 6*/ 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, FAIL,
102/* 8 9 : ; < = > ? */
103/* 7*/ 0x14, 0x15, DONE, FAIL, FAIL, FAIL, FAIL, FAIL,
104/* @ A B C D E F G */
105/* 8*/ 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D,
106/* H I J K L M N O */
107/* 9*/ 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, FAIL,
108/* P Q R S T U V W */
109/*10*/ 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, FAIL,
110/* X Y Z [ \ ] ^ _ */
111/*11*/ 0x2C, 0x2D, 0x2E, 0x2F, FAIL, FAIL, FAIL, FAIL,
112/* ` a b c d e f g */
113/*12*/ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, FAIL,
114/* h i j k l m n o */
115/*13*/ 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, FAIL, FAIL,
116/* p q r s t u v w */
117/*14*/ 0x3D, 0x3E, 0x3F, FAIL, FAIL, FAIL, FAIL, FAIL,
118/* x y z { | } ~ ^? */
119/*15*/ FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
120/*16*/ FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
121 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
122 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
123 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
124 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
125 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
126 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
127 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
128 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
129 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
130 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
131 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
132 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
133 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
134 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
135 FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL, FAIL,
136};
137
138static unsigned char table_b2a_hqx[] =
139 "!\"#$%&'()*+,-012345689@ABCDEFGHIJKLMNPQRSTUVXYZ[`abcdefhijklmpqr";
140
Jack Jansen84bbc2e1995-10-04 16:38:44 +0000141static char table_a2b_base64[] = {
142 -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
143 -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
144 -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63,
145 52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1, 0,-1,-1, /* Note PAD->0 */
146 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14,
147 15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1,
148 -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40,
149 41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1
150};
151
152#define BASE64_PAD '='
153#define BASE64_MAXBIN 57 /* Max binary chunk size (76 char line) */
154
155static unsigned char table_b2a_base64[] =
156 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
157
158
159
Jack Jansen72781191995-08-07 14:34:15 +0000160static unsigned short crctab_hqx[256] = {
161 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
162 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
163 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
164 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
165 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
166 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
167 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
168 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
169 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
170 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
171 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
172 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
173 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
174 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
175 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
176 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
177 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
178 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
179 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
180 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
181 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
182 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
183 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
184 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
185 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
186 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
187 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
188 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
189 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
190 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
191 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
192 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0,
193};
194
195static char doc_a2b_uu[] = "(ascii) -> bin. Decode a line of uuencoded data";
196
197static PyObject *
198binascii_a2b_uu(self, args)
199 PyObject *self;
200 PyObject *args;
201{
202 unsigned char *ascii_data, *bin_data;
203 int leftbits = 0;
204 unsigned char this_ch;
205 unsigned int leftchar = 0;
206 PyObject *rv;
207 int ascii_len, bin_len;
208
209 if ( !PyArg_ParseTuple(args, "s#", &ascii_data, &ascii_len) )
210 return NULL;
211
212 /* First byte: binary data length (in bytes) */
213 bin_len = (*ascii_data++ - ' ') & 077;
214 ascii_len--;
215
216 /* Allocate the buffer */
217 if ( (rv=PyString_FromStringAndSize(NULL, bin_len)) == NULL )
218 return NULL;
219 bin_data = (unsigned char *)PyString_AsString(rv);
220
221 for( ; bin_len > 0 ; ascii_len--, ascii_data++ ) {
222 this_ch = *ascii_data;
223 if ( this_ch == '\n' || this_ch == '\r' || ascii_len <= 0) {
224 /*
225 ** Whitespace. Assume some spaces got eaten at
226 ** end-of-line. (We check this later)
227 */
228 this_ch = 0;
229 } else {
Jack Jansen5d957971995-11-14 10:35:19 +0000230 /* Check the character for legality
231 ** The 64 in stead of the expected 63 is because there are a few
232 ** uuencodes out there that use '@' as zero in stead of space.
233 */
234 if ( this_ch < ' ' || this_ch > (' ' + 64)) {
Jack Jansen72781191995-08-07 14:34:15 +0000235 PyErr_SetString(Error, "Illegal char");
236 Py_DECREF(rv);
237 return NULL;
238 }
239 this_ch = (this_ch - ' ') & 077;
240 }
241 /*
242 ** Shift it in on the low end, and see if there's
243 ** a byte ready for output.
244 */
245 leftchar = (leftchar << 6) | (this_ch);
246 leftbits += 6;
247 if ( leftbits >= 8 ) {
248 leftbits -= 8;
249 *bin_data++ = (leftchar >> leftbits) & 0xff;
250 leftchar &= ((1 << leftbits) - 1);
251 bin_len--;
252 }
253 }
254 /*
255 ** Finally, check that if there's anything left on the line
256 ** that it's whitespace only.
257 */
258 while( ascii_len-- > 0 ) {
259 this_ch = *ascii_data++;
260 if ( this_ch != ' ' && this_ch != '\n' && this_ch != '\r' ) {
261 PyErr_SetString(Error, "Trailing garbage");
262 Py_DECREF(rv);
263 return NULL;
264 }
265 }
266 return rv;
267}
268
269static char doc_b2a_uu[] = "(bin) -> ascii. Uuencode line of data";
270
271static PyObject *
272binascii_b2a_uu(self, args)
273 PyObject *self;
274 PyObject *args;
275{
276 unsigned char *ascii_data, *bin_data;
277 int leftbits = 0;
278 unsigned char this_ch;
279 unsigned int leftchar = 0;
280 PyObject *rv;
281 int bin_len;
282
283 if ( !PyArg_ParseTuple(args, "s#", &bin_data, &bin_len) )
284 return NULL;
285 if ( bin_len > 45 ) {
286 /* The 45 is a limit that appears in all uuencode's */
287 PyErr_SetString(Error, "At most 45 bytes at once");
288 return NULL;
289 }
290
291 /* We're lazy and allocate to much (fixed up later) */
292 if ( (rv=PyString_FromStringAndSize(NULL, bin_len*2)) == NULL )
293 return NULL;
294 ascii_data = (unsigned char *)PyString_AsString(rv);
295
296 /* Store the length */
297 *ascii_data++ = ' ' + (bin_len & 077);
298
299 for( ; bin_len > 0 || leftbits != 0 ; bin_len--, bin_data++ ) {
300 /* Shift the data (or padding) into our buffer */
301 if ( bin_len > 0 ) /* Data */
302 leftchar = (leftchar << 8) | *bin_data;
303 else /* Padding */
304 leftchar <<= 8;
305 leftbits += 8;
306
307 /* See if there are 6-bit groups ready */
308 while ( leftbits >= 6 ) {
309 this_ch = (leftchar >> (leftbits-6)) & 0x3f;
310 leftbits -= 6;
311 *ascii_data++ = this_ch + ' ';
312 }
313 }
314 *ascii_data++ = '\n'; /* Append a courtesy newline */
315
316 _PyString_Resize(&rv, (ascii_data - (unsigned char *)PyString_AsString(rv)));
317 return rv;
318}
319
Jack Jansen84bbc2e1995-10-04 16:38:44 +0000320static char doc_a2b_base64[] = "(ascii) -> bin. Decode a line of base64 data";
321
322static PyObject *
323binascii_a2b_base64(self, args)
324 PyObject *self;
325 PyObject *args;
326{
327 unsigned char *ascii_data, *bin_data;
328 int leftbits = 0;
329 unsigned char this_ch;
330 unsigned int leftchar = 0;
331 int npad = 0;
332 PyObject *rv;
333 int ascii_len, bin_len;
334
335 if ( !PyArg_ParseTuple(args, "s#", &ascii_data, &ascii_len) )
336 return NULL;
337
338 bin_len = ((ascii_len+3)/4)*3; /* Upper bound, corrected later */
339
340 /* Allocate the buffer */
341 if ( (rv=PyString_FromStringAndSize(NULL, bin_len)) == NULL )
342 return NULL;
343 bin_data = (unsigned char *)PyString_AsString(rv);
344 bin_len = 0;
345 for( ; ascii_len > 0 ; ascii_len--, ascii_data++ ) {
346 /*
347 ** XXXX I don't do any checks on the chars, ignoring
348 ** any illegal chars. Hope this is correct...
349 */
350 this_ch = (*ascii_data & 0x7f);
351 if ( this_ch == BASE64_PAD )
352 npad++;
353 this_ch = table_a2b_base64[(*ascii_data) & 0x7f];
354 if ( this_ch == -1 ) continue;
355 /*
356 ** Shift it in on the low end, and see if there's
357 ** a byte ready for output.
358 */
359 leftchar = (leftchar << 6) | (this_ch);
360 leftbits += 6;
361 if ( leftbits >= 8 ) {
362 leftbits -= 8;
363 *bin_data++ = (leftchar >> leftbits) & 0xff;
364 leftchar &= ((1 << leftbits) - 1);
365 bin_len++;
366 }
367 }
368 /* Check that no bits are left */
369 if ( leftbits ) {
370 PyErr_SetString(Error, "Incorrect padding");
371 Py_DECREF(rv);
372 return NULL;
373 }
374 /* and remove any padding */
375 bin_len -= npad;
376 /* and set string size correctly */
377 _PyString_Resize(&rv, bin_len);
378 return rv;
379}
380
381static char doc_b2a_base64[] = "(bin) -> ascii. Base64-code line of data";
382
383static PyObject *
384binascii_b2a_base64(self, args)
385 PyObject *self;
386 PyObject *args;
387{
388 unsigned char *ascii_data, *bin_data;
389 int leftbits = 0;
390 unsigned char this_ch;
391 unsigned int leftchar = 0;
392 PyObject *rv;
393 int bin_len;
394
395 if ( !PyArg_ParseTuple(args, "s#", &bin_data, &bin_len) )
396 return NULL;
397 if ( bin_len > BASE64_MAXBIN ) {
398 PyErr_SetString(Error, "Too much data for base64 line");
399 return NULL;
400 }
401
402 /* We're lazy and allocate to much (fixed up later) */
403 if ( (rv=PyString_FromStringAndSize(NULL, bin_len*2)) == NULL )
404 return NULL;
405 ascii_data = (unsigned char *)PyString_AsString(rv);
406
407 for( ; bin_len > 0 ; bin_len--, bin_data++ ) {
408 /* Shift the data into our buffer */
409 leftchar = (leftchar << 8) | *bin_data;
410 leftbits += 8;
411
412 /* See if there are 6-bit groups ready */
413 while ( leftbits >= 6 ) {
414 this_ch = (leftchar >> (leftbits-6)) & 0x3f;
415 leftbits -= 6;
416 *ascii_data++ = table_b2a_base64[this_ch];
417 }
418 }
419 if ( leftbits == 2 ) {
420 *ascii_data++ = table_b2a_base64[(leftchar&3) << 4];
421 *ascii_data++ = BASE64_PAD;
422 *ascii_data++ = BASE64_PAD;
423 } else if ( leftbits == 4 ) {
424 *ascii_data++ = table_b2a_base64[(leftchar&0xf) << 2];
425 *ascii_data++ = BASE64_PAD;
426 }
427 *ascii_data++ = '\n'; /* Append a courtesy newline */
428
429 _PyString_Resize(&rv, (ascii_data - (unsigned char *)PyString_AsString(rv)));
430 return rv;
431}
432
Jack Jansen72781191995-08-07 14:34:15 +0000433static char doc_a2b_hqx[] = "ascii -> bin, done. Decode .hqx coding";
434
435static PyObject *
436binascii_a2b_hqx(self, args)
437 PyObject *self;
438 PyObject *args;
439{
440 unsigned char *ascii_data, *bin_data;
441 int leftbits = 0;
442 unsigned char this_ch;
Jack Janseneaeb1c81995-08-14 12:17:57 +0000443 unsigned int leftchar = 0;
Jack Jansen72781191995-08-07 14:34:15 +0000444 PyObject *rv;
445 int len;
446 int done = 0;
447
448 if ( !PyArg_ParseTuple(args, "s#", &ascii_data, &len) )
449 return NULL;
450
451 /* Allocate a string that is too big (fixed later) */
452 if ( (rv=PyString_FromStringAndSize(NULL, len)) == NULL )
453 return NULL;
454 bin_data = (unsigned char *)PyString_AsString(rv);
455
456 for( ; len > 0 ; len--, ascii_data++ ) {
457 /* Get the byte and look it up */
458 this_ch = table_a2b_hqx[*ascii_data];
459 if ( this_ch == SKIP )
460 continue;
461 if ( this_ch == FAIL ) {
462 PyErr_SetString(Error, "Illegal char");
463 Py_DECREF(rv);
464 return NULL;
465 }
466 if ( this_ch == DONE ) {
467 /* The terminating colon */
468 done = 1;
469 break;
470 }
471
472 /* Shift it into the buffer and see if any bytes are ready */
473 leftchar = (leftchar << 6) | (this_ch);
474 leftbits += 6;
475 if ( leftbits >= 8 ) {
476 leftbits -= 8;
477 *bin_data++ = (leftchar >> leftbits) & 0xff;
478 leftchar &= ((1 << leftbits) - 1);
479 }
480 }
481
482 if ( leftbits && !done ) {
483 PyErr_SetString(Incomplete,
484 "String has incomplete number of bytes");
485 Py_DECREF(rv);
486 return NULL;
487 }
488 _PyString_Resize(&rv, (bin_data - (unsigned char *)PyString_AsString(rv)));
489 if ( rv )
490 return Py_BuildValue("Oi", rv, done);
491 return NULL;
492}
493
494static char doc_rlecode_hqx[] = "Binhex RLE-code binary data";
495
496static PyObject *
497binascii_rlecode_hqx(self, args)
498 PyObject *self;
499 PyObject *args;
500{
501 unsigned char *in_data, *out_data;
502 PyObject *rv;
503 unsigned char ch;
504 int in, inend, len;
505
506 if ( !PyArg_ParseTuple(args, "s#", &in_data, &len) )
507 return NULL;
508
509 /* Worst case: output is twice as big as input (fixed later) */
510 if ( (rv=PyString_FromStringAndSize(NULL, len*2)) == NULL )
511 return NULL;
512 out_data = (unsigned char *)PyString_AsString(rv);
513
514 for( in=0; in<len; in++) {
515 ch = in_data[in];
516 if ( ch == RUNCHAR ) {
517 /* RUNCHAR. Escape it. */
518 *out_data++ = RUNCHAR;
519 *out_data++ = 0;
520 } else {
521 /* Check how many following are the same */
522 for(inend=in+1;
523 inend<len && in_data[inend] == ch &&
524 inend < in+255;
525 inend++) ;
Jack Jansen0223aa11995-08-31 13:44:23 +0000526 if ( inend - in > 3 ) {
527 /* More than 3 in a row. Output RLE. */
Jack Jansen72781191995-08-07 14:34:15 +0000528 *out_data++ = ch;
529 *out_data++ = RUNCHAR;
530 *out_data++ = inend-in;
531 in = inend-1;
532 } else {
533 /* Less than 3. Output the byte itself */
534 *out_data++ = ch;
535 }
536 }
537 }
538 _PyString_Resize(&rv, (out_data - (unsigned char *)PyString_AsString(rv)));
539 return rv;
540}
541
542static char doc_b2a_hqx[] = "Encode .hqx data";
543
544static PyObject *
545binascii_b2a_hqx(self, args)
546 PyObject *self;
547 PyObject *args;
548{
549 unsigned char *ascii_data, *bin_data;
550 int leftbits = 0;
551 unsigned char this_ch;
Jack Janseneaeb1c81995-08-14 12:17:57 +0000552 unsigned int leftchar = 0;
Jack Jansen72781191995-08-07 14:34:15 +0000553 PyObject *rv;
554 int len;
555
556 if ( !PyArg_ParseTuple(args, "s#", &bin_data, &len) )
557 return NULL;
558
559 /* Allocate a buffer that is at least large enough */
560 if ( (rv=PyString_FromStringAndSize(NULL, len*2)) == NULL )
561 return NULL;
562 ascii_data = (unsigned char *)PyString_AsString(rv);
563
564 for( ; len > 0 ; len--, bin_data++ ) {
565 /* Shift into our buffer, and output any 6bits ready */
566 leftchar = (leftchar << 8) | *bin_data;
567 leftbits += 8;
568 while ( leftbits >= 6 ) {
569 this_ch = (leftchar >> (leftbits-6)) & 0x3f;
570 leftbits -= 6;
571 *ascii_data++ = table_b2a_hqx[this_ch];
572 }
573 }
574 /* Output a possible runt byte */
575 if ( leftbits ) {
576 leftchar <<= (6-leftbits);
577 *ascii_data++ = table_b2a_hqx[leftchar & 0x3f];
578 }
579 _PyString_Resize(&rv, (ascii_data - (unsigned char *)PyString_AsString(rv)));
580 return rv;
581}
582
583static char doc_rledecode_hqx[] = "Decode hexbin RLE-coded string";
584
585static PyObject *
586binascii_rledecode_hqx(self, args)
587 PyObject *self;
588 PyObject *args;
589{
590 unsigned char *in_data, *out_data;
591 unsigned char in_byte, in_repeat;
592 PyObject *rv;
593 int in_len, out_len, out_len_left;
594
595 if ( !PyArg_ParseTuple(args, "s#", &in_data, &in_len) )
596 return NULL;
597
598 /* Empty string is a special case */
599 if ( in_len == 0 )
600 return Py_BuildValue("s", "");
601
602 /* Allocate a buffer of reasonable size. Resized when needed */
603 out_len = in_len*2;
604 if ( (rv=PyString_FromStringAndSize(NULL, out_len)) == NULL )
605 return NULL;
606 out_len_left = out_len;
607 out_data = (unsigned char *)PyString_AsString(rv);
608
609 /*
610 ** We need two macros here to get/put bytes and handle
611 ** end-of-buffer for input and output strings.
612 */
613#define INBYTE(b) \
614 do { \
615 if ( --in_len < 0 ) { \
616 PyErr_SetString(Incomplete, ""); \
617 Py_DECREF(rv); \
618 return NULL; \
619 } \
620 b = *in_data++; \
621 } while(0)
622
623#define OUTBYTE(b) \
624 do { \
625 if ( --out_len_left < 0 ) { \
626 _PyString_Resize(&rv, 2*out_len); \
627 if ( rv == NULL ) return NULL; \
628 out_data = (unsigned char *)PyString_AsString(rv) + out_len; \
629 out_len_left = out_len; \
630 out_len = out_len * 2; \
631 } \
632 *out_data++ = b; \
633 } while(0)
634
635 /*
636 ** Handle first byte separately (since we have to get angry
637 ** in case of an orphaned RLE code).
638 */
639 INBYTE(in_byte);
640
641 if (in_byte == RUNCHAR) {
642 INBYTE(in_repeat);
643 if (in_repeat != 0) {
644 /* Note Error, not Incomplete (which is at the end
645 ** of the string only). This is a programmer error.
646 */
647 PyErr_SetString(Error, "Orphaned RLE code at start");
648 Py_DECREF(rv);
649 return NULL;
650 }
651 OUTBYTE(RUNCHAR);
652 } else {
653 OUTBYTE(in_byte);
654 }
655
656 while( in_len > 0 ) {
657 INBYTE(in_byte);
658
659 if (in_byte == RUNCHAR) {
660 INBYTE(in_repeat);
661 if ( in_repeat == 0 ) {
662 /* Just an escaped RUNCHAR value */
663 OUTBYTE(RUNCHAR);
664 } else {
665 /* Pick up value and output a sequence of it */
666 in_byte = out_data[-1];
667 while ( --in_repeat > 0 )
668 OUTBYTE(in_byte);
669 }
670 } else {
671 /* Normal byte */
672 OUTBYTE(in_byte);
673 }
674 }
675 _PyString_Resize(&rv, (out_data - (unsigned char *)PyString_AsString(rv)));
676 return rv;
677}
678
679static char doc_crc_hqx[] = "(data, oldcrc) -> newcrc. Compute hqx CRC incrementally";
680
681static PyObject *
682binascii_crc_hqx(self, args)
683 PyObject *self;
684 PyObject *args;
685{
686 unsigned char *bin_data;
687 unsigned int crc;
688 int len;
689
690 if ( !PyArg_ParseTuple(args, "s#i", &bin_data, &len, &crc) )
691 return NULL;
692
693 while(len--) {
694 crc=((crc<<8)&0xff00)^crctab_hqx[((crc>>8)&0xff)^*bin_data++];
695 }
696
697 return Py_BuildValue("i", crc);
698}
699
700/* List of functions defined in the module */
701
702static struct PyMethodDef binascii_module_methods[] = {
703 {"a2b_uu", binascii_a2b_uu, 1, doc_a2b_uu},
704 {"b2a_uu", binascii_b2a_uu, 1, doc_b2a_uu},
Jack Jansen84bbc2e1995-10-04 16:38:44 +0000705 {"a2b_base64", binascii_a2b_base64, 1,
706 doc_a2b_base64},
707 {"b2a_base64", binascii_b2a_base64, 1,
708 doc_b2a_base64},
Jack Jansen72781191995-08-07 14:34:15 +0000709 {"a2b_hqx", binascii_a2b_hqx, 1, doc_a2b_hqx},
710 {"b2a_hqx", binascii_b2a_hqx, 1, doc_b2a_hqx},
711 {"rlecode_hqx", binascii_rlecode_hqx, 1,
712 doc_rlecode_hqx},
713 {"rledecode_hqx", binascii_rledecode_hqx, 1,
714 doc_rledecode_hqx},
715 {"crc_hqx", binascii_crc_hqx, 1, doc_crc_hqx},
716 {NULL, NULL} /* sentinel */
717};
718
719
720/* Initialization function for the module (*must* be called initbinascii) */
721static char doc_binascii[] = "Conversion between binary data and ASCII";
722
723void
724initbinascii()
725{
726 PyObject *m, *d, *x;
727
728 /* Create the module and add the functions */
729 m = Py_InitModule("binascii", binascii_module_methods);
730
731 d = PyModule_GetDict(m);
732 x = PyString_FromString(doc_binascii);
733 PyDict_SetItemString(d, "__doc__", x);
734
735 Error = PyString_FromString("binascii.Error");
736 PyDict_SetItemString(d, "Error", Error);
737 Incomplete = PyString_FromString("binascii.Incomplete");
738 PyDict_SetItemString(d, "Incomplete", Incomplete);
739
740 /* Check for errors */
741 if (PyErr_Occurred())
742 Py_FatalError("can't initialize module binascii");
743}