LCOV - code coverage report
Current view: top level - g10 - textfilter.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 75 83 90.4 %
Date: 2015-11-05 17:10:59 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /* textfilter.c
       2             :  * Copyright (C) 1998, 1999, 2000, 2001, 2004 Free Software Foundation, Inc.
       3             :  *
       4             :  * This file is part of GnuPG.
       5             :  *
       6             :  * GnuPG is free software; you can redistribute it and/or modify
       7             :  * it under the terms of the GNU General Public License as published by
       8             :  * the Free Software Foundation; either version 3 of the License, or
       9             :  * (at your option) any later version.
      10             :  *
      11             :  * GnuPG is distributed in the hope that it will be useful,
      12             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :  * GNU General Public License for more details.
      15             :  *
      16             :  * You should have received a copy of the GNU General Public License
      17             :  * along with this program; if not, see <http://www.gnu.org/licenses/>.
      18             :  */
      19             : 
      20             : #include <config.h>
      21             : #include <stdio.h>
      22             : #include <stdlib.h>
      23             : #include <string.h>
      24             : #include <errno.h>
      25             : #include <assert.h>
      26             : 
      27             : #include "gpg.h"
      28             : #include "status.h"
      29             : #include "iobuf.h"
      30             : #include "util.h"
      31             : #include "filter.h"
      32             : #include "i18n.h"
      33             : #include "options.h"
      34             : #include "status.h"
      35             : 
      36             : #ifdef HAVE_DOSISH_SYSTEM
      37             : #define LF "\r\n"
      38             : #else
      39             : #define LF "\n"
      40             : #endif
      41             : 
      42             : #define MAX_LINELEN 19995 /* a little bit smaller than in armor.c */
      43             :                           /* to make sure that a warning is displayed while */
      44             :                           /* creating a message */
      45             : 
      46             : static unsigned
      47        5228 : len_without_trailing_chars( byte *line, unsigned len, const char *trimchars )
      48             : {
      49             :     byte *p, *mark;
      50             :     unsigned n;
      51             : 
      52      208143 :     for(mark=NULL, p=line, n=0; n < len; n++, p++ ) {
      53      202915 :         if( strchr( trimchars, *p ) ) {
      54       38632 :             if( !mark )
      55       32726 :                 mark = p;
      56             :         }
      57             :         else
      58      164283 :             mark = NULL;
      59             :     }
      60             : 
      61        5228 :     return mark? (mark - line) : len;
      62             : }
      63             : 
      64             : 
      65             : static int
      66           6 : standard( text_filter_context_t *tfx, IOBUF a,
      67             :           byte *buf, size_t size, size_t *ret_len)
      68             : {
      69           6 :     int rc=0;
      70           6 :     size_t len = 0;
      71             :     unsigned maxlen;
      72             : 
      73           6 :     assert( size > 10 );
      74           6 :     size -= 2;  /* reserve 2 bytes to append CR,LF */
      75          85 :     while( !rc && len < size ) {
      76             :         int lf_seen;
      77             : 
      78        2940 :         while( len < size && tfx->buffer_pos < tfx->buffer_len )
      79        2782 :             buf[len++] = tfx->buffer[tfx->buffer_pos++];
      80          79 :         if( len >= size )
      81           0 :             continue;
      82             : 
      83             :         /* read the next line */
      84          79 :         maxlen = MAX_LINELEN;
      85          79 :         tfx->buffer_pos = 0;
      86          79 :         tfx->buffer_len = iobuf_read_line( a, &tfx->buffer,
      87             :                                            &tfx->buffer_size, &maxlen );
      88          79 :         if( !maxlen )
      89           0 :             tfx->truncated++;
      90          79 :         if( !tfx->buffer_len ) {
      91           6 :             if( !len )
      92           3 :                 rc = -1; /* eof */
      93           6 :             break;
      94             :         }
      95          73 :         lf_seen = tfx->buffer[tfx->buffer_len-1] == '\n';
      96             : 
      97             :         /* The story behind this is that 2440 says that textmode
      98             :            hashes should canonicalize line endings to CRLF and remove
      99             :            spaces and tabs.  2440bis-12 says to just canonicalize to
     100             :            CRLF.  1.4.0 was released using the bis-12 behavior, but it
     101             :            was discovered that many mail clients do not canonicalize
     102             :            PGP/MIME signature text appropriately (and were relying on
     103             :            GnuPG to handle trailing spaces).  So, we default to the
     104             :            2440 behavior, but use the 2440bis-12 behavior if the user
     105             :            specifies --no-rfc2440-text.  The default will be changed
     106             :            at some point in the future when the mail clients have been
     107             :            upgraded.  Aside from PGP/MIME and broken mail clients,
     108             :            this makes no difference to any signatures in the real
     109             :            world except for a textmode detached signature.  PGP always
     110             :            used the 2440bis-12 behavior (ignoring 2440 itself), so
     111             :            this actually makes us compatible with PGP textmode
     112             :            detached signatures for the first time. */
     113          73 :         if(opt.rfc2440_text)
     114           0 :           tfx->buffer_len=trim_trailing_chars(tfx->buffer,tfx->buffer_len,
     115             :                                               " \t\r\n");
     116             :         else
     117          73 :           tfx->buffer_len=trim_trailing_chars(tfx->buffer,tfx->buffer_len,
     118             :                                               "\r\n");
     119             : 
     120          73 :         if( lf_seen ) {
     121          72 :             tfx->buffer[tfx->buffer_len++] = '\r';
     122          72 :             tfx->buffer[tfx->buffer_len++] = '\n';
     123             :         }
     124             :     }
     125           6 :     *ret_len = len;
     126           6 :     return rc;
     127             : }
     128             : 
     129             : 
     130             : /****************
     131             :  * The filter is used to make canonical text: Lines are terminated by
     132             :  * CR, LF, trailing white spaces are removed.
     133             :  */
     134             : int
     135          12 : text_filter( void *opaque, int control,
     136             :              IOBUF a, byte *buf, size_t *ret_len)
     137             : {
     138          12 :     size_t size = *ret_len;
     139          12 :     text_filter_context_t *tfx = opaque;
     140          12 :     int rc=0;
     141             : 
     142          12 :     if( control == IOBUFCTRL_UNDERFLOW ) {
     143           6 :         rc = standard( tfx, a, buf, size, ret_len );
     144             :     }
     145           6 :     else if( control == IOBUFCTRL_FREE ) {
     146           3 :         if( tfx->truncated )
     147           0 :             log_error(_("can't handle text lines longer than %d characters\n"),
     148             :                         MAX_LINELEN );
     149           3 :         xfree( tfx->buffer );
     150           3 :         tfx->buffer = NULL;
     151             :     }
     152           3 :     else if( control == IOBUFCTRL_DESC )
     153           0 :         *(char**)buf = "text_filter";
     154          12 :     return rc;
     155             : }
     156             : 
     157             : 
     158             : /****************
     159             :  * Copy data from INP to OUT and do some escaping if requested.
     160             :  * md is updated as required by rfc2440
     161             :  */
     162             : int
     163          10 : copy_clearsig_text( IOBUF out, IOBUF inp, gcry_md_hd_t md,
     164             :                     int escape_dash, int escape_from)
     165             : {
     166             :     unsigned int maxlen;
     167          10 :     byte *buffer = NULL;    /* malloced buffer */
     168             :     unsigned int bufsize;   /* and size of this buffer */
     169             :     unsigned int n;
     170          10 :     int truncated = 0;
     171          10 :     int pending_lf = 0;
     172             : 
     173          10 :    if( !escape_dash )
     174           1 :         escape_from = 0;
     175             : 
     176          10 :     write_status_begin_signing (md);
     177             : 
     178             :     for(;;) {
     179        5249 :         maxlen = MAX_LINELEN;
     180        5249 :         n = iobuf_read_line( inp, &buffer, &bufsize, &maxlen );
     181        5249 :         if( !maxlen )
     182           0 :             truncated++;
     183             : 
     184        5249 :         if( !n )
     185          10 :             break; /* read_line has returned eof */
     186             : 
     187             :         /* update the message digest */
     188        5239 :         if( escape_dash ) {
     189        5228 :             if( pending_lf ) {
     190        5220 :                 gcry_md_putc ( md, '\r' );
     191        5220 :                 gcry_md_putc ( md, '\n' );
     192             :             }
     193        5228 :             gcry_md_write ( md, buffer,
     194        5228 :                             len_without_trailing_chars (buffer, n, " \t\r\n"));
     195             :         }
     196             :         else
     197          11 :             gcry_md_write ( md, buffer, n );
     198        5239 :         pending_lf = buffer[n-1] == '\n';
     199             : 
     200             :         /* write the output */
     201        5239 :         if(    ( escape_dash && *buffer == '-')
     202        5231 :             || ( escape_from && n > 4 && !memcmp(buffer, "From ", 5 ) ) ) {
     203           8 :             iobuf_put( out, '-' );
     204           8 :             iobuf_put( out, ' ' );
     205             :         }
     206             : 
     207             : #if  0 /*defined(HAVE_DOSISH_SYSTEM)*/
     208             :         /* We don't use this anymore because my interpretation of rfc2440 7.1
     209             :          * is that there is no conversion needed.  If one decides to
     210             :          * clearsign a unix file on a DOS box he will get a mixed line endings.
     211             :          * If at some point it turns out, that a conversion is a nice feature
     212             :          * we can make an option out of it.
     213             :          */
     214             :         /* make sure the lines do end in CR,LF */
     215             :         if( n > 1 && ( (buffer[n-2] == '\r' && buffer[n-1] == '\n' )
     216             :                             || (buffer[n-2] == '\n' && buffer[n-1] == '\r'))) {
     217             :             iobuf_write( out, buffer, n-2 );
     218             :             iobuf_put( out, '\r');
     219             :             iobuf_put( out, '\n');
     220             :         }
     221             :         else if( n && buffer[n-1] == '\n' ) {
     222             :             iobuf_write( out, buffer, n-1 );
     223             :             iobuf_put( out, '\r');
     224             :             iobuf_put( out, '\n');
     225             :         }
     226             :         else
     227             :             iobuf_write( out, buffer, n );
     228             : 
     229             : #else
     230        5239 :         iobuf_write( out, buffer, n );
     231             : #endif
     232        5239 :     }
     233             : 
     234             :     /* at eof */
     235          10 :     if( !pending_lf ) { /* make sure that the file ends with a LF */
     236           3 :         iobuf_writestr( out, LF );
     237           3 :         if( !escape_dash )
     238           0 :             gcry_md_putc( md, '\n' );
     239             :     }
     240             : 
     241          10 :     if( truncated )
     242           0 :         log_info(_("input line longer than %d characters\n"), MAX_LINELEN );
     243             : 
     244          10 :     return 0; /* okay */
     245             : }

Generated by: LCOV version 1.11