diff options
author | Rob Funk <rfunk@funknet.net> | 2004-06-08 03:59:01 +0000 |
---|---|---|
committer | Rob Funk <rfunk@funknet.net> | 2004-06-08 03:59:01 +0000 |
commit | d78b61e3efaea197a6e5b2b72bf2981a9ed69461 (patch) | |
tree | 1704e13ce5d767d59868a2d5e834cb2e988ed90f /mime64/mime64.c | |
parent | d9e84e176fe538e110d9612f9832d69846e8d3e7 (diff) | |
download | fetchmail-d78b61e3efaea197a6e5b2b72bf2981a9ed69461.tar.gz fetchmail-d78b61e3efaea197a6e5b2b72bf2981a9ed69461.tar.bz2 fetchmail-d78b61e3efaea197a6e5b2b72bf2981a9ed69461.zip |
Add files from ESR's dev directory that weren't under version control
svn path=/trunk/; revision=3881
Diffstat (limited to 'mime64/mime64.c')
-rw-r--r-- | mime64/mime64.c | 795 |
1 files changed, 795 insertions, 0 deletions
diff --git a/mime64/mime64.c b/mime64/mime64.c new file mode 100644 index 00000000..c7ddd3ed --- /dev/null +++ b/mime64/mime64.c @@ -0,0 +1,795 @@ +/* mime64 */ +/* MIME base64 encoder/decoder by Karl Hahn hahn@lds.loral.com 3-Aug-94 */ +/* modified 30-Sep-94 by Karl Hahn hahn@lds.loral.com: handle multiple + content */ +/* modified 12-Jan-95 by Karl Hahn hahn@lds.loral.com: handle file names + that are encased in quotes */ +/* modified 18-Jan-95 by Karl Hahn hahn@lds.loral.com: prevent complete + failure if filename in name field matches name of input file */ +/* modified 19-Jan-95 by Karl Hahn hahn@lds.loral.com: prevent early exit + if last decoded character falls on a multiple of 3 -- would cause error + message and failure to rename output file if rename was necessary */ +/* modified 19-Jan-95 by Karl Hahn hahn@lds.loral.com: prevent complete + failure if a line of text preceding the MIME64 stuff contains no + non-base64 characters */ +/* modified 19-Jan-95 by Karl Hahn hahn@lds.loral.com: fixed command + line parser to prevent missing a name field preceded by another + name field */ +/* modified 19-Jan-95 by Karl Hahn hahn@lds.loral.com: prevent error + message at the end of decoding each section. Terminates output + file now on a blank line as well as the conditions that did so + previously */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#ifdef __FreeBSD__ +#define strcmpi(x,y) strcasecmp(x,y) +#endif + +char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + "0123456789+/"; + +enum TOKENTYPE { NONE, BLANKS, PUNCT, TAG, NAME, CONTENT }; + +struct TOKEN { + char *text; + int length; + int index; + enum TOKENTYPE type; + }; + +int compare_token( struct TOKEN *token, char *text ) +{ + int index=0; + int count; + int result; + char blivit1, blivit2; + + count = token->length; + + if ( count > 0 ) + { + result = 1; + } + else + { + result = 0; + } + + while ( (count > 0) && ( result != 0 ) ) + { + blivit1 = token->text[index++]; + if ( (blivit1 >= 'a' ) && (blivit1 <= 'z') ) + { + blivit1 -= ' '; + } + + blivit2 = *text++; + if ( (blivit2 >= 'a' ) && (blivit2 <= 'z') ) + { + blivit2 -= ' '; + } + + if ( blivit1 != blivit2 ) + { + result = 0; + } + + count--; + } + + return result; +} + +int ispunct( char blivit ) +{ + if ( ( blivit >= 'a' ) && (blivit <= 'z' ) ) + { + blivit -= ' '; + } + + if ( ( ( blivit < '0' ) || + ( ( blivit > '9' ) && (blivit < 'A') ) || + ( blivit > 'Z' ) ) && + ( blivit != '-') && (blivit != '/') && (blivit != '.') ) + { + return 1; + } + else + { + return 0; + } +} + +void fixname( char *name ) +{ + while ( *name != '\0' ) + { + + if (ispunct( *name ) ) + { + *name = '\0'; + } + + name++; + } +} + +void acquire_token( char *line, enum TOKENTYPE type, struct TOKEN *token ) +{ + int doneflag=0, startflag=1; + int index; + enum TOKENTYPE nextstate=NONE; + char blivit; + + if (token->type == NONE) + { + token->index = 0; + token->length = 0; + } + + index = token->index + token->length; + + token->text = 0; + + while ( doneflag == 0 ) + { + blivit = line[index]; + if ( (blivit >= 'a') && (blivit <= 'z') ) + { + blivit -= ' '; + } + + switch (token->type) + { + case NONE: + if ( blivit == ' ') + { + index++; + token->index++; + } + else + { + token->type = TAG; + nextstate = TAG; + } + break; + + case BLANKS: + if ( blivit == ' ') + { + index++; + } + else if ( ispunct( blivit ) ) + { + token->type = PUNCT; + token->index = index; + } + else + { + token->type = nextstate; + token->index = index; + } + break; + + case PUNCT: + if ( blivit < ' ') + { + doneflag = 1; + token->type = NONE; + token->index = index; + token->text = line + index; + token->length = 0; + } + else if ( blivit == ' ' ) + { + token->type = BLANKS; + token->index = index; + if ( line[ token->index ] == ';' ) + { + nextstate = NAME; + } + else if ( line[ token->index ] == '=' ) + { + nextstate = CONTENT; + } + + } + else if ( ispunct( blivit ) ) + { + index++; + } + else + { + if ( line[ token->index ] == ';' ) + { + nextstate = NAME; + } + else if ( line[ token->index ] == '=' ) + { + nextstate = CONTENT; + } + + token->type = nextstate; + token->index = index; + } + break; + + case TAG: + if ( ispunct( blivit ) ) + { + token->length = index - token->index; + token->text = line + token->index; + nextstate = NAME; + + if ( ( ( type == TAG ) || ( type == NONE ) ) && !startflag) + { + doneflag = 1; + } + else if (blivit == ' ') + { + token->type = BLANKS; + token->index = index; + } + else + { + token->type = PUNCT; + token->index = index; + } + } + else + { + index++; + } + break; + + case NAME: + if ( ispunct( blivit ) ) + { + token->length = index - token->index; + token->text = line + token->index; + + if ( blivit != ';' ) + { + nextstate = CONTENT; + } + else + { + nextstate = NAME; + } + + if ( ( ( type == NAME ) || ( type == NONE ) ) && !startflag ) + { + doneflag = 1; + } + else if (blivit == ' ') + { + token->type = BLANKS; + token->index = index; + } + else + { + token->type = PUNCT; + token->index = index; + } + } + else + { + index++; + } + break; + + case CONTENT: + if ( ispunct( blivit ) ) + { + token->length = index - token->index; + token->text = line + token->index; + nextstate = NAME; + + if ( ( ( type == CONTENT ) || ( type == NONE ) ) && !startflag ) + { + doneflag = 1; + } + else if (blivit == ' ') + { + token->type = BLANKS; + token->index = index; + } + else + { + token->type = PUNCT; + token->index = index; + } + } + else + { + index++; + } + break; + } + startflag = 0; + } +} + +void fputch( char blivit, FILE *f ) +{ +/* if (blivit == '\n') fputc( '\r', f );*/ + fputc( blivit, f ); +} + +int classify_args( int narg, + char *rawargs[], char *fileargs[], char *optargs[] ) +{ + int index, jndex, kndex; + char *argptr; + + for ( index = 0, jndex = 0, kndex = 0; index < narg; index++ ) + { + argptr = rawargs[index]; + if (*argptr == '-') + { + argptr++; + optargs[kndex++] = argptr; + } + else + { + fileargs[jndex++] = argptr; + } + } + + return kndex; +} + +int cvt_ascii( unsigned char alpha ) +{ + if ( (alpha >= 'A') && (alpha <= 'Z') ) return (int)(alpha - 'A'); + else if ( (alpha >= 'a') && (alpha <= 'z') ) + return 26 + (int)(alpha - 'a'); + else if ( (alpha >= '0') && (alpha <= '9' ) ) + return 52 + (int)(alpha - '0'); + else if ( alpha == '+' ) return 62; + else if ( alpha == '/' ) return 63; + else if ( alpha == '=' ) return -2; + else return -1; +} + +char *fileargs[64], *optargs[64]; + +struct STATE64 { + unsigned long int accum; + int shift; + }; + + +int main( int nargs, char *cargs[] ) +{ + int n_options, n_files, index, jndex, shift, save_shift; + enum { ENCODE, DECODE } whattodo = DECODE; + int help_flag = 0, replace_flag = 0, perm_replace_flag = 0, quit = 0; + int cycle_flag = 0; + FILE *fin, *fout = NULL, *dummy; + unsigned char blivit; + unsigned long accum, value; + char buf[80], dumname[80]; + char *cptr, *altptr; + int decode_state; + struct TOKEN token; + int firsttime = 1; + int skipflag = 0; + int printmsg = 1; + int outcount = 0; + + n_options = classify_args( nargs, cargs, fileargs, optargs ); + + n_files = nargs - n_options; + + if ( n_files < 2 ) help_flag = 1; + + for ( index = 0; index < n_options; index++ ) + { + if ( ( optargs[index][0] == 'e' ) || + ( optargs[index][0] == 'E' ) ) whattodo = ENCODE; + if ( optargs[index][0] == '?' ) help_flag = 1; + } + + if ( help_flag ) + { + printf( "mime64 infile [outfile] [-option] [-option] etc.\n\n" + "convert between binary and MIME BASE64 format\n\n" + " -e MIME base64 encode (default is decode)\n" + " -? display help message\n\n" + "if no outfile given, output file replaces infile\n" ); + } + + if ( n_files < 2 ) exit(0); + + if ( whattodo == DECODE ) + { + fin = fopen( fileargs[1], "r" ); + } + else + { + fin = fopen( fileargs[1], "rb" ); + } + + if ( fin == 0 ) + { + printf( "%s file not found\n", fileargs[1] ); + exit(-1); + } + + if ( n_files > 2 ) + { + if ( whattodo == DECODE ) + { + sprintf( dumname, "%s", fileargs[2] ); + } + else + { + fout = fopen( fileargs[2], "w" ); + + if ( fout == 0 ) + { + printf( "Couldn't open %s for output\n", fileargs[2] ); + } + } + } + else + { + if ( whattodo == DECODE ) + { + sprintf( dumname, "%s", fileargs[1] ); + } + else + { + fout = fopen( "$$$$$$$$.$$$", "w" ); + } + + replace_flag = 1; + } + + +do { + quit = 0; + printmsg = 1; + + if ( whattodo == DECODE ) + { + shift = 0; + accum = 0; + decode_state = 0; + + while ( ( !feof( fin ) ) && (quit == 0) ) + { + fgets( buf, 80, fin ); + if ( feof( fin ) ) + { + if ( ( dumname[0] != '\0' ) && ( shift != 0 ) ) + { + printf( "Unexpected end of file encountered in %s\n" + "last few bytes may have been lost\n", dumname ); + quit = 1; + decode_state = 1; + continue; + } + else if ( cycle_flag == 0 ) + { + quit = 1; + decode_state = 1; + continue; + } + } + else + { + cycle_flag = 1; + + if ( (decode_state == 1) && + ( (buf[0] == '\n') || (buf[0] < '+') ) ) + { + quit = 1; + + if ( shift != 0 ) + { + printf( "Unexpected end of section in %s\n" + "last few bytes may have been lost\n", dumname ); + } + + continue; + } + } + + + if ( decode_state == 0 ) + { + for ( index = 0; + (buf[index] != '\n') && (buf[index] != '\0') && + (decode_state >= 0); + index++ ) + { + if ( ( (buf[index] >= 'A') && (buf[index] <= 'Z') ) || + ( (buf[index] >= 'a') && (buf[index] <= 'z') ) || + ( (buf[index] >= '0') && (buf[index] <= '9') ) || + (buf[index] == '+') || + (buf[index] == '/') || + (buf[index] == '=') ) + { + decode_state = 1; + } + else + { + decode_state = -2; + } + } + + if ( decode_state <= 0 ) + { + + decode_state = 0; + token.type = NONE; + + acquire_token( buf, TAG, &token ); + if ( compare_token( &token, "Content-Type") ) + { + do + { + acquire_token( buf, NAME, &token ); + if ( compare_token( &token, "name" ) ) + { + acquire_token( buf, CONTENT, &token ); + + if ( ( replace_flag ) || + ( firsttime == 0 ) ) + { + sscanf( token.text, "%s", dumname ); + fixname( dumname ); + + if ( strcmpi( dumname, fileargs[1] ) != 0 ) + { + replace_flag = 0; + } + else + { + if ( perm_replace_flag ) + { + printf( + "More than one output file named %s\n", + dumname ); + + exit(-1); + } + } + } + } + } while ( token.type != NONE ); + } + else if ( compare_token( &token, "Content-transfer-encoding" ) ) + { + skipflag = 1; + + do + { + acquire_token( buf, NAME, &token ); + if ( compare_token( &token, "base64" ) ) + { + skipflag = 0; + } + } while ( token.type != NONE ); + } + continue; + } + else if ( skipflag != 0 ) + { + continue; + } + } + + if ( printmsg ) + { + if ( skipflag ) + { + printf( "Section %s not MIME base64\n", dumname ); + } + else + { + printf( "Creating %s\n", dumname ); + if ( strcmpi( dumname, fileargs[1] ) == 0 ) + { + replace_flag = 1; + } + + if ( replace_flag ) + { + fout = fopen( "$$$$$$$$.$$$", "wb" ); + } + else + { + fout = fopen( dumname, "wb" ); + } + + if ( fout == 0 ) + { + printf( "Couldn't open %s for output\n", dumname ); + } + } + + printmsg = 0; + } + + if ( fout == 0 ) + { + printf( "No filename given for subsequent section\n" ); + exit(-1); + } + + if ( feof(fin) ) + { + quit = 1; + } + + if ( quit != 0 ) + { + buf[0] = '\0'; + } + + for ( index = 0; (buf[index] != '\n') && (buf[index] != '\0'); index++) + { + value = cvt_ascii( buf[index] ); + + if ( value < 64 ) + { + accum <<= 6; + shift += 6; + accum |= value; + if ( shift >= 8 ) + { + shift -= 8; + value = accum >> shift; + blivit = (unsigned char)value & 0xFFl; + fputc( blivit, fout ); + } + } + else + { + quit = 1; + break; + } + } + } + } + else + { + fprintf ( fout, + "Content-Type: text/plain; charset=US-ASCII; name=%s\n" + "Content-transfer-encoding: base64\n\n", fileargs[1] ); + + shift = 0; + accum = 0; + index = 0; + while ( ( !feof( fin ) ) || (shift != 0) ) + { + if ( ( !feof( fin ) ) && ( quit == 0 ) ) + { + blivit = fgetc( fin ); + + if ( feof( fin ) ) + { + quit = 1; + save_shift = shift; + blivit = 0; + } + } + else + { + quit = 1; + save_shift = shift; + blivit = 0; + } + + if ( (quit == 0) || (shift != 0) ) + { + value = (unsigned long)blivit; + accum <<= 8; + shift += 8; + accum |= value; + } /* ENDIF */ + + while ( shift >= 6 ) + { + shift -= 6; + value = (accum >> shift) & 0x3Fl; + blivit = alphabet[value]; + + buf[index++] = blivit; + if ( index >= 60 ) + { + buf[index] = '\0'; + fprintf( fout, "%s\n", buf ); + index = 0; + } + + if ( quit != 0 ) + { + shift = 0; + } + } + } + + if ( save_shift == 2 ) + { + buf[index++] = '='; + if ( index >= 60 ) + { + buf[index] = '\0'; + fprintf( fout, "%s\n", buf ); + index = 0; + } + + buf[index++] = '='; + if ( index >= 60 ) + { + buf[index] = '\0'; + fprintf( fout, "%s\n", buf ); + index = 0; + } + } + else if ( save_shift == 4 ) + { + buf[index++] = '='; + if ( index >= 60 ) + { + buf[index] = '\0'; + fprintf( fout, "%s\n", buf ); + index = 0; + } + } + + if ( index != 0 ) + { + buf[index] = '\0'; + fprintf( fout, "%s\n", buf ); + } + } + + if ( fout ) + { + ++outcount; + fclose( fout ); + } + + if ( replace_flag ) + { + perm_replace_flag = 1; + + if ( ( whattodo == DECODE ) && ( decode_state <= 0 ) && ( outcount == 0 ) ) + { + remove( "$$$$$$$$.$$$" ); + printf( "No MIME base64 lines found in %s\n", fileargs[1] ); + } + } + else + { + if ( ( whattodo == DECODE ) && ( decode_state <= 0 ) && ( outcount == 0 ) ) + { + remove( fileargs[2] ); + printf( "No MIME base64 lines found in %s\n", fileargs[1] ); + } + } + + fout = 0; + firsttime = 0; + dumname[0] = '\0'; + cycle_flag = 0; + +} while ( !feof( fin ) ); + + +if ( perm_replace_flag ) +{ + remove( fileargs[1] ); + rename( "$$$$$$$$.$$$", fileargs[1] ); +} + +fclose( fin ); +} |