Functions

cbf_codes.c File Reference

#include "cbf_codes.h"
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
Include dependency graph for cbf_codes.c:

Go to the source code of this file.

Functions

int cbf_is_base64digest (const char *encoded_digest)
int cbf_md5digest_to64 (char *encoded_digest, const unsigned char *digest)
int cbf_md5digest (cbf_file *file, size_t size, char *digest)
int cbf_toqp (cbf_file *infile, cbf_file *outfile, size_t size)
int cbf_tobase64 (cbf_file *infile, cbf_file *outfile, size_t size)
int cbf_tobasex (cbf_file *infile, cbf_file *outfile, size_t size, size_t elsize, unsigned int base)
int cbf_fromqp (cbf_file *infile, cbf_file *outfile, size_t size, size_t *readsize, char *digest)
int cbf_frombase64 (cbf_file *infile, cbf_file *outfile, size_t size, size_t *readsize, char *digest)
int cbf_frombasex (cbf_file *infile, cbf_file *outfile, size_t size, size_t *readsize, char *digest)

Function Documentation

int cbf_frombase64 ( cbf_file infile,
cbf_file outfile,
size_t  size,
size_t *  readsize,
char *  digest 
)

Definition at line 786 of file cbf_codes.c.

References cbf_failnez, CBF_FILEREAD, cbf_flush_characters(), cbf_md5digest_to64(), cbf_put_character(), cbf_read_character(), cbf_compress_nodestruct::count, MD5Final(), MD5Init(), and MD5Update().

Referenced by cbf_lex(), and cbf_read_mime().

{
  static int decode_64 [256] = {
  
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 
    52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, 64, -1, -1, 
    -1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 
    15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, 
    -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 
    41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, 
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 
    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
    
    };

  MD5_CTX context;
  
  unsigned char buffer [64], rawdigest [17];
    
  int c [4], d [3], bufsize;
  
  int read, write;
    
  size_t count;


    /* Initialise the MD5 context */
    
  if (digest)

    MD5Init (&context);


  count = 0;

  bufsize = 0;
  
  while (count < size)
  {
      /* Read 4 characters */
      
    for (read = 0; read < 4; read++)
    
      do
      {
        c [read] = cbf_read_character (infile);
        
        if (c [read] == EOF)
        
          return CBF_FILEREAD;
      }
      while (decode_64 [c [read] & 0x0ff] < 0);


      /* End of data? */
      
    if (c [0] == '=' || c [1] == '=')
    
      break;


      /* Valid combinations: xxxx xxx= xx== */
      
    c [0] = decode_64 [c [0] & 0x0ff];
    c [1] = decode_64 [c [1] & 0x0ff];
    c [2] = decode_64 [c [2] & 0x0ff];
    c [3] = decode_64 [c [3] & 0x0ff];

    d [0] = ((c [0] << 2) & 0x0fc) | ((c [1] >> 4) & 0x003);
    d [1] = ((c [1] << 4) & 0x0f0) | ((c [2] >> 2) & 0x00f);
    d [2] = ((c [2] << 6) & 0x0c0) | ((c [3]     ) & 0x03f);
    
    if (c [2] == 64)
    
      read = 1;
      
    else
    
      if (c [3] == 64)
      
        read = 2;
        
      else
      
        read = 3;
        
        
      /* Save the data */
      
    for (write = 0; write < read; write++)
    {
      if (outfile)

        cbf_failnez (cbf_put_character (outfile, d [write]))

      if (digest)
      {
        buffer [bufsize] = (unsigned char) d [write];
      
        bufsize++;

        if (bufsize > 63)
        {
          MD5Update (&context, buffer, 64);

          bufsize = 0;
        }
      }
    }

    count += read;
  }


    /* Get the digest */

  if (digest)
  {
    if (bufsize)

      MD5Update (&context, buffer, bufsize);

    MD5Final (rawdigest, &context);

    cbf_md5digest_to64 (digest, rawdigest);
  }


    /* Flush the buffer */

  if (outfile)
  
    cbf_failnez (cbf_flush_characters (outfile))


    /* Save the number of characters read */
    
  if (readsize)
  
    *readsize = count;
    
    
    /* Success */
    
  return 0;
}
int cbf_frombasex ( cbf_file infile,
cbf_file outfile,
size_t  size,
size_t *  readsize,
char *  digest 
)

Definition at line 946 of file cbf_codes.c.

