home *** CD-ROM | disk | FTP | other *** search
- Path: sparky!uunet!ukma!asuvax!chnews!sedona!bhoughto
- From: bhoughto@sedona.intel.com (Blair P. Houghton)
- Newsgroups: comp.mail.mime
- Subject: Re: X.400 and multimedia mail
- Date: 13 Dec 1992 19:27:15 GMT
- Organization: Intel Corp., Chandler, Arizona
- Lines: 248
- Message-ID: <1gg2qjINN2df@chnews.intel.com>
- References: <1galsqINNr88@gap.caltech.edu> <Bz6H65.EnH@zoo.toronto.edu> <1gfg5uINN5ej@calvin.NYU.EDU>
- NNTP-Posting-Host: alfalfa.intel.com
-
- In article <1gfg5uINN5ej@calvin.NYU.EDU> roy@mchip00.med.nyu.edu (Roy Smith) writes:
- >henry@zoo.toronto.edu (Henry Spencer) writes:
- >> And uuencode is essentially identical to base64 except that it's not as
- >> good, due to some fundamental design mistakes; in particular, it isn't any
- >> more compact.
- >
- > What ever happened to btoa? It came out a bunch of years ago, but
- >never seemed to catch on. As I remember, it was touted as a replacement for
- >uuencode with the advantage that it only incurred a 5/4ths expansion instead
- >of 4/3rds. Was there some reason why MIME didn't use btoa?
-
- Portability of the character representation.
-
- RFC 1341 explicitly cites a desire to use only characters
- which appear in all[*] extant literal standards. The set
- [A-Za-z0-9+/] (the brackets aren't included) appears just
- about everywhere. You could probably add [-,.=] to
- that[**], but you don't need more than 64 for a 6-bit
- code.
-
- By the way, in case anyone wants it, I've enclosed some
- simple base64 stuff below, as an example of the ascii
- implementation on a machine with 8-bit bytes. It doesn't
- ignore newlines in the ascii, yet, but it doesn't create
- them, either.
-
- --Blair
- "Boy, are we gonna get mail..."
- -D. Letterman
-
-
- [*] almost all? I don't remember any exceptions.
- [**] '=', of course, _is_ included, as the padding character.
-
-
- --
- /* base64.c -- routines to convert to and from base64 encoding */
- /* (C) 1992 Blair P. Houghton; All Rights Reserved */
-
- #include <stdio.h>
- #include <stddef.h>
- #include <errno.h>
-
- char base64_to_ascii[] = {
- 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', /* 00-07 */
- 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', /* 08-0f */
- 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', /* 10-17 */
- 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', /* 18-1f */
- 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', /* 20-27 */
- 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', /* 28-2f */
- 'w', 'x', 'y', 'z', '0', '1', '2', '3', /* 30-37 */
- '4', '5', '6', '7', '8', '9', '+', '/' /* 38-3f */
- };
-
- #define PAD '='
-
-
- char ascii_to_base64[] = {
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 62, 0, 0, 0, 63,
- 52, 53, 54, 55, 56, 57, 58, 59,
- 60, 61, 0, 0, 0,/**/0, 0, 0, /* comment at '=' */
- 0, 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, 0, 0, 0, 0, 0,
- 0, 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, 0, 0, 0, 0, 0
- };
-
-
- static char s1, s2, s3, s4;
-
- void binary_to_ascii_base64( char *s, const char *t )
- {
- /*
- * using `*t++' here instead of the array notation
- * is an invitation to undefined-order-of-evaluation bugs
- */
- s1 = (t[0] & 0xfc)>>2;
- s2 = (t[0] & 0x03)<<4 | (t[1]&0xf0)>>4;
- s3 = (t[1] & 0x0f)<<2 | (t[2]&0xc0)>>6;
- s4 = t[2] & 0x3f;
-
- *s++ = (char)base64_to_ascii[ s1 ];
- *s++ = (char)base64_to_ascii[ s2 ];
- *s++ = (char)base64_to_ascii[ s3 ];
- *s = (char)base64_to_ascii[ s4 ];
- }
-
- void ascii_base64_to_binary( const char *s, char *t )
- {
- s1 = ascii_to_base64[ *s++ ];
- s2 = ascii_to_base64[ *s++ ];
- s3 = ascii_to_base64[ *s++ ];
- s4 = ascii_to_base64[ *s ];
-
- *t++ = s1<<2 | (s2&0x30)>>4;
- *t++ = (s2&0x0f)<<4 | (s3&0x3c)>>2;
- *t = (s3&0x03)<<6 | s4;
- }
-
-
- char *convert_to_binary( const char *s, size_t n_s, size_t *n_t )
- {
- static char sx[4], tx[4], *t, *t_start;
- static unsigned spares, n_loop, n;
-
- spares = (s[n_s - 1] == PAD) + (s[n_s - 2] == PAD); /* adding logicals */
-
- n_loop = (spares ? (n_s - 4) : n_s) / 4; /* # of whole groups */
-
- *n_t = 3 * n_loop + (spares ? (3 - spares) : 0);
-
- if ( *n_t == 0 )
- return NULL;
-
- errno = 0;
- t = t_start = (char *) malloc( *n_t );
- if ( !t ) {
- perror( "convert_to_binary(): allocating binary array" );
- exit( 1 );
- }
-
- while ( n_loop-- ) {
- ascii_base64_to_binary(s,t);
- s += 4;
- t += 3;
- }
-
- /* last quartet */
- if ( spares ) {
- /* one or two PAD characters were found */
- sx[0] = sx[1] = sx[2] = sx[3] = 0;
- tx[0] = tx[1] = tx[2] = 0;
- for( n = 0; n < spares; n++ )
- sx[n] = s[n];
- ascii_base64_to_binary(sx,tx);
- *t = tx[0]; /* ...X; two PAD chars --> one bin */
- if ( spares == 1 )
- *++t = tx[1]; /* ...XX; one PAD --> two extra bins */
- }
-
- return t_start;
- }
-
-
- char *convert_to_ascii_base_64( const char *t, size_t n_t, size_t *n_s )
- {
- static char tx[4], *s, *s_start;
- static unsigned spares, n_loop, n;
-
- switch( n_t % 3 ) {
- case 1:
- spares = 2;
- break;
- case 2:
- spares = 1;
- break;
- case 0:
- spares = 0;
- break;
- }
-
- n_loop = (spares ? (n_t - (3-spares)) : n_t) / 3; /* # of whole groups */
-
- *n_s = 4 * (n_loop + (spares != 0)); /* adding logicals */
-
- if ( *n_s < 4 )
- return NULL;
-
- errno = 0;
- s = s_start = (char *) malloc( *n_s );
- if ( !s ) {
- perror( "convert_to_ascii_base_64(): allocating ascii array" );
- exit( 1 );
- }
-
- while ( n_loop-- ) {
- binary_to_ascii_base64(s,t);
- s += 4;
- t += 3;
- }
-
- if ( spares ) {
- /* one or two PAD characters are needed */
- tx[0] = tx[1] = tx[2] = 0;
- for( n = 0; n < spares; n++ )
- tx[n] = t[n];
- binary_to_ascii_base64(s,tx);
- s[3] = PAD; /* "....XXX=" */
- if ( spares == 2 )
- s[2] = PAD; /* "....XX==" */
- }
-
- return s_start;
- }
-
- #ifdef BASE64MAIN
-
- #include "/eng/eng21/bhoughto/include/slurp.h"
-
- int main( void )
- {
- char u[4] = { 'a', 'r', '8', 'N' };
- char t[] = { 0xfa, 0xeb, 0xdc, 0xcd };
- char *s, *r;
- size_t n_u, n_t, n_s, n_r, i;
-
- n_u = 4;
- for ( i = 0; i < n_u; i++ )
- printf( "%c ", base64_to_ascii[ ascii_to_base64[ u[i] ] ] );
- printf( "(%d bytes)\n", n_u );
-
- n_t = sizeof(t);
- printf( "%x %x %x %x (%d bytes)\n", t[0], t[1], t[2], t[3], n_t );
-
- s = convert_to_ascii_base_64( t, n_t, &n_s );
-
- for ( i = 0; i < n_s; i++ )
- printf( "%x ", ascii_to_base64[ s[i] ] );
- printf( "\n\"%s\" (%d chars)\n", s, n_s );
-
- r = convert_to_binary( s, n_s, &n_r );
-
- for ( i = 0; i < n_r; i++ )
- printf( "%x ", r[i] );
- printf( "(%d bytes)\n", n_r );
-
- s = slurp( "/tmp/foo" );
-
- n_s = strlen( s ) + 1;
-
- r = convert_to_ascii_base_64( s, n_s, &n_r );
-
- fputs( r, stdout );
-
- fputs( convert_to_binary( r, n_r, &n_s ) , stdout);
- }
-
- #endif
-
-