cbf_read_mime.c

Go to the documentation of this file.
00001 /**********************************************************************
00002  * cbf_read_mime -- read MIME-encoded binary sections                 *
00003  *                                                                    *
00004  * Version 0.6 13 January 1999                                        *
00005  *                                                                    *
00006  *            Paul Ellis (ellis@ssrl.slac.stanford.edu) and           *
00007  *         Herbert J. Bernstein (yaya@bernstein-plus-sons.com)        *
00008  **********************************************************************/
00009   
00010 /**********************************************************************
00011  *                               NOTICE                               *
00012  * Creative endeavors depend on the lively exchange of ideas. There   *
00013  * are laws and customs which establish rights and responsibilities   *
00014  * for authors and the users of what authors create.  This notice     *
00015  * is not intended to prevent you from using the software and         *
00016  * documents in this package, but to ensure that there are no         *
00017  * misunderstandings about terms and conditions of such use.          *
00018  *                                                                    *
00019  * Please read the following notice carefully.  If you do not         *
00020  * understand any portion of this notice, please seek appropriate     *
00021  * professional legal advice before making use of the software and    *
00022  * documents included in this software package.  In addition to       *
00023  * whatever other steps you may be obliged to take to respect the     *
00024  * intellectual property rights of the various parties involved, if   *
00025  * you do make use of the software and documents in this package,     *
00026  * please give credit where credit is due by citing this package,     *
00027  * its authors and the URL or other source from which you obtained    *
00028  * it, or equivalent primary references in the literature with the    *
00029  * same authors.                                                      *
00030  *                                                                    *
00031  * Some of the software and documents included within this software   *
00032  * package are the intellectual property of various parties, and      *
00033  * placement in this package does not in any way imply that any       *
00034  * such rights have in any way been waived or diminished.             *
00035  *                                                                    *
00036  * With respect to any software or documents for which a copyright    *
00037  * exists, ALL RIGHTS ARE RESERVED TO THE OWNERS OF SUCH COPYRIGHT.   *
00038  *                                                                    *
00039  * Even though the authors of the various documents and software      *
00040  * found here have made a good faith effort to ensure that the        *
00041  * documents are correct and that the software performs according     *
00042  * to its documentation, and we would greatly appreciate hearing of   *
00043  * any problems you may encounter, the programs and documents any     *
00044  * files created by the programs are provided **AS IS** without any   *
00045  * warranty as to correctness, merchantability or fitness for any     *
00046  * particular or general use.                                         *
00047  *                                                                    *
00048  * THE RESPONSIBILITY FOR ANY ADVERSE CONSEQUENCES FROM THE USE OF    *
00049  * PROGRAMS OR DOCUMENTS OR ANY FILE OR FILES CREATED BY USE OF THE   *
00050  * PROGRAMS OR DOCUMENTS LIES SOLELY WITH THE USERS OF THE PROGRAMS   *
00051  * OR DOCUMENTS OR FILE OR FILES AND NOT WITH AUTHORS OF THE          *
00052  * PROGRAMS OR DOCUMENTS.                                             *
00053  **********************************************************************/
00054  
00055 /**********************************************************************
00056  *                          The IUCr Policy                           *
00057  *                                 on                                 *
00058  *     the Use of the Crystallographic Information File (CIF)         *
00059  *                                                                    *
00060  * The Crystallographic Information File (Hall, Allen & Brown,        *
00061  * 1991) is, as of January 1992, the recommended method for           *
00062  * submitting publications to Acta Crystallographica Section C. The   *
00063  * International Union of Crystallography holds the Copyright on      *
00064  * the CIF, and has applied for Patents on the STAR File syntax       *
00065  * which is the basis for the CIF format.                             *
00066  *                                                                    *
00067  * It is a principal objective of the IUCr to promote the use of      *
00068  * CIF for the exchange and storage of scientific data. The IUCr's    *
00069  * sponsorship of the CIF development was motivated by its            *
00070  * responsibility to its scientific journals, which set the           *
00071  * standards in crystallographic publishing. The IUCr intends that    *
00072  * CIFs will be used increasingly for electronic submission of        *
00073  * manuscripts to these journals in future. The IUCr recognises       *
00074  * that, if the CIF and the STAR File are to be adopted as a means    *
00075  * for universal data exchange, the syntax of these files must be     *
00076  * strictly and uniformly adhered to. Even small deviations from      *
00077  * the syntax would ultimately cause the demise of the universal      *
00078  * file concept. Through its Copyrights and Patents the IUCr has      *
00079  * taken the steps needed to ensure strict conformance with this      *
00080  * syntax.                                                            *
00081  *                                                                    *
00082  * The IUCr policy on the use of the CIF and STAR File processes is   *
00083  * as follows:                                                        *
00084  * _________________________________________________________________  *
00085  *                                                                    *
00086  *  * 1 CIFs and STAR Files may be generated, stored or transmitted,  *
00087  *    without permission or charge, provided their purpose is not     *
00088  *    specifically for profit or commercial gain, and provided that   *
00089  *    the published syntax is strictly adhered to.                    *
00090  *  * 2 Computer software may be developed for use with CIFs or STAR  *
00091  *    files, without permission or charge, provided it is distributed *
00092  *    in the public domain. This condition also applies to software   *
00093  *    for which a charge is made, provided that its primary function  *
00094  *    is for use with files that satisfy condition 1 and that it is   *
00095  *    distributed as a minor component of a larger package of         *
00096  *    software.                                                       *
00097  *  * 3 Permission will be granted for the use of CIFs and STAR Files *
00098  *    for specific commercial purposes (such as databases or network  *
00099  *    exchange processes), and for the distribution of commercial     *
00100  *    CIF/STAR software, on written application to the IUCr Executive *
00101  *    Secretary, 2 Abbey Square, Chester CH1 2HU, England. The        *
00102  *    nature, terms and duration of the licences granted will be      *
00103  *    determined by the IUCr Executive and Finance Committees.        *
00104  *                                                                    *
00105  * _________________________________________________________________  *
00106  *                                                                    *
00107  * In summary, the IUCr wishes to promote the use of the STAR File    *
00108  * concepts as a standard universal data file. It will insist on      *
00109  * strict compliance with the published syntax for all                *
00110  * applications. To assist with this compliance, the IUCr provides    *
00111  * public domain software for checking the logical integrity of a     *
00112  * CIF, and for validating the data name definitions contained        *
00113  * within a CIF. Detailed information on this software, and the       *
00114  * associated dictionaries, may be obtained from the IUCr Office at   *
00115  * 5 Abbey Square, Chester CH1 2HU, England.                          *
00116  **********************************************************************/
00117 
00118 /**********************************************************************
00119  * The following notice applies to some portions of this software     *
00120  * which were derived in part from the routine decode.c in mpack      *
00121  *                                                                    *
00122  * (C) Copyright 1993,1994 by Carnegie Mellon University              *
00123  * All Rights Reserved.                                               *
00124  *                                                                    *
00125  * Permission to use, copy, modify, distribute, and sell this         *
00126  * softwareand its documentation for any purpose is hereby granted    *
00127  * without fee, provided that the above copyright notice appear in    *
00128  * all copies and that both that copyright notice and this permission *
00129  * notice appear in supporting documentation, and that the name of    *
00130  * Carnegie Mellon University not be used in advertising or publicity *
00131  * pertaining to distribution of the software without specific,       *
00132  * written prior permission.  Carnegie Mellon University makes no     *
00133  * representations about the suitability of this software for any     *
00134  * purpose.  It is provided "as is" without express or implied        *
00135  * warranty.                                                          *
00136  *                                                                    *
00137  * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO *
00138  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY *
00139  * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE       *
00140  * LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY   *
00141  * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,    *
00142  * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS     *
00143  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR            *
00144  * PERFORMANCE OF THIS SOFTWARE.                                      *
00145  **********************************************************************/
00146 
00147 #ifdef __cplusplus
00148 
00149 extern "C" {
00150 
00151 #endif
00152 
00153 #include "cbf.h"
00154 #include "cbf_file.h"
00155 #include "cbf_context.h"
00156 #include "cbf_binary.h"
00157 #include "cbf_codes.h"
00158 #include "cbf_read_mime.h"
00159 #include "cbf_string.h"
00160 
00161 #include <ctype.h>
00162 #include <string.h>
00163 
00164 
00165   /* Convert a MIME-encoded binary section to a temporary binary section */
00166 
00167 int cbf_mime_temp (cbf_node *column, unsigned int row)
00168 {
00169   cbf_file *file;
00170   
00171   cbf_file *temp_file;
00172   
00173   long start, temp_start;
00174   
00175   size_t size;
00176   
00177   int id, bits, sign, type, checked_digest;
00178 
00179   unsigned int compression;
00180   
00181   char old_digest [25], *new_digest, digest [25];
00182 
00183   
00184     /* Check the value */
00185 
00186   if (!cbf_is_mimebinary (column, row))
00187 
00188     return CBF_ASCII;
00189 
00190 
00191     /* Parse it */
00192 
00193   size = 0;
00194   
00195   cbf_failnez (cbf_get_bintext (column, row, &type,
00196                                 &id, &file, &start, &size, &checked_digest, 
00197                                 old_digest, &bits, &sign, &compression))
00198   
00199 
00200     /* Position the file at the start of the mime section */
00201 
00202   cbf_failnez (cbf_set_fileposition (file, start, SEEK_SET))
00203 
00204 
00205     /* Get the temporary file */
00206 
00207   cbf_failnez (cbf_open_temporary (column->context, &temp_file))
00208 
00209 
00210     /* Move to the end of the temporary file */
00211 
00212   cbf_onfailnez (cbf_set_fileposition (temp_file, 0, SEEK_END),
00213                  cbf_delete_fileconnection (&temp_file))
00214 
00215 
00216     /* Get the starting location */
00217 
00218   cbf_onfailnez (cbf_get_fileposition (temp_file, &temp_start),
00219                  cbf_delete_fileconnection (&temp_file))
00220     
00221 
00222     /* Calculate a new digest if necessary */
00223     
00224   if (cbf_is_base64digest (old_digest) && (file->read_headers & MSG_DIGEST) 
00225                                        && !checked_digest)
00226 
00227     new_digest = digest;
00228     
00229   else
00230   
00231     new_digest = NULL;
00232     
00233 
00234     /* Decode the binary data to the temporary file */
00235     
00236   cbf_onfailnez (cbf_read_mime (file, temp_file, 
00237                                       NULL, NULL, old_digest, new_digest),
00238                  cbf_delete_fileconnection (&temp_file))
00239 
00240 
00241     /* Check the digest */
00242     
00243   if (new_digest)
00244   
00245     if (strcmp (old_digest, new_digest) == 0)
00246     
00247       checked_digest = 1;
00248       
00249     else
00250                  
00251       return CBF_FORMAT | cbf_delete_fileconnection (&temp_file);
00252 
00253   
00254     /* Replace the connection */
00255     
00256   cbf_onfailnez (cbf_set_bintext (column, row, CBF_TOKEN_TMP_BIN,
00257                                   id, temp_file, temp_start, size, 
00258                                   checked_digest, old_digest, bits,
00259                                                               sign,
00260                                                               compression),
00261                     cbf_delete_fileconnection (&temp_file))
00262  
00263 
00264     /* Success */
00265     
00266   return 0;
00267 }
00268 
00269 
00270   /* Convert a MIME-encoded binary section to a normal binary section */
00271      
00272 int cbf_read_mime (cbf_file *infile, cbf_file   *outfile,
00273                                      size_t     *size,
00274                                      long       *id,
00275                                      char       *old_digest,
00276                                      char       *new_digest)
00277 {
00278   int encoding;
00279   
00280   size_t file_size;
00281 
00282   unsigned int compression;
00283 
00284   
00285     /* Read the header */
00286     
00287   encoding = 0;
00288   
00289   file_size = 0;
00290     
00291   cbf_failnez (cbf_parse_mimeheader (infile, &encoding, 
00292                                              &file_size, id, 
00293                                              old_digest,
00294                                              &compression,
00295                                              NULL, NULL))
00296                                              
00297   if (file_size <= 0)
00298 
00299     return CBF_FORMAT;
00300 
00301 
00302     /* Discard any bits in the buffers */
00303     
00304   cbf_failnez (cbf_reset_bits (outfile))
00305 
00306 
00307     /* Decode the binary data */
00308     
00309   switch (encoding)
00310   {
00311     case ENC_QP:
00312     
00313       cbf_failnez (cbf_fromqp (infile, outfile, file_size, NULL, 
00314                                new_digest))
00315 
00316       break;
00317       
00318     case ENC_BASE64:
00319     
00320       cbf_failnez (cbf_frombase64 (infile, outfile, file_size, NULL, 
00321                                    new_digest))
00322 
00323       break;
00324       
00325     case ENC_BASE8:
00326     case ENC_BASE10:
00327     case ENC_BASE16:
00328     
00329       cbf_failnez (cbf_frombasex (infile, outfile, file_size, NULL, 
00330                                   new_digest))
00331 
00332       break;
00333       
00334     default:
00335     
00336       return CBF_FORMAT;
00337   }
00338 
00339 
00340     /* Flush the buffers */
00341 
00342   cbf_failnez (cbf_flush_bits (outfile))
00343 
00344 
00345     /* Size (excluding the encoding) */
00346 
00347   if (size)
00348   
00349     *size = file_size;
00350     
00351     
00352     /* Success */
00353     
00354   return 0;
00355 }
00356 
00357 
00358   /* Is the line blank? */
00359 
00360 int cbf_is_blank (const char *line)
00361 {
00362   if (line)
00363   
00364     for (; *line; line++)
00365     
00366       if (!isspace (*line))
00367       
00368         return 0;
00369         
00370   return 1;
00371 }
00372 
00373 /* Find non-blank length of a line */
00374 
00375 int cbf_nblen (const char *line, int *nblen)
00376 {
00377   register char *myline;
00378 
00379   register int mylen;
00380 
00381   *nblen = mylen = 0;
00382 
00383   
00384 
00385   if (!(myline = (char *)line)) return 1;
00386 
00387   for (; *myline; myline++)
00388 
00389     if (!isspace (*myline)) mylen = myline-(char *)line+1;
00390 
00391   *nblen = mylen;
00392 
00393   return 0;
00394   
00395 }
00396 
00397 
00398   /* Skip whitespace and comments */ 
00399 
00400 int cbf_skip_whitespace (cbf_file *file, const char **line, 
00401                                          const char **curpoint, 
00402                                          int        *freshline)
00403 {
00404   static const char end = '\0';
00405   
00406   const char *c;     
00407 
00408   int comment_level;
00409 
00410 
00411     /* Repeating the end of a line? */
00412 
00413   if (*freshline)
00414   {
00415     *curpoint = &end;
00416     
00417     return 0;
00418   }
00419 
00420   c = *curpoint;
00421 
00422   comment_level = 0;
00423   
00424   while (isspace (*c) || *c == '(' || *c == '\0')
00425 
00426     if (*c == '\0')
00427     {
00428       cbf_failnez (cbf_read_line (file, line))
00429 
00430       c = *line;
00431 
00432       if (cbf_is_blank (c) || (*c != ' ' && *c != '\t'))
00433       {
00434         *freshline = 1;
00435 
00436         *curpoint = &end;
00437 
00438         return 0;
00439       }
00440     } 
00441     else 
00442     
00443       if (*c == '(')
00444       {
00445         c++;
00446 
00447         comment_level++;
00448 
00449         while (comment_level)
00450         {
00451           switch (*c)
00452           {
00453             case '\0':
00454 
00455               cbf_failnez (cbf_read_line (file, line))
00456 
00457               c = *line;
00458 
00459               if (cbf_is_blank (c) || (*c != ' ' && *c != '\t'))
00460               {
00461                 *freshline = 1;
00462 
00463                 *curpoint = &end;
00464 
00465                 return 0;
00466               }
00467 
00468               break;
00469 
00470             case '\\':
00471 
00472               c++;
00473 
00474               break;
00475 
00476             case '(':              
00477 
00478               comment_level++;                
00479 
00480               break;
00481 
00482             case ')':
00483 
00484               comment_level--;
00485 
00486               break;
00487           }
00488 
00489           c++;
00490         }
00491       }
00492       else  
00493       
00494         c++;
00495 
00496   *freshline = 0;
00497 
00498   *curpoint = c;
00499 
00500 
00501     /* Success */
00502     
00503   return 0;
00504 }
00505   
00506 
00507   /* Parse the MIME header looking for values of type:
00508   
00509      Content-Type:
00510      Content-Transfer-Encoding:
00511      X-Binary-Size:
00512      X-Binary-ID:
00513      X-Binary-Element-Type:
00514      Content-MD5: */
00515      
00516 int cbf_parse_mimeheader (cbf_file *file, int        *encoding,
00517                                           size_t     *size,
00518                                           long       *id,
00519                                           char       *digest,
00520                                  unsigned int        *compression,
00521                                           int        *bits,
00522                                           int        *sign)
00523 {
00524   static const char *value [] = {
00525   
00526     "Content-Type:",                /* State 0 */
00527     "Content-Transfer-Encoding:",   /* State 1 */
00528     "X-Binary-Size:",               /* State 2 */
00529     "X-Binary-ID:",                 /* State 3 */
00530     "X-Binary-Element-Type:",       /* State 4 */
00531     "Content-MD5:"                  /* State 5 */
00532   
00533     };
00534 
00535   const char *line, *c;
00536   
00537   int state, continuation, item, line_count, fresh_line, quote, text_bits, 
00538       count, failure, nblen;
00539   
00540   
00541     /* Defaults */
00542     
00543   if (encoding)
00544   
00545     *encoding = 0;
00546   
00547   if (size)
00548   
00549     *size = 0;
00550   
00551   if (id)
00552   
00553     *id = 0;
00554   
00555   if (digest)
00556   
00557     *digest = '\0';
00558 
00559   if (compression)
00560 
00561     *compression = CBF_NONE;
00562     
00563   if (bits)
00564   
00565     *bits = 0;
00566     
00567   if (sign)
00568   
00569     *sign = -1;
00570   
00571   
00572     /* Read the file line by line */
00573     
00574   state = -1;
00575   
00576   line_count = 0;
00577 
00578   fresh_line = 0;
00579 
00580   nblen = 1;
00581 
00582   while (nblen)
00583   {
00584     if (!fresh_line)
00585     
00586       cbf_failnez (cbf_read_line (file, &line))
00587 
00588     cbf_nblen(line, &nblen);
00589       
00590     fresh_line = 0;
00591 
00592     line_count++;
00593 
00594      /* Check for premature terminations */
00595  
00596     if ( (line[0] == ';') || 
00597       ( cbf_cistrncmp(line,"--CIF-BINARY-FORMAT-SECTION--",29) == 0 ) )
00598 
00599       return CBF_FORMAT;
00600 
00601 
00602       /* Check for a header continuation line */
00603       
00604     continuation = line [0] == ' ' || line [0] == '\t';
00605 
00606 
00607       /* Check for a new item */
00608       
00609     if (continuation)
00610 
00611       item = 0;
00612       
00613     else
00614     {
00615       for (c = line; *c != ':' && *c > 32 && *c < 127; c++);
00616       
00617       item = c != line && *c == ':';
00618     }
00619           
00620 
00621       /* Check for the end of the header */
00622 
00623     if (line_count > 1 && cbf_is_blank (line))
00624             
00625       return 0;
00626 
00627 
00628       /* Check for valid header-ness of line */
00629       
00630     if (!item && (line_count == 1 || !continuation))
00631 
00632       return CBF_FORMAT;
00633         
00634 
00635        /* Look for the entries we are interested in */
00636       
00637     c = line;
00638 
00639     if (item)
00640 
00641       for (state = 5; state > -1; state--)
00642 
00643         if (cbf_cistrncmp (line, value [state], strlen (value [state])) 
00644                            == 0)
00645 
00646         {
00647           c = line + strlen (value [state]);
00648           
00649           break;
00650         }
00651        
00652 
00653       /* Skip past comments and whitespace */
00654         
00655     cbf_failnez (cbf_skip_whitespace (file, &line, &c, &fresh_line))
00656       
00657 
00658       /* Get the value */
00659       
00660     switch (state)
00661     {
00662       case 0:
00663           
00664           /* Content */
00665               
00666         if (cbf_cistrncmp (c, "application/", 12) != 0 &&
00667             cbf_cistrncmp (c, "image/",        6) != 0 &&
00668             cbf_cistrncmp (c, "text/",         5) != 0 &&
00669             cbf_cistrncmp (c, "audio/",        6) != 0 &&
00670             cbf_cistrncmp (c, "video/",        6) != 0)
00671 
00672           return CBF_FORMAT;
00673 
00674               
00675         while (*c)
00676         {
00677             /* Skip to the end of the section (a semicolon) */
00678               
00679           while (*c)
00680               
00681             if (*c == '\"')
00682             {
00683               c++;
00684 
00685               while (*c)
00686 
00687                 if (*c == '\"')
00688                 {
00689                   c++;
00690 
00691                   break;
00692                 }
00693                 else
00694                 {
00695                   if (*c == '\\')
00696 
00697                     c++;
00698 
00699                   if (*c)
00700 
00701                     c++;
00702                 }
00703             }
00704             else 
00705 
00706               if (*c == '(')
00707 
00708                 cbf_failnez (cbf_skip_whitespace (file, &line, &c, 
00709                                                         &fresh_line))
00710 
00711               else
00712 
00713                 if (*c == ';')
00714                 {
00715                   c++;
00716 
00717                   break;
00718                 }
00719                 else
00720 
00721                   c++;
00722 
00723             
00724             /* We are at the end of the section or the end of the item */
00725               
00726           cbf_failnez (cbf_skip_whitespace (file, &line, &c, 
00727                                                   &fresh_line))
00728 
00729           if (cbf_cistrncmp (c, "conversions", 11) == 0) 
00730           {
00731             c += 11;
00732 
00733             cbf_failnez (cbf_skip_whitespace (file, &line, &c, 
00734                                                     &fresh_line))
00735 
00736             if (*c == '=') 
00737             {
00738               c++;
00739 
00740               cbf_failnez (cbf_skip_whitespace (file, &line, &c, 
00741                                                       &fresh_line))
00742 
00743               if (compression) 
00744               {
00745                 quote = 0;
00746 
00747                 if (*c == '\"')
00748                       
00749                   quote = 1;
00750                       
00751                 *compression = CBF_NONE;
00752 
00753                 if (cbf_cistrncmp (c + quote, "x-cbf_packed", 12) == 0)
00754 
00755                   *compression = CBF_PACKED;
00756 
00757                 if (cbf_cistrncmp (c + quote, "x-cbf_canonical", 15) == 0)
00758                       
00759                   *compression = CBF_CANONICAL;
00760 
00761                 if (cbf_cistrncmp (c + quote, "x-cbf_byte_offset", 17) == 0)
00762   
00763                   *compression = CBF_BYTE_OFFSET;
00764 
00765                 if (cbf_cistrncmp (c + quote, "x-cbf_predictor", 15) == 0)
00766 
00767                   *compression = CBF_PREDICTOR;
00768               }
00769             }
00770           }
00771         }
00772           
00773       state = -1;
00774           
00775       break;
00776 
00777       case 1:
00778         
00779           /* Binary encoding */
00780               
00781         if (encoding)
00782         {
00783            failure = 1;
00784 
00785            quote = 0;
00786 
00787            if (*c == '\"')
00788                       
00789               quote = 1;
00790 
00791           if (cbf_cistrncmp (c+quote, "Quoted-Printable", 16) == 0)
00792               
00793             if (isspace (c [16]) || c [16] == '(' 
00794               || (quote && c [16] == '\"')) {
00795 
00796               failure = 0;
00797               
00798               *encoding = ENC_QP;
00799             }
00800                 
00801           if (cbf_cistrncmp (c+quote, "Base64", 6) == 0)
00802               
00803             if (isspace (c [6]) || c [6] == '(' || (quote && c [16] == '\"')) {
00804 
00805               failure = 0;
00806               
00807               *encoding = ENC_BASE64;
00808             }
00809                 
00810           if (cbf_cistrncmp (c+quote, "X-Base8", 7) == 0)
00811 
00812             if (isspace (c [7]) || c [7] == '(' || (quote && c [16] == '\"')) {
00813 
00814               failure = 0;
00815               
00816               *encoding = ENC_BASE8;
00817             }
00818                 
00819           if (cbf_cistrncmp (c+quote, "X-Base10", 8) == 0)
00820               
00821             if (isspace (c [8]) || c [8] == '(' || (quote && c [16] == '\"')) {
00822 
00823               failure = 0;
00824               
00825               *encoding = ENC_BASE10;
00826             }
00827                 
00828           if (cbf_cistrncmp (c+quote, "X-Base16", 8) == 0)
00829               
00830             if (isspace (c [8]) || c [8] == '(' || (quote && c [16] == '\"')) {
00831 
00832               failure = 0;
00833               
00834               *encoding = ENC_BASE16;
00835             }
00836 
00837           if (cbf_cistrncmp (c+quote, "7bit", 4) == 0 ||
00838               cbf_cistrncmp (c+quote, "8bit", 4) == 0)
00839               
00840             if (isspace (c [4]) || c [4] == '(' || (quote && c [16] == '\"')) {
00841 
00842               failure = 0;
00843               
00844               *encoding = ENC_NONE;
00845             }
00846 
00847           if (cbf_cistrncmp (c+quote, "Binary", 6) == 0)
00848               
00849             if (isspace (c [6]) || c [6] == '(' || (quote && c [16] == '\"')) {
00850 
00851               failure = 0;
00852               
00853               *encoding = ENC_NONE;
00854             }
00855         }
00856 
00857         if (failure) return CBF_FORMAT;
00858         
00859         break;
00860           
00861       case 2:
00862           
00863           /* Binary size */
00864             
00865         if (size)
00866           
00867           *size = atol (c);
00868             
00869         break;
00870           
00871       case 3:
00872 
00873           /* Binary ID */
00874           
00875         if (id)
00876 
00877           *id = atol (c);
00878               
00879         break;
00880             
00881       case 4:
00882           
00883           /* Binary element type (signed/unsigned ?-bit integer) */
00884 
00885         failure = 3;
00886 
00887         while (*c)
00888         {
00889           quote = 0;
00890 
00891           cbf_failnez (cbf_skip_whitespace (file, &line, &c, 
00892                                                   &fresh_line))
00893           if (*c == '\"') {
00894 
00895             if (quote) break;
00896 
00897             c++;
00898 
00899             quote++;
00900           }
00901           
00902           if (failure == 3) {
00903 
00904             if (cbf_cistrncmp (c, "signed", 6) == 0)
00905             {
00906               c += 6;
00907             
00908               if (sign) *sign = 1;
00909 
00910               failure --;
00911             }
00912           
00913             if (cbf_cistrncmp (c, "unsigned", 8) == 0)
00914             {
00915               c += 8;
00916               
00917               if (sign) *sign = 0;
00918 
00919               failure --;
00920             }
00921           }
00922           
00923           if (failure == 2) {
00924 
00925             count = 0;
00926             
00927             sscanf (c, "%d-%n", &text_bits, &count);
00928               
00929             if (cbf_cistrncmp (c+count, "bit", 3 ) == 0)
00930 
00931               if (count && text_bits > 0 && text_bits <= 64)
00932               {
00933                 c += count;
00934             
00935                 if (bits) *bits = text_bits;
00936 
00937                 failure --;
00938               }
00939           }
00940 
00941           if (failure == 1) {
00942 
00943             if (cbf_cistrncmp (c, "integer", 7 ) == 0) failure--;
00944 
00945           }
00946 
00947           if (*c)
00948           
00949             c++;
00950         }
00951         
00952         if (failure) return CBF_FORMAT;
00953  
00954         break;
00955           
00956       case 5:
00957 
00958           /* Message digest */
00959             
00960         if (digest)
00961         {
00962           strncpy (digest, c, 24);
00963               
00964           digest [24] = '\0';
00965         }
00966             
00967         break;
00968     }
00969   }
00970 
00971 
00972     /* Success */
00973     
00974   return 0;      
00975 }
00976 
00977 
00978 #ifdef __cplusplus
00979 
00980 }
00981 
00982 #endif