References cbf_failnez, CBF_FILEREAD, cbf_flush_characters(), CBF_FORMAT, cbf_md5digest_to64(), cbf_put_character(), cbf_read_character(), cbf_file::column, cbf_compress_nodestruct::count, MD5Final(), MD5Init(), and MD5Update().

Referenced by cbf_lex(), and cbf_read_mime().

{
  MD5_CTX context;
  
  unsigned char buffer [64], rawdigest [17];

  int c, bufsize;
  
  char val [80], *end;
 
  int read, write, base, direction, elsize, valcount, padding;
    
  size_t count;

  unsigned long l;


    /* Defaults */
    
  base = 10;
  
  direction = 1;
  
  elsize = 4;

  count = 0;
  
  valcount = 0;
  
  padding = 0;
  
  bufsize = 0;


    /* Initialise the MD5 context */

  if (digest)

    MD5Init (&context);


  while (count < size)
  {
      /* Read the (first) character */
      
    c = cbf_read_character (infile);
    
    if (c == EOF)
    
      return CBF_FILEREAD;
      
      
      /* Interpret it */
      
    if (c == '>')
    {
      direction = 1;
      
      c = ' ';
    }
    else
        
      if (c == '<')
      {
        direction = -1;
        
        c = ' ';
      }
      else
      
        if (c == '#')
        {
            /* Comment */
            
          do
            
            c = cbf_read_character (infile);
            
          while (c != EOF && c != '\n');
          
          if (c == EOF)
          
            return CBF_FORMAT;
        }

    switch (infile->column)
    {
      case 1:

        if (c == 'O' || c == 'o')
              
          base = 8;

        else

          if (c == 'D' || c == 'd')

            base = 10;

          else

            if (c == 'H' || c == 'h')

              base = 16;

            else

              return CBF_FORMAT;
              
        break;

      case 2:
            
        if (isdigit (c) && c != '0')
        
          elsize = c - '0';
          
      case 3:

        break;

      default:
      
        if (!isspace (c))
        
          if (c == '=')
          
            padding++;
            
          else
          {
              /* Save the character */
             
            if (valcount > 78)
          
              return CBF_FORMAT;
            
            val [valcount] = c;
          
            valcount++;
          }
        else
        
          if (valcount)
          {
              /* Convert the number */
            
            val [valcount] = '\0';
          
            l = strtoul (val, &end, base);
        
            if (end != &val [valcount])
        
              return CBF_FORMAT;
        
      
              /* Save the binary data */
              
            if ((padding % 2) || padding > 6)
            
              return CBF_FORMAT;
              
            read = elsize - padding / 2;
        
            for (write = 0; write < read; write++)
            {
              if (direction < 0)
              
                c = (unsigned char) ((l >> ((read - write - 1) * 8)) & 0x0ff);

              else

                c = (unsigned char) ((l >> (write * 8)) & 0x0ff);

              if (outfile)
              
                cbf_failnez (cbf_put_character (outfile, c))

              if (digest)
              {
                buffer [bufsize] = (unsigned char) c;
      
                bufsize++;

                if (bufsize > 63)
                {
                  MD5Update (&context, buffer, 64);

                  bufsize = 0;
                }
              }
            }
         
            count += read;
            
            valcount = 0;
            
            padding = 0;
          }
    }
  }


    /* Get the digest */

  if (digest)
  {
    if (bufsize)

      MD5Update (&context, buffer, bufsize);

    MD5Final (rawdigest, &context);

    cbf_md5digest_to64 (digest, rawdigest);
  }


    /* Flush the buffer */

  if (outfile)
  
    cbf_failnez (cbf_flush_characters (outfile))


    /* Save the number of characters read */
    
  if (readsize)
  
    *readsize = count;
    
    
    /* Success */
    
  return 0;
}  
int cbf_fromqp ( cbf_file infile,
cbf_file outfile,
size_t  size,
size_t *  readsize,
char *  digest 
)

Definition at line 649 of file cbf_codes.c.

References cbf_failnez, CBF_FILEREAD, cbf_flush_characters(), CBF_FORMAT, cbf_md5digest_to64(), cbf_put_character(), cbf_read_character(), cbf_compress_nodestruct::count, MD5Final(), MD5Init(), and MD5Update().

Referenced by cbf_lex(), and cbf_read_mime().

