/* MODULE HTUU.c ** UUENCODE AND UUDECODE ** ** ACKNOWLEDGEMENT: ** This code is taken from rpem distribution, and was originally ** written by Mark Riordan. ** ** AUTHORS: ** MR Mark Riordan riordanmr@clvax1.cl.msu.edu ** AL Ari Luotonen luotonen@dxcern.cern.ch ** ** HISTORY: ** Added as part of the WWW library and edited to conform ** with the WWW project coding standards by: AL 5 Aug 1993 ** Originally written by: MR 12 Aug 1990 ** Original header text: ** ------------------------------------------------------------- ** File containing routines to convert a buffer ** of bytes to/from RFC 1113 printable encoding format. ** ** This technique is similar to the familiar Unix uuencode ** format in that it maps 6 binary bits to one ASCII ** character (or more aptly, 3 binary bytes to 4 ASCII ** characters). However, RFC 1113 does not use the same ** mapping to printable characters as uuencode. ** ** Mark Riordan 12 August 1990 and 17 Feb 1991. ** This code is hereby placed in the public domain. ** ------------------------------------------------------------- ** ** BUGS: ** ** */ #include "HTUtils.h" #include "HTUU.h" #include "LYLeaks.h" PRIVATE char six2pr[64] = { 'A','B','C','D','E','F','G','H','I','J','K','L','M', 'N','O','P','Q','R','S','T','U','V','W','X','Y','Z', 'a','b','c','d','e','f','g','h','i','j','k','l','m', 'n','o','p','q','r','s','t','u','v','w','x','y','z', '0','1','2','3','4','5','6','7','8','9','+','/' }; PRIVATE unsigned char pr2six[256]; /*--- function HTUU_encode ----------------------------------------------- * * Encode a single line of binary data to a standard format that * uses only printing ASCII characters (but takes up 33% more bytes). * * Entry bufin points to a buffer of bytes. If nbytes is not * a multiple of three, then the byte just beyond * the last byte in the buffer must be 0. * nbytes is the number of bytes in that buffer. * This cannot be more than 48. * bufcoded points to an output buffer. Be sure that this * can hold at least 1 + (4*nbytes)/3 characters. * * Exit bufcoded contains the coded line. The first 4*nbytes/3 bytes * contain printing ASCII characters representing * those binary bytes. This may include one or * two '=' characters used as padding at the end. * The last byte is a zero byte. * Returns the number of ASCII characters in "bufcoded". */ PUBLIC int HTUU_encode ARGS3(unsigned char *, bufin, unsigned int, nbytes, char *, bufcoded) { /* ENC is the basic 1 character encoding function to make a char printing */ #define ENC(c) six2pr[c] register char *outptr = bufcoded; unsigned int i; /* This doesn't seem to be needed (AL): register unsigned char *inptr = bufin; */ for (i=0; i> 2); /* c1 */ *(outptr++) = ENC(((*bufin << 4) & 060) | ((bufin[1] >> 4) & 017)); /*c2*/ *(outptr++) = ENC(((bufin[1] << 2) & 074) | ((bufin[2] >> 6) & 03));/*c3*/ *(outptr++) = ENC(bufin[2] & 077); /* c4 */ bufin += 3; } /* If nbytes was not a multiple of 3, then we have encoded too * many characters. Adjust appropriately. */ if(i == nbytes+1) { /* There were only 2 bytes in that last group */ outptr[-1] = '='; } else if(i == nbytes+2) { /* There was only 1 byte in that last group */ outptr[-1] = '='; outptr[-2] = '='; } *outptr = '\0'; return(outptr - bufcoded); } /*--- function HTUU_decode ------------------------------------------------ * * Decode an ASCII-encoded buffer back to its original binary form. * * Entry bufcoded points to a uuencoded string. It is * terminated by any character not in * the printable character table six2pr, but * leading whitespace is stripped. * bufplain points to the output buffer; must be big * enough to hold the decoded string (generally * shorter than the encoded string) plus * as many as two extra bytes used during * the decoding process. * outbufsize is the maximum number of bytes that * can fit in bufplain. * * Exit Returns the number of binary bytes decoded. * bufplain contains these bytes. */ PUBLIC int HTUU_decode ARGS3(char *, bufcoded, unsigned char *, bufplain, int, outbufsize) { /* single character decode */ #define DEC(c) pr2six[(int)c] #define MAXVAL 63 static int first = 1; int nbytesdecoded, j; register char *bufin = bufcoded; register unsigned char *bufout = bufplain; register int nprbytes; /* If this is the first call, initialize the mapping table. * This code should work even on non-ASCII machines. */ if(first) { first = 0; for(j=0; j<256; j++) pr2six[j] = MAXVAL+1; for(j=0; j<64; j++) pr2six[(unsigned char)six2pr[j]] = (unsigned char)j; #if 0 pr2six['A']= 0; pr2six['B']= 1; pr2six['C']= 2; pr2six['D']= 3; pr2six['E']= 4; pr2six['F']= 5; pr2six['G']= 6; pr2six['H']= 7; pr2six['I']= 8; pr2six['J']= 9; pr2six['K']=10; pr2six['L']=11; pr2six['M']=12; pr2six['N']=13; pr2six['O']=14; pr2six['P']=15; pr2six['Q']=16; pr2six['R']=17; pr2six['S']=18; pr2six['T']=19; pr2six['U']=20; pr2six['V']=21; pr2six['W']=22; pr2six['X']=23; pr2six['Y']=24; pr2six['Z']=25; pr2six['a']=26; pr2six['b']=27; pr2six['c']=28; pr2six['d']=29; pr2six['e']=30; pr2six['f']=31; pr2six['g']=32; pr2six['h']=33; pr2six['i']=34; pr2six['j']=35; pr2six['k']=36; pr2six['l']=37; pr2six['m']=38; pr2six['n']=39; pr2six['o']=40; pr2six['p']=41; pr2six['q']=42; pr2six['r']=43; pr2six['s']=44; pr2six['t']=45; pr2six['u']=46; pr2six['v']=47; pr2six['w']=48; pr2six['x']=49; pr2six['y']=50; pr2six['z']=51; pr2six['0']=52; pr2six['1']=53; pr2six['2']=54; pr2six['3']=55; pr2six['4']=56; pr2six['5']=57; pr2six['6']=58; pr2six['7']=59; pr2six['8']=60; pr2six['9']=61; pr2six['+']=62; pr2six['/']=63; #endif } /* Strip leading whitespace. */ while(*bufcoded==' ' || *bufcoded == '\t') bufcoded++; /* Figure out how many characters are in the input buffer. * If this would decode into more bytes than would fit into * the output buffer, adjust the number of input bytes downwards. */ bufin = bufcoded; while(pr2six[(unsigned char)*(bufin++)] <= MAXVAL); nprbytes = bufin - bufcoded - 1; nbytesdecoded = ((nprbytes+3)/4) * 3; if(nbytesdecoded > outbufsize) { nprbytes = (outbufsize*4)/3; } bufin = bufcoded; while (nprbytes > 0) { *(bufout++) = (unsigned char) (DEC(*bufin) << 2 | DEC(bufin[1]) >> 4); *(bufout++) = (unsigned char) (DEC(bufin[1]) << 4 | DEC(bufin[2]) >> 2); *(bufout++) = (unsigned char) (DEC(bufin[2]) << 6 | DEC(bufin[3])); bufin += 4; nprbytes -= 4; } if(nprbytes & 03) { if(pr2six[(int)bufin[-2]] > MAXVAL) { nbytesdecoded -= 2; } else { nbytesdecoded -= 1; } } return(nbytesdecoded); }