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

Generated by: LCOV version 1.11