{
  MD5_CTX context;
  
  unsigned char buffer [64], rawdigest [17];

  int c, bufsize;
  
  char val [3], *end;
    
  size_t count;


    /* Initialise the MD5 context */
    
  if (digest)

    MD5Init (&context);


  bufsize = 0;    
  
  count = 0;
    
  val [2] = '\0';

  while (count < size)
  {
      /* Read the (first) character */
      
    c = cbf_read_character (infile);
    
    if (c == EOF)
    
      return CBF_FILEREAD;
      
      
      /* Decode it */
      
    if (c == '=')
    {
        /* Get the second character */
        
      c = cbf_read_character (infile);
      
      if (c == EOF)
      
        return CBF_FILEREAD;
        
      if (c != '\n')
      {
          /* Get the third character */
        
        val [0] = c;

        c = cbf_read_character (infile);

        if (c == EOF)
      
          return CBF_FILEREAD;
          
        val [1] = c;
          
        
          /* Calculate the value */
          
        c = strtoul (val, &end, 16);
        
        if (end != &val [2])
        
          return CBF_FORMAT;
      }
    } 
    
    
      /* Save it */
      
    if (outfile)

      cbf_failnez (cbf_put_character (outfile, c))

    if (digest)
    {
      buffer [bufsize] = c;
      
      bufsize++;

      if (bufsize > 63)
      {
        MD5Update (&context, buffer, 64);

        bufsize = 0;
      }
    }

    count++;
  }
  
  
    /* Get the digest */

  if (digest)
  {
    if (bufsize)

      MD5Update (&context, buffer, bufsize);

    MD5Final (rawdigest, &context);

    cbf_md5digest_to64 (digest, rawdigest);
  }


    /* Flush the buffer */

  if (outfile)
  
    cbf_failnez (cbf_flush_characters (outfile))


    /* Save the number of characters read */
    
  if (readsize)
  
    *readsize = count;
    
    
    /* Success */
    
  return 0;
}
int cbf_is_base64digest ( const char *  encoded_digest)

Definition at line 184 of file cbf_codes.c.

Referenced by cbf_check_digest(), cbf_lex(), cbf_mime_temp(), cbf_set_bintext(), and cbf_write_binary().

{
  static char basis_64 [] =

       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
       
  if (!encoded_digest)
  
    return 0;

  if (strlen (encoded_digest) != 24)

    return 0;
    
  return strspn (encoded_digest, basis_64) == 22 &&
                 encoded_digest [22] == '=' &&
                 encoded_digest [23] == '=';
}
int cbf_md5digest ( cbf_file file,
size_t  size,
char *  digest 
)

Definition at line 251 of file cbf_codes.c.

References cbf_failnez, cbf_get_block(), cbf_get_buffer(), cbf_md5digest_to64(), MD5Final(), MD5Init(), and MD5Update().

Referenced by cbf_check_digest(), cbf_lex(), and cbf_write_binary().

{
  MD5_CTX context;
  
  unsigned char rawdigest [17];

  unsigned int todo;
  
  const char *buffer;


    /* Initialise the MD5 context */

  MD5Init (&context);


    /* Update the digest in blocks of 1024 */

  while (size > 0)
  {
    if (size >= 1024)

      todo = 1024;

    else

      todo = size;

    cbf_failnez (cbf_get_block (file, todo))
    
    cbf_failnez (cbf_get_buffer (file, &buffer, NULL))

    MD5Update (&context, buffer, todo);

    size -= todo;
  }
  
  
    /* Get the final digest */
    
  MD5Final (rawdigest, &context);

  cbf_md5digest_to64 (digest, rawdigest);


    /* Success */
    
  return 0;
}
int cbf_md5digest_to64 ( char *  encoded_digest,
const unsigned char *  digest 
)

Definition at line 206 of file cbf_codes.c.

References CBF_ARGUMENT.

Referenced by cbf_end_digest(), cbf_frombase64(), cbf_frombasex(), cbf_fromqp(), and cbf_md5digest().

{
  static char basis_64 [] =

       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

  int todo;
  
  if (!encoded_digest || !digest)
  
    return CBF_ARGUMENT;
  

    /* Encode the 16 characters in base 64 */
    
  for (todo = 0; todo < 18; todo += 3)
  {
    encoded_digest [0] = basis_64 [((digest [todo + 0] >> 2) & 0x03f)];

    if (todo < 15)
    {
      encoded_digest [1] = basis_64 [((digest [todo + 0] << 4) & 0x030) |
                                     ((digest [todo + 1] >> 4) & 0x00f)];
      encoded_digest [2] = basis_64 [((digest [todo + 1] << 2) & 0x03c) |
                                     ((digest [todo + 2] >> 6) & 0x003)];
      encoded_digest [3] = basis_64 [((digest [todo + 2])      & 0x03f)];
    }
    else
    {
      encoded_digest [1] = basis_64 [((digest [todo + 0] << 4) & 0x030)];

      encoded_digest [2] = encoded_digest [3] = '=';
    }

    encoded_digest += 4;
  } 
  
  *encoded_digest  = '\0';

  return 0;
}    
int cbf_tobase64 ( cbf_file infile,
cbf_file outfile,
size_t  size 
)

