aboutsummaryrefslogtreecommitdiffstats
path: root/mime64/mime64.c
diff options
context:
space:
mode:
authorRob Funk <rfunk@funknet.net>2004-06-08 03:59:01 +0000
committerRob Funk <rfunk@funknet.net>2004-06-08 03:59:01 +0000
commitd78b61e3efaea197a6e5b2b72bf2981a9ed69461 (patch)
tree1704e13ce5d767d59868a2d5e834cb2e988ed90f /mime64/mime64.c
parentd9e84e176fe538e110d9612f9832d69846e8d3e7 (diff)
downloadfetchmail-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.c795
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 );
+}