Functions

cbf_read_mime.h File Reference

#include "cbf_file.h"
Include dependency graph for cbf_read_mime.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

int cbf_mime_temp (cbf_node *column, unsigned int row)
int cbf_nblen (const char *line, int *nblen)
int cbf_read_mime (cbf_file *infile, cbf_file *outfile, size_t *size, long *id, char *old_digest, char *new_digest)
int cbf_parse_mimeheader (cbf_file *file, int *encoding, size_t *size, long *id, char *digest, unsigned int *compression, int *bits, int *sign)

Function Documentation

int cbf_mime_temp ( cbf_node column,
unsigned int  row 
)

Definition at line 167 of file cbf_read_mime.c.

References bits(), CBF_ASCII, cbf_delete_fileconnection(), cbf_failnez, CBF_FORMAT, cbf_get_bintext(), cbf_get_fileposition(), cbf_is_base64digest(), cbf_is_mimebinary(), cbf_onfailnez, cbf_open_temporary(), cbf_read_mime(), cbf_set_bintext(), cbf_set_fileposition(), CBF_TOKEN_TMP_BIN, cbf_node_struct::context, MSG_DIGEST, and cbf_file::read_headers.

Referenced by cbf_binary_parameters(), cbf_check_digest(), cbf_get_binary(), and cbf_write_value().

{
  cbf_file *file;
  
  cbf_file *temp_file;
  
  long start, temp_start;
  
  size_t size;
  
  int id, bits, sign, type, checked_digest;

  unsigned int compression;
  
  char old_digest [25], *new_digest, digest [25];

  
    /* Check the value */

  if (!cbf_is_mimebinary (column, row))

    return CBF_ASCII;


    /* Parse it */

  size = 0;
  
  cbf_failnez (cbf_get_bintext (column, row, &type,
                                &id, &file, &start, &size, &checked_digest, 
                                old_digest, &bits, &sign, &compression))
  

    /* Position the file at the start of the mime section */

  cbf_failnez (cbf_set_fileposition (file, start, SEEK_SET))


    /* Get the temporary file */

  cbf_failnez (cbf_open_temporary (column->context, &temp_file))


    /* Move to the end of the temporary file */

  cbf_onfailnez (cbf_set_fileposition (temp_file, 0, SEEK_END),
                 cbf_delete_fileconnection (&temp_file))


    /* Get the starting location */

  cbf_onfailnez (cbf_get_fileposition (temp_file, &temp_start),
                 cbf_delete_fileconnection (&temp_file))
    

    /* Calculate a new digest if necessary */
    
  if (cbf_is_base64digest (old_digest) && (file->read_headers & MSG_DIGEST) 
                                       && !checked_digest)

    new_digest = digest;
    
  else
  
    new_digest = NULL;
    

    /* Decode the binary data to the temporary file */
    
  cbf_onfailnez (cbf_read_mime (file, temp_file, 
                                      NULL, NULL, old_digest, new_digest),
                 cbf_delete_fileconnection (&temp_file))


    /* Check the digest */
    
  if (new_digest)
  
    if (strcmp (old_digest, new_digest) == 0)
    
      checked_digest = 1;
      
    else
                 
      return CBF_FORMAT | cbf_delete_fileconnection (&temp_file);

  
    /* Replace the connection */
    
  cbf_onfailnez (cbf_set_bintext (column, row, CBF_TOKEN_TMP_BIN,
                                  id, temp_file, temp_start, size, 
                                  checked_digest, old_digest, bits,
                                                              sign,
                                                              compression),
                    cbf_delete_fileconnection (&temp_file))
 

    /* Success */
    
  return 0;
}
int cbf_nblen ( const char *  line,
int *  nblen 
)

Definition at line 375 of file cbf_read_mime.c.

Referenced by cbf_lex(), and cbf_parse_mimeheader().