Definition at line 380 of file cbf_codes.c.

References cbf_failnez, CBF_FILEREAD, cbf_flush_characters(), cbf_get_character(), cbf_write_character(), cbf_write_string(), and cbf_file::column.

Referenced by cbf_write_binary().

{
  static char basis_64 [] =

       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

  int c [3];
    
  int read;
    
  while (size > 0)
  {
      /* Read up to 3 characters */
        
    c [1] = c [2] = 0;

    for (read = 0; read < 3 && read < size; read++)
    {
      c [read] = cbf_get_character (infile);
        
      if (c [read] == EOF)
        
        return CBF_FILEREAD;
    }

    size -= read;

    if (outfile->column > 71)
    
      cbf_failnez (cbf_write_character (outfile, '\n'))


      /* Write a 24-bit chunk in base-64 */
      
    cbf_failnez (cbf_write_character (outfile, 
                                        basis_64 [(c [0] >> 2) & 0x03f]))
    cbf_failnez (cbf_write_character (outfile, 
                                        basis_64 [((c [0] << 4) & 0x030) |
                                                  ((c [1] >> 4) & 0x00f)]))
                                                     
    if (read == 1)
    
      cbf_failnez (cbf_write_string (outfile, "=="))
      
    else
    {
      cbf_failnez (cbf_write_character (outfile, 
                                        basis_64 [((c [1] << 2) & 0x03c) |
                                                  ((c [2] >> 6) & 0x003)]))
    
      if (read == 2)

        cbf_failnez (cbf_write_character (outfile, '='))

      else 

        cbf_failnez (cbf_write_character (outfile, basis_64 [c [2] & 0x03f]))
    }
  }
  
  if (outfile->column)

    cbf_failnez (cbf_write_character (outfile, '\n'))

    
    /* Flush the buffer */

  cbf_failnez (cbf_flush_characters (outfile))

   
    /* Success */
    
  return 0;
}
int cbf_tobasex ( cbf_file infile,
cbf_file outfile,
size_t  size,
size_t  elsize,
unsigned int  base 
)

Definition at line 458 of file cbf_codes.c.

References CBF_ARGUMENT, cbf_failnez, CBF_FILEREAD, cbf_flush_characters(), cbf_get_character(), cbf_write_character(), cbf_write_string(), cbf_file::column, cbf_compress_nodestruct::count, ENC_BACKWARD, ENC_FORWARD, and cbf_file::write_encoding.

Referenced by cbf_write_binary().

