home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 18 REXX / 18-REXX.zip / rxendeco.zip / QUOTE.C < prev    next >
C/C++ Source or Header  |  2001-07-15  |  6KB  |  202 lines

  1. /* +------------------------------------------------------------------------+
  2.    |  Quoted-Printable encode/decode.    2001-07-14    Dave Lewis           |
  3.    +------------------------------------------------------------------------+ */
  4.  
  5. #pragma strings(readonly)
  6.  
  7. #include <stdlib.h>
  8. #include <stdio.h>
  9. #include <memory.h>
  10. #include <string.h>
  11. #include <ctype.h>
  12.  
  13. /*-----------------------------------------------------------------------------
  14.  
  15.    See RFC 1521 Section "5.1.  Quoted-Printable Content-Transfer-Encoding"
  16.  
  17.    This program assumes that the text being passed in is has already been
  18.    converted to canonical form. i.e. hard line breaks are CRLF sequences.
  19.  
  20. -----------------------------------------------------------------------------*/
  21.  
  22. static unsigned char AllwaysEncode[256] =
  23. {
  24. /* 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F        */
  25.    1,  1,  1,  1,  1,  1,  1,  1,  1,  0,  0,  1,  1,  0,  1,  1,  /* 0 */
  26.    1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  /* 1 */
  27.    0,  1,  1,  1,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  /* 2 */
  28.    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  0,  /* 3 */
  29.    1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  /* 4 */
  30.    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  0,  /* 5 */
  31.    1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  /* 6 */
  32.    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  1,  1,  1,  /* 7 */
  33.    1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  /* 8 */
  34.    1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  /* 9 */
  35.    1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  /* A */
  36.    1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  /* B */
  37.    1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  /* C */
  38.    1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  /* D */
  39.    1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  /* E */
  40.    1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1   /* F */
  41. };
  42.  
  43. /*-----------------------------------------------------------------------------
  44.  
  45. -----------------------------------------------------------------------------*/
  46.  
  47. void utHexToBin ( unsigned char *target, unsigned char *source, int length );
  48.  
  49. /*-----------------------------------------------------------------------------
  50.  
  51.   Convert 8bit character array to quoted-printable
  52.  
  53. -----------------------------------------------------------------------------*/
  54.  
  55. int utTxtToQuoted ( unsigned char **trget, unsigned char *source, int length )
  56. {
  57.   int allocated = length * 3;
  58.   int retlen    = 0;
  59.   int newline   = 1;
  60.   int curlen    = 0;
  61.   unsigned char *target = malloc( allocated );
  62.  
  63.   while ( length-- )
  64.   {
  65.     int encode = 0;
  66.  
  67.     if ( retlen + 8 > allocated )
  68.       target = realloc( target, allocated += 256 );
  69.  
  70.     if ( newline )       /* These are problem strings */
  71.     {
  72.       if ( length >= 4 && !memicmp( source, "From ", 5 ) ||
  73.            length >= 2 && !memcmp ( source, ".\r\n", 3 ) ||
  74.            *source == '\n'                                )
  75.         encode = 1;
  76.  
  77.       newline = 0;
  78.     }
  79.  
  80.     if ( !encode && length >= 2 && source[1] == '\r' && source[2] == '\n' )
  81.       if ( *source == ' ' || *source == '\t' ) encode = 1; /* Trailing space */
  82.  
  83.     if ( !encode && *source == '\r' && source[1] != '\n' ) encode = 1;
  84.     if ( !encode && *source == '\n' )
  85.        if ( source[-1] != '\r' ) encode  = 1;
  86.        else                      newline = 1;
  87.  
  88.     if ( encode || AllwaysEncode[ *source ] )
  89.     {
  90.       sprintf ( &target[retlen], "=%2.2X", *source );
  91.       curlen += 3;
  92.       retlen += 3;
  93.     }
  94.     else
  95.     {
  96.       target[retlen] = *source;
  97.       curlen++;
  98.       retlen++;
  99.     }
  100.  
  101.     source++;
  102.  
  103.     if ( newline ) curlen  = 0;
  104.     else if ( curlen >= 70 && length > 1 )
  105.     {
  106.       if ( !encode           && source[0] == '\n' ) continue;
  107.       if ( source[0] == '\r' && source[1] == '\n' ) continue;
  108.       if ( source[1] == '\r' && source[2] == '\n' ) continue;
  109.  
  110.       memcpy( &target[retlen], "=\r\n", 3 );   /* Soft Break */
  111.  
  112.       retlen += 3;
  113.       curlen  = 0;
  114.       newline = 1;
  115.     }
  116.   }
  117.  
  118.   *trget = target;
  119.  
  120.   return ( retlen );
  121. }
  122.  
  123. /*-----------------------------------------------------------------------------
  124.  
  125.   Convert quoted-printable to 8bit character array
  126.  
  127. -----------------------------------------------------------------------------*/
  128.  
  129. int utQuotedToTxt ( unsigned char *target, unsigned char *source, int length )
  130. {
  131.   int retlen = 0;
  132.   unsigned char *cp, *np;
  133.  
  134.   cp = source;
  135.  
  136.   while ( length > 0 )
  137.   {
  138.     if ( length >= 3 && ( np = memchr( cp, '=', length - 3 ) ) != NULL )
  139.     {
  140.       int fraction = np - cp;
  141.  
  142.       if ( fraction )
  143.       {
  144.         memmove( target, cp, fraction );
  145.         target += fraction;
  146.         retlen += fraction;
  147.         length -= fraction;
  148.       }
  149.  
  150.       if ( np[1] != '\r' && np[2] != '\n' )
  151.       {
  152.         utHexToBin ( target++, np + 1, 2 );
  153.         retlen++;
  154.       }
  155.  
  156.       length -= 3;
  157.       cp = np + 3;
  158.     }
  159.     else
  160.     {
  161.       if ( target != cp ) memmove( target, cp, length );
  162.       retlen += length;
  163.       break;
  164.     }
  165.   }
  166.  
  167.   return ( retlen );
  168. }
  169.  
  170. /*-----------------------------------------------------------------------
  171.     utHexToAsc
  172. -----------------
  173.  
  174.     Convert every 2 HEX bytes to 1 binary piece of data
  175.  
  176. -----------------------------------------------------------------------*/
  177.  
  178. void utHexToBin ( unsigned char *target, unsigned char *source, int length )
  179. {
  180.   static unsigned char hexDigits[] = "0123456789ABCDEF";
  181.   unsigned char workval;
  182.   int           nibble;
  183.  
  184.   if ( length & 1 ) length++;
  185.  
  186.   memset ( target, 0, length >> 1 );
  187.  
  188.   for ( nibble = 0; nibble < length; nibble++ )
  189.   {
  190.     workval = ( (unsigned char *)memchr( hexDigits, toupper(*source),
  191.                         sizeof( hexDigits ) ) - hexDigits ) & 0x0F;
  192.  
  193.     if ( !(nibble & 1) )  workval <<= 4;
  194.     target[ nibble >> 1 ] |= workval;
  195.  
  196.     if ( !*(++source) ) break;
  197.   }
  198.  
  199.   return;
  200. }
  201.  
  202.