{
  register char *myline;

  register int mylen;

  *nblen = mylen = 0;

  

  if (!(myline = (char *)line)) return 1;

  for (; *myline; myline++)

    if (!isspace (*myline)) mylen = myline-(char *)line+1;

  *nblen = mylen;

  return 0;
  
}
int cbf_parse_mimeheader ( cbf_file file,
int *  encoding,
size_t *  size,
long *  id,
char *  digest,
unsigned int *  compression,
int *  bits,
int *  sign 
)

Definition at line 516 of file cbf_read_mime.c.

References CBF_BYTE_OFFSET, CBF_CANONICAL, cbf_cistrncmp(), cbf_failnez, CBF_FORMAT, cbf_is_blank(), cbf_nblen(), CBF_NONE, CBF_PACKED, CBF_PREDICTOR, cbf_read_line(), cbf_skip_whitespace(), cbf_compress_nodestruct::count, ENC_BASE10, ENC_BASE16, ENC_BASE64, ENC_BASE8, ENC_NONE, and ENC_QP.

Referenced by cbf_lex(), and cbf_read_mime().

{
  static const char *value [] = {
  
    "Content-Type:",                /* State 0 */
    "Content-Transfer-Encoding:",   /* State 1 */
    "X-Binary-Size:",               /* State 2 */
    "X-Binary-ID:",                 /* State 3 */
    "X-Binary-Element-Type:",       /* State 4 */
    "Content-MD5:"                  /* State 5 */
  
    };

  const char *line, *c;
  
  int state, continuation, item, line_count, fresh_line, quote, text_bits, 
      count, failure, nblen;
  
  
    /* Defaults */
    
  if (encoding)
  
    *encoding = 0;
  
  if (size)
  
    *size = 0;
  
  if (id)
  
    *id = 0;
  
  if (digest)
  
    *digest = '\0';

  if (compression)

    *compression = CBF_NONE;
    
  if (bits)
  
    *bits = 0;
    
  if (sign)
  
    *sign = -1;
  
  
    /* Read the file line by line */
    
  state = -1;
  
  line_count = 0;

  fresh_line = 0;

  nblen = 1;

  while (nblen)
  {
    if (!fresh_line)
    
      cbf_failnez (cbf_read_line (file, &line))

    cbf_nblen(line, &nblen);
      
    fresh_line = 0;

    line_count++;

     /* Check for premature terminations */
 
    if ( (line[0] == ';') || 
      ( cbf_cistrncmp(line,"--CIF-BINARY-FORMAT-SECTION--",29) == 0 ) )

      return CBF_FORMAT;


      /* Check for a header continuation line */
      
    continuation = line [0] == ' ' || line [0] == '\t';


      /* Check for a new item */
      
    if (continuation)

      item = 0;
      
    else
    {
      for (c = line; *c != ':' && *c > 32 && *c < 127; c++);
      
      item = c != line && *c == ':';
    }
          

      /* Check for the end of the header */

    if (line_count > 1 && cbf_is_blank (line))
            
      return 0;


      /* Check for valid header-ness of line */
      
    if (!item && (line_count == 1 || !continuation))

      return CBF_FORMAT;
        

       /* Look for the entries we are interested in */
      
    c = line;

    if (item)

      for (state = 5; state > -1; state--)

        if (cbf_cistrncmp (line, value [state], strlen (value [state])) 
                           == 0)

        {
          c = line + strlen (value [state]);
          
          break;
        }
       

      /* Skip past comments and whitespace */
        
    cbf_failnez (cbf_skip_whitespace (file, &line, &c, &fresh_line))
      

      /* Get the value */
      
    switch (state)
    {
      case 0:
          
          /* Content */
              
        if (cbf_cistrncmp (c, "application/", 12) != 0 &&
            cbf_cistrncmp (c, "image/",        6) != 0 &&
            cbf_cistrncmp (c, "text/",         5) != 0 &&
            cbf_cistrncmp (c, "audio/",        6) != 0 &&
            cbf_cistrncmp (c, "video/",        6) != 0)

          return CBF_FORMAT;

              
        while (*c)
        {
            /* Skip to the end of the section (a semicolon) */
              
          while (*c)
              
            if (*c == '\"')
            {
              c++;

              while (*c)

                if (*c == '\"')
                {
                  c++;

                  break;
                }
                else
                {
                  if (*c == '\\')

                    c++;

                  if (*c)

                    c++;
                }
            }
            else 

              if (*c == '(')

                cbf_failnez (cbf_skip_whitespace (file, &line, &c, 
                                                        &fresh_line))

              else

                if (*c == ';')
                {
                  c++;

                  break;
                }
                else

                  c++;

            
            /* We are at the end of the section or the end of the item */
              
          cbf_failnez (cbf_skip_whitespace (file, &line, &c, 
                                                  &fresh_line))

          if (cbf_cistrncmp (c, "conversions", 11) == 0) 
          {
            c += 11;

            cbf_failnez (cbf_skip_whitespace (file, &line, &c, 
                                                    &fresh_line))

            if (*c == '=') 
            {
              c++;

              cbf_failnez (cbf_skip_whitespace (file, &line, &c, 
                                                      &fresh_line))

              if (compression) 
              {
                quote = 0;

                if (*c == '\"')
                      
                  quote = 1;
                      
                *compression = CBF_NONE;

                if (cbf_cistrncmp (c + quote, "x-cbf_packed", 12) == 0)

                  *compression = CBF_PACKED;

                if (cbf_cistrncmp (c + quote, "x-cbf_canonical", 15) == 0)
                      
                  *compression = CBF_CANONICAL;

                if (cbf_cistrncmp (c + quote, "x-cbf_byte_offset", 17) == 0)
  
                  *compression = CBF_BYTE_OFFSET;

                if (cbf_cistrncmp (c + quote, "x-cbf_predictor", 15) == 0)

                  *compression = CBF_PREDICTOR;
              }
            }
          }
        }
          
      state = -1;
          
      break;

      case 1:
        
          /* Binary encoding */
              
        if (encoding)
        {
           failure = 1;

           quote = 0;

           if (*c == '\"')
                      
              quote = 1;

          if (cbf_cistrncmp (c+quote, "Quoted-Printable", 16) == 0)
              
            if (isspace (c [16]) || c [16] == '(' 
              || (quote && c [16] == '\"')) {

              failure = 0;
              
              *encoding = ENC_QP;
            }
                
          if (cbf_cistrncmp (c+quote, "Base64", 6) == 0)
              
            if (isspace (c [6]) || c [6] == '(' || (quote && c [16] == '\"')) {

              failure = 0;
              
              *encoding = ENC_BASE64;
            }
                
          if (cbf_cistrncmp (c+quote, "X-Base8", 7) == 0)

            if (isspace (c [7]) || c [7] == '(' || (quote && c [16] == '\"')) {

              failure = 0;
              
              *encoding = ENC_BASE8;
            }
                
          if (cbf_cistrncmp (c+quote, "X-Base10", 8) == 0)
              
            if (isspace (c [8]) || c [8] == '(' || (quote && c [16] == '\"')) {

              failure = 0;
              
              *encoding = ENC_BASE10;
            }
                
          if (cbf_cistrncmp (c+quote, "X-Base16", 8) == 0)
              
            if (isspace (c [8]) || c [8] == '(' || (quote && c [16] == '\"')) {

              failure = 0;
              
              *encoding = ENC_BASE16;
            }

          if (cbf_cistrncmp (c+quote, "7bit", 4) == 0 ||
              cbf_cistrncmp (c+quote, "8bit", 4) == 0)
              
            if (isspace (c [4]) || c [4] == '(' || (quote && c [16] == '\"')) {

              failure = 0;
              
              *encoding = ENC_NONE;
            }

          if (cbf_cistrncmp (c+quote, "Binary", 6) == 0)
              
            if (isspace (c [6]) || c [6] == '(' || (quote && c [16] == '\"')) {

              failure = 0;
              
              *encoding = ENC_NONE;
            }
        }

        if (failure) return CBF_FORMAT;
        
        break;
          
      case 2:
          
          /* Binary size */
            
        if (size)
          
          *size = atol (c);
            
        break;
          
      case 3:

          /* Binary ID */
          
        if (id)

          *id = atol (c);
              
        break;
            
      case 4:
          
          /* Binary element type (signed/unsigned ?-bit integer) */

        failure = 3;

        while (*c)
        {
          quote = 0;

          cbf_failnez (cbf_skip_whitespace (file, &line, &c, 
                                                  &fresh_line))
          if (*c == '\"') {

            if (quote) break;

            c++;

            quote++;
          }
          
          if (failure == 3) {

            if (cbf_cistrncmp (c, "signed", 6) == 0)
            {
              c += 6;
            
              if (sign) *sign = 1;

              failure --;
            }
          
            if (cbf_cistrncmp (c, "unsigned", 8) == 0)
            {
              c += 8;
              
              if (sign) *sign = 0;

              failure --;
            }
          }
          
          if (failure == 2) {

            count = 0;
            
            sscanf (c, "%d-%n", &text_bits, &count);
              
            if (cbf_cistrncmp (c+count, "bit", 3 ) == 0)

              if (count && text_bits > 0 && text_bits <= 64)
              {
                c += count;
            
                if (bits) *bits = text_bits;

                failure --;
              }
          }

          if (failure == 1) {

            if (cbf_cistrncmp (c, "integer", 7 ) == 0) failure--;

          }

          if (*c)
          
            c++;
        }
        
        if (failure) return CBF_FORMAT;
 
        break;
          
      case 5:

          /* Message digest */
            
        if (digest)
        {
          strncpy (digest, c, 24);
              
          digest [24] = '\0';
        }
            
        break;
    }
  }


    /* Success */
    
  return 0;      
}
int cbf_read_mime ( cbf_file infile,
cbf_file outfile,
size_t *  size,
long *  id,
char *  old_digest,
char *  new_digest 
)