{
  int c [8];
  
  int count, read;
  
  long l;
  
  unsigned long block_count;
  
  char line [96], number [64];
  

    /* Check the arguments */
    
  if (elsize > 8 || (base != 8 && base != 10 && base != 16))
  
    return CBF_ARGUMENT;
  

  block_count = 0;

  while (size > 0)
  {
      /* End of a 512-element block? */

    if ((block_count % 512) == 0)
    {
      if (outfile->column)

        cbf_failnez (cbf_write_character (outfile, '\n'))
        
      if (block_count)
      
        cbf_failnez (cbf_write_string (outfile, "#\n"))
        
      if (base == 8)

        cbf_failnez (cbf_write_string (outfile, "# Octal encoding"))
        
      else
      
        if (base == 10)

          cbf_failnez (cbf_write_string (outfile, "# Decimal encoding"))
          
        else
        
          cbf_failnez (cbf_write_string (outfile, "# Hexadecimal encoding"))

      sprintf (line, ", byte %lu", (unsigned long) block_count * elsize);

      cbf_failnez (cbf_write_string (outfile, line))

      if (outfile->write_encoding & ENC_FORWARD)

        cbf_failnez (cbf_write_string (outfile, ", byte order 1234...\n#\n"))
                             
      else
    
        cbf_failnez (cbf_write_string (outfile, ", byte order ...4321\n#\n"))
    }


      /* Read up to elsize characters */
        
    memset (c, 0, sizeof (c));

    for (read = 0; read < elsize && read < size; read++)
    {
      c [read] = cbf_get_character (infile);
        
      if (c [read] == EOF)
        
        return CBF_FILEREAD;
    }
    
    size -= read;
    
    block_count++;


      /* Make the number */

    number [0] = '\0';
    
    if ((outfile->write_encoding & ENC_BACKWARD) && read < elsize)

      for (count = read; count < elsize; count++)

        strcat (number, "==");

    l = 0;
    
    if (outfile->write_encoding & ENC_FORWARD)

      for (count = read - 1; count >= 0; count--)
        
        l = (l << 8) | (c [count] & 0x0ff);

    else

      for (count = 0; count < read; count++)
        
        l = (l << 8) | (c [count] & 0x0ff);

    if (base == 8)

      sprintf (number + strlen (number), "%lo", l);
      
    else

      if (base == 10)
    
        sprintf (number + strlen (number), "%lu", l);
        
      else

        sprintf (number + strlen (number), "%lX", l);
    
    if ((outfile->write_encoding & ENC_FORWARD) && read < elsize)

      for (count = read; count < elsize; count++)

        strcat (number, "==");


      /* Write the number */    

    if (outfile->column + strlen (number) > 74)

      cbf_failnez (cbf_write_character (outfile, '\n'))

    if (outfile->column)

      cbf_failnez (cbf_write_character (outfile, ' '))

    else
    {
        /* Start a new line */
        
      if (base == 8)
      
        cbf_failnez (cbf_write_character (outfile, 'O'))
        
      else
      
        if (base == 10)
        
          cbf_failnez (cbf_write_character (outfile, 'D'))
          
        else
        
          cbf_failnez (cbf_write_character (outfile, 'H'))
      
      sprintf (line, "%1u", (unsigned int) elsize);
      
      cbf_failnez (cbf_write_string (outfile, line))

      if (outfile->write_encoding & ENC_FORWARD)
      
        cbf_failnez (cbf_write_string (outfile, "> "))
        
      else
      
        cbf_failnez (cbf_write_string (outfile, "< "))
    }

    cbf_failnez (cbf_write_string (outfile, number))
  }
  
  if (outfile->column)

    cbf_failnez (cbf_write_character (outfile, '\n'))

    
    /* Flush the buffer */

  cbf_failnez (cbf_flush_characters (outfile))

   
    /* Success */

  return 0;
}
int cbf_toqp ( cbf_file infile,
cbf_file outfile,
size_t  size 
)

Definition at line 304 of file cbf_codes.c.

References CBF_ARGUMENT, cbf_failnez, CBF_FILEREAD, cbf_flush_characters(), cbf_get_character(), cbf_write_character(), cbf_write_string(), and cbf_file::column.

Referenced by cbf_write_binary().

{
  static char basis_16 [] = "0123456789ABCDEF";

  int c;
    
    
    /* Check the arguments */
      
  if (!infile || !outfile)
    
    return CBF_ARGUMENT;


    /* Copy the characters */      
    
  while (size > 0)
  {
      /* Read the next character */
        
    c = cbf_get_character (infile);
      
    if (c == EOF)
      
      return CBF_FILEREAD;
    
    size--;

    if (outfile->column > 74)
      
      cbf_failnez (cbf_write_string (outfile, "=\n"))

    if ((c <= 31)  ||
        (c >= 39 && c <= 41) ||
        (c >= 43 && c <= 47) ||
        (c == 58)  ||
        (c == 61)  ||
        (c == 63)  ||
        (c >= 127) || 
        (c == ';' && outfile->column == 0))
    {
        /* Base-16 */
        
      if (outfile->column > 72)
      
        cbf_failnez (cbf_write_string (outfile, "=\n"))
      
      cbf_failnez (cbf_write_character (outfile, '='))
      cbf_failnez (cbf_write_character (outfile, basis_16 [(c >> 4) & 0x0f]))
      cbf_failnez (cbf_write_character (outfile, basis_16 [c & 0x0f]))
    }
    else

        /* Base-256 */
        
      cbf_failnez (cbf_write_character (outfile, c))
  }
  
  if (outfile->column)

    cbf_failnez (cbf_write_string (outfile, "=\n"))


    /* Flush the buffer */

  cbf_failnez (cbf_flush_characters (outfile))

   
    /* Success */
    
  return 0;
}