home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / mime64.zip / mime64.c < prev    next >
Text File  |  1994-11-05  |  17KB  |  696 lines

  1. /* mime64 */
  2. /* MIME base64 encoder/decoder by Karl Hahn  hahn@lds.loral.com  3-Aug-94 */
  3. /* modified 30-Sep-94 by Karl Hahn hahn@lds.loral.com: handle multiple
  4.    content */
  5. #include <stdio.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8.  
  9. char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
  10.                   "0123456789+/";
  11.  
  12. enum TOKENTYPE { NONE, BLANKS, PUNCT, TAG, NAME, CONTENT };
  13.  
  14. struct TOKEN {
  15.                 char *text;
  16.                 int  length;
  17.                 int  index;
  18.                 enum TOKENTYPE type;
  19.              };
  20.  
  21. int compare_token( struct TOKEN *token, char *text )
  22. {
  23.    int index=0;
  24.    int count;
  25.    int result;
  26.    char blivit1, blivit2;
  27.  
  28.    count = token->length;
  29.  
  30.    if ( count > 0 )
  31.    {
  32.       result = 1;
  33.    }
  34.    else
  35.    {
  36.       result = 0;
  37.    }
  38.  
  39.    while ( (count > 0) && ( result != 0 ) )
  40.    {
  41.       blivit1 = token->text[index++];
  42.       if ( (blivit1 >= 'a' ) && (blivit1 <= 'z') )
  43.       {
  44.          blivit1 -= ' ';
  45.       }
  46.  
  47.       blivit2 = *text++;
  48.       if ( (blivit2 >= 'a' ) && (blivit2 <= 'z') )
  49.       {
  50.          blivit2 -= ' ';
  51.       }
  52.  
  53.       if ( blivit1 != blivit2 )
  54.       {
  55.          result = 0;
  56.       }
  57.  
  58.       count--;
  59.    }
  60.  
  61.    return result;
  62. }
  63.  
  64. int ispunct( char blivit )
  65. {
  66.    if ( ( ( blivit < '0' ) ||
  67.           ( ( blivit > '9' ) && (blivit < 'A') ) ||
  68.           ( blivit > 'Z' ) ) &&
  69.         ( blivit != '-') && (blivit != '/') && (blivit != '.') )
  70.    {
  71.       return 1;
  72.    }
  73.    else
  74.    {
  75.       return 0;
  76.    }
  77. }
  78.  
  79. void acquire_token( char *line, enum TOKENTYPE type, struct TOKEN *token )
  80. {
  81.    int doneflag=0, startflag=1;
  82.    int index;
  83.    enum TOKENTYPE nextstate=NONE;
  84.    char blivit;
  85.  
  86.    if (token->type == NONE)
  87.    {
  88.       token->index = 0;
  89.       token->length = 0;
  90.    }
  91.  
  92.    index = token->index + token->length;
  93.  
  94.    token->text = 0;
  95.  
  96.    while ( doneflag == 0 )
  97.    {
  98.       blivit = line[index];
  99.       if ( (blivit >= 'a') && (blivit <= 'z') )
  100.       {
  101.          blivit -= ' ';
  102.       }
  103.  
  104.       switch (token->type)
  105.       {
  106.          case NONE:
  107.          if ( blivit == ' ')
  108.          {
  109.             index++;
  110.             token->index++;
  111.          }
  112.          else
  113.          {
  114.             token->type = TAG;
  115.             nextstate = TAG;
  116.          }
  117.          break;
  118.  
  119.          case BLANKS:
  120.          if      ( blivit == ' ')
  121.          {
  122.             index++;
  123.          }
  124.          else if ( ispunct( blivit ) )
  125.          {
  126.             token->type = PUNCT;
  127.             token->index = index;
  128.          }
  129.          else
  130.          {
  131.             token->type = nextstate;
  132.             token->index = index;
  133.          }
  134.          break;
  135.  
  136.          case PUNCT:
  137.          if      ( blivit <  ' ')
  138.          {
  139.             doneflag = 1;
  140.             token->type = NONE;
  141.             token->index = index;
  142.             token->text = line + index;
  143.             token->length = 0;
  144.          }
  145.          else if ( blivit == ' ' )
  146.          {
  147.             token->type = BLANKS;
  148.             token->index = index;
  149.             if      ( line[ token->index ] == ';' )
  150.             {
  151.                nextstate = NAME;
  152.             }
  153.             else if ( line[ token->index ] == '=' )
  154.             {
  155.                nextstate = CONTENT;
  156.             }
  157.  
  158.          }
  159.          else if ( ispunct( blivit ) )
  160.          {
  161.             index++;
  162.          }
  163.          else
  164.          {
  165.             if      ( line[ token->index ] == ';' )
  166.             {
  167.                nextstate = NAME;
  168.             }
  169.             else if ( line[ token->index ] == '=' )
  170.             {
  171.                nextstate = CONTENT;
  172.             }
  173.  
  174.             token->type = nextstate;
  175.             token->index = index;
  176.          }
  177.          break;
  178.  
  179.          case TAG:
  180.          if ( ispunct( blivit ) )
  181.          {
  182.             token->length = index - token->index;
  183.             token->text = line + token->index;
  184.             nextstate = NAME;
  185.  
  186.             if ( ( ( type == TAG ) || ( type == NONE ) ) && !startflag)
  187.             {
  188.                doneflag = 1;
  189.             }
  190.             else if (blivit == ' ')
  191.             {
  192.                token->type = BLANKS;
  193.                token->index = index;
  194.             }
  195.             else
  196.             {
  197.                token->type = PUNCT;
  198.                token->index = index;
  199.             }
  200.          }
  201.          else
  202.          {
  203.             index++;
  204.          }
  205.          break;
  206.  
  207.          case NAME:
  208.          if ( ispunct( blivit ) )
  209.          {
  210.             token->length = index - token->index;
  211.             token->text = line + token->index;
  212.             nextstate = CONTENT;
  213.  
  214.             if ( ( ( type == NAME ) || ( type == NONE ) ) && !startflag )
  215.             {
  216.                doneflag = 1;
  217.             }
  218.             else if (blivit == ' ')
  219.             {
  220.                token->type = BLANKS;
  221.                token->index = index;
  222.             }
  223.             else
  224.             {
  225.                token->type = PUNCT;
  226.                token->index = index;
  227.             }
  228.          }
  229.          else
  230.          {
  231.             index++;
  232.          }
  233.          break;
  234.  
  235.          case CONTENT:
  236.          if ( ispunct( blivit ) )
  237.          {
  238.             token->length = index - token->index;
  239.             token->text = line + token->index;
  240.             nextstate = NAME;
  241.  
  242.             if ( ( ( type == CONTENT ) || ( type == NONE ) ) && !startflag )
  243.             {
  244.                doneflag = 1;
  245.             }
  246.             else if (blivit == ' ')
  247.             {
  248.                token->type = BLANKS;
  249.                token->index = index;
  250.             }
  251.             else
  252.             {
  253.                token->type = PUNCT;
  254.                token->index = index;
  255.             }
  256.          }
  257.          else
  258.          {
  259.             index++;
  260.          }
  261.          break;
  262.       }
  263.       startflag = 0;
  264.    }
  265. }
  266.  
  267. void fputch( char blivit, FILE *f )
  268. {
  269. /*   if (blivit == '\n') fputc( '\r', f );*/
  270.    fputc( blivit, f );
  271. }
  272.  
  273. int classify_args( int narg,
  274.                    char *rawargs[], char *fileargs[], char *optargs[] )
  275. {
  276.    int index, jndex, kndex;
  277.    char *argptr;
  278.  
  279.    for ( index = 0, jndex = 0, kndex = 0; index < narg; index++ )
  280.    {
  281.       argptr = rawargs[index];
  282.       if (*argptr == '-')
  283.       {
  284.          argptr++;
  285.          optargs[kndex++] = argptr;
  286.       }
  287.       else
  288.       {
  289.          fileargs[jndex++] = argptr;
  290.       }
  291.    }
  292.  
  293.    return kndex;
  294. }
  295.  
  296. int cvt_ascii( unsigned char alpha )
  297. {
  298.    if      ( (alpha >= 'A') && (alpha <= 'Z') ) return (int)(alpha - 'A');
  299.    else if ( (alpha >= 'a') && (alpha <= 'z') )
  300.         return 26 + (int)(alpha - 'a');
  301.    else if ( (alpha >= '0') && (alpha <= '9' ) )
  302.         return 52 + (int)(alpha - '0');
  303.    else if ( alpha == '+' ) return 62;
  304.    else if ( alpha == '/' ) return 63;
  305.    else if ( alpha == '=' ) return -2;
  306.    else                     return -1;
  307. }
  308.  
  309. char *fileargs[64], *optargs[64];
  310.  
  311. struct STATE64 {
  312.                   unsigned long int accum;
  313.                   int               shift;
  314.                };
  315.  
  316.  
  317. int main( int nargs, char *cargs[] )
  318. {
  319.    int n_options, n_files, index, jndex, shift, save_shift;
  320.    enum { ENCODE, DECODE } whattodo = DECODE;
  321.    int help_flag = 0, replace_flag = 0, quit = 0;
  322.    FILE *fin, *fout, *dummy;
  323.    unsigned char blivit;
  324.    unsigned long accum, value;
  325.    char buf[80], dumname[80];
  326.    char *cptr, *altptr;
  327.    int decode_state;
  328.    struct TOKEN token;
  329.    int firsttime = 1;
  330.    int skipflag = 0;
  331.    int printmsg = 1;
  332.  
  333.    n_options = classify_args( nargs, cargs, fileargs, optargs );
  334.  
  335.    n_files = nargs - n_options;
  336.  
  337.    if ( n_files < 2 ) help_flag = 1;
  338.  
  339.    for ( index = 0; index < n_options; index++ )
  340.    {
  341.       if ( ( optargs[index][0] == 'e' ) ||
  342.            ( optargs[index][0] == 'E' ) ) whattodo = ENCODE;
  343.       if ( optargs[index][0] == '?' ) help_flag = 1;
  344.    }
  345.  
  346.    if ( help_flag )
  347.    {
  348.       printf( "mime64 infile [outfile] [-option] [-option] etc.\n\n"
  349.               "convert between binary and MIME BASE64 format\n\n"
  350.               "        -e       MIME base64 encode (default is decode)\n"
  351.               "        -?       display help message\n\n"
  352.               "if no outfile given, output file replaces infile\n" );
  353.    }
  354.  
  355.    if ( n_files < 2 ) exit(0);
  356.  
  357.    if ( whattodo == DECODE )
  358.    {
  359.       fin = fopen( fileargs[1], "r" );
  360.    }
  361.    else
  362.    {
  363.       fin = fopen( fileargs[1], "rb" );
  364.    }
  365.  
  366.    if ( fin == 0 )
  367.    {
  368.       printf( "%s file not found\n", fileargs[1] );
  369.       exit(-1);
  370.    }
  371.  
  372.    if ( n_files > 2 )
  373.    {
  374.       if ( whattodo == DECODE )
  375.       {
  376.          sprintf( dumname, "%s", fileargs[2] );
  377.       }
  378.       else
  379.       {
  380.          fout = fopen( fileargs[2], "w" );
  381.       }
  382.  
  383.       if ( fout == 0 )
  384.       {
  385.          printf( "Couldn't open %s for output\n", fileargs[2] );
  386.       }
  387.    }
  388.    else
  389.    {
  390.       if ( whattodo == DECODE )
  391.       {
  392.          sprintf( dumname, "%s", fileargs[1] );
  393.       }
  394.       else
  395.       {
  396.          fout = fopen( "$$$$$$$$.$$$", "w" );
  397.       }
  398.  
  399.       replace_flag = 1;
  400.    }
  401.  
  402.  
  403. do {
  404.    quit = 0;
  405.    printmsg = 1;
  406.  
  407.    if ( whattodo == DECODE )
  408.    {
  409.       shift = 0;
  410.       accum = 0;
  411.       decode_state = 0;
  412.  
  413.       while ( ( !feof( fin ) ) && (quit == 0) )
  414.       {
  415.          fgets( buf, 80, fin );
  416.          if ( feof( fin ) )
  417.          {
  418.             if ( dumname[0] != '\0' )
  419.             {
  420.                printf( "Unexpected end of file encountered in %s\n",
  421.                        dumname );
  422.             }
  423.  
  424.             exit(0);
  425.          }
  426.  
  427.          if ( decode_state == 0 )
  428.          {
  429.             for ( index = 0;
  430.                   (buf[index] != '\n') && (buf[index] != '\0') &&
  431.                   (decode_state >= 0);
  432.                   index++ )
  433.             {
  434.                if ( ( (buf[index] >= 'A') && (buf[index] <= 'Z') ) ||
  435.                     ( (buf[index] >= 'a') && (buf[index] <= 'z') ) ||
  436.                     ( (buf[index] >= '0') && (buf[index] <= '9') ) ||
  437.                     (buf[index] == '+') ||
  438.                     (buf[index] == '/') ||
  439.                     (buf[index] == '=') )
  440.                {
  441.                   decode_state = 1;
  442.                }
  443.                else
  444.                {
  445.                   decode_state = -2;
  446.                }
  447.             }
  448.  
  449.             if ( decode_state <= 0 )
  450.             {
  451.                decode_state = 0;
  452.                token.type = NONE;
  453.  
  454.                acquire_token( buf, TAG, &token );
  455.                if      ( compare_token( &token, "Content-Type") )
  456.                {
  457.                   do
  458.                   {
  459.                      acquire_token( buf, NAME, &token );
  460.                      if ( compare_token( &token, "name" ) )
  461.                      {
  462.                         acquire_token( buf, CONTENT, &token );
  463.  
  464.                         if ( ( replace_flag ) ||
  465.                              ( firsttime == 0 ) )
  466.                         {
  467.                            sscanf( token.text, "%s", dumname );
  468.                            replace_flag = 0;
  469.                         }
  470.                      }
  471.                   } while ( token.type != NONE );
  472.                }
  473.                else if ( compare_token( &token, "Content-transfer-encoding" ) )
  474.                {
  475.                   skipflag = 1;
  476.  
  477.                   do
  478.                   {
  479.                      acquire_token( buf, NAME, &token );
  480.                      if ( compare_token( &token, "base64" ) )
  481.                      {
  482.                         skipflag = 0;
  483.                      }
  484.                   } while ( token.type != NONE );
  485.                }
  486.                continue;
  487.             }
  488.             else if ( skipflag != 0 )
  489.             {
  490.                continue;
  491.             }
  492.          }
  493.  
  494.          if ( printmsg )
  495.          {
  496.             if ( skipflag )
  497.             {
  498.                printf( "Section %s not MIME base64\n", dumname );
  499.             }
  500.             else
  501.             {
  502.                printf( "Creating %s\n", dumname );
  503. #ifndef __EMX__
  504.                if ( strcmpi( dumname, fileargs[1] ) == 0 )
  505. #else
  506.                if ( stricmp( dumname, fileargs[1] ) == 0 )
  507. #endif
  508.                {
  509.                   replace_flag = 1;
  510.                }
  511.  
  512.                if ( replace_flag )
  513.                {
  514.                   fout = fopen( "$$$$$$$$.$$$", "wb" );
  515.                }
  516.                else
  517.                {
  518.                   fout = fopen( dumname, "wb" );
  519.                }
  520.  
  521.                if ( fout == 0 )
  522.                {
  523.                   printf( "Couldn't open %s for output\n", dumname );
  524.                }
  525.             }
  526.  
  527.             printmsg = 0;
  528.          }
  529.  
  530.          if ( fout == 0 )
  531.          {
  532.             printf( "No filename given for subsequent section\n" );
  533.             exit(-1);
  534.          }
  535.  
  536.          if ( feof(fin) )
  537.          {
  538.             quit = 1;
  539.          }
  540.  
  541.          if ( quit != 0 )
  542.          {
  543.             buf[0] = '\0';
  544.          }
  545.  
  546.          for ( index = 0; (buf[index] != '\n') && (buf[index] != '\0'); index++)
  547.          {
  548.             value = cvt_ascii( buf[index] );
  549.  
  550.             if ( value < 64 )
  551.             {
  552.                accum <<= 6;
  553.                shift += 6;
  554.                accum |= value;
  555.                if ( shift >= 8 )
  556.                {
  557.                   shift -= 8;
  558.                   value = accum >> shift;
  559.                   blivit = (unsigned char)value & 0xFFl;
  560.                   fputc( blivit, fout );
  561.                }
  562.             }
  563.             else
  564.             {
  565.                quit = 1;
  566.                break;
  567.             }
  568.          }
  569.       }
  570.    }
  571.    else
  572.    {
  573.       fprintf ( fout,
  574.        "Content-Type: text/plain; charset=US-ASCII; name=%s\n"
  575.        "Content-transfer-encoding: base64\n\n", fileargs[1] );
  576.  
  577.       shift = 0;
  578.       accum = 0;
  579.       index = 0;
  580.       while ( ( !feof( fin ) ) || (shift != 0) )
  581.       {
  582.          if ( ( !feof( fin ) ) && ( quit == 0 ) )
  583.          {
  584.             blivit = fgetc( fin );
  585.  
  586.             if ( feof( fin ) )
  587.             {
  588.                quit = 1;
  589.                save_shift = shift;
  590.                blivit = 0;
  591.             }
  592.          }
  593.          else
  594.          {
  595.             quit = 1;
  596.             save_shift = shift;
  597.             blivit = 0;
  598.          }
  599.  
  600.          if ( (quit == 0) || (shift != 0) )
  601.          {
  602.             value = (unsigned long)blivit;
  603.             accum <<= 8;
  604.             shift += 8;
  605.             accum |= value;
  606.          } /* ENDIF */
  607.  
  608.          while ( shift >= 6 )
  609.          {
  610.             shift -= 6;
  611.             value = (accum >> shift) & 0x3Fl;
  612.             blivit = alphabet[value];
  613.  
  614.             buf[index++] = blivit;
  615.             if ( index >= 60 )
  616.             {
  617.                buf[index] = '\0';
  618.                fprintf( fout, "%s\n", buf );
  619.                index = 0;
  620.             }
  621.  
  622.             if ( quit != 0 )
  623.             {
  624.                shift = 0;
  625.             }
  626.          }
  627.       }
  628.  
  629.       if      ( save_shift == 2 )
  630.       {
  631.          buf[index++] = '=';
  632.          if ( index >= 60 )
  633.          {
  634.             buf[index] = '\0';
  635.             fprintf( fout, "%s\n", buf );
  636.             index = 0;
  637.          }
  638.  
  639.          buf[index++] = '=';
  640.          if ( index >= 60 )
  641.          {
  642.             buf[index] = '\0';
  643.             fprintf( fout, "%s\n", buf );
  644.             index = 0;
  645.          }
  646.       }
  647.       else if ( save_shift == 4 )
  648.       {
  649.          buf[index++] = '=';
  650.          if ( index >= 60 )
  651.          {
  652.             buf[index] = '\0';
  653.             fprintf( fout, "%s\n", buf );
  654.             index = 0;
  655.          }
  656.       }
  657.  
  658.       if ( index != 0 )
  659.       {
  660.          buf[index] = '\0';
  661.          fprintf( fout, "%s\n", buf );
  662.       }
  663.    }
  664.  
  665.    fclose( fout );
  666.  
  667.    if ( replace_flag )
  668.    {
  669.       if ( ( whattodo == DECODE ) && ( decode_state <= 0 ) )
  670.       {
  671.          remove( "$$$$$$$$.$$$" );
  672.          printf( "No MIME base64 lines found in %s\n", fileargs[1] );
  673.       }
  674.       else
  675.       {
  676.          remove( fileargs[1] );
  677.          rename( "$$$$$$$$.$$$", fileargs[1] );
  678.       }
  679.    }
  680.    else
  681.    {
  682.       if ( ( whattodo == DECODE ) && ( decode_state <= 0 ) )
  683.       {
  684.          remove( fileargs[2] );
  685.          printf( "No MIME base64 lines found in %s\n", fileargs[1] );
  686.       }
  687.    }
  688.  
  689.    fout = 0;
  690.    firsttime = 0;
  691.    dumname[0] = '\0';
  692. } while ( !feof( fin ) );
  693.  
  694. fclose( fin );
  695. }
  696.