Definition at line 272 of file cbf_read_mime.c.

References cbf_failnez, cbf_flush_bits(), CBF_FORMAT, cbf_frombase64(), cbf_frombasex(), cbf_fromqp(), cbf_parse_mimeheader(), cbf_reset_bits(), ENC_BASE10, ENC_BASE16, ENC_BASE64, ENC_BASE8, and ENC_QP.

Referenced by cbf_mime_temp().

{
  int encoding;
  
  size_t file_size;

  unsigned int compression;

  
    /* Read the header */
    
  encoding = 0;
  
  file_size = 0;
    
  cbf_failnez (cbf_parse_mimeheader (infile, &encoding, 
                                             &file_size, id, 
                                             old_digest,
                                             &compression,
                                             NULL, NULL))
                                             
  if (file_size <= 0)

    return CBF_FORMAT;


    /* Discard any bits in the buffers */
    
  cbf_failnez (cbf_reset_bits (outfile))


    /* Decode the binary data */
    
  switch (encoding)
  {
    case ENC_QP:
    
      cbf_failnez (cbf_fromqp (infile, outfile, file_size, NULL, 
                               new_digest))

      break;
      
    case ENC_BASE64:
    
      cbf_failnez (cbf_frombase64 (infile, outfile, file_size, NULL, 
                                   new_digest))

      break;
      
    case ENC_BASE8:
    case ENC_BASE10:
    case ENC_BASE16:
    
      cbf_failnez (cbf_frombasex (infile, outfile, file_size, NULL, 
                                  new_digest))

      break;
      
    default:
    
      return CBF_FORMAT;
  }


    /* Flush the buffers */

  cbf_failnez (cbf_flush_bits (outfile))


    /* Size (excluding the encoding) */

  if (size)
  
    *size = file_size;
    
    
    /* Success */
    
  return 0;
}