armor rewritten, but still buggy
[gnupg.git] / g10 / textfilter.c
1 /* textfilter.c
2  *      Copyright (c) 1997 by Werner Koch (dd9jn)
3  *
4  * This file is part of G10.
5  *
6  * G10 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 2 of the License, or
9  * (at your option) any later version.
10  *
11  * G10 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, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <assert.h>
27
28 #include "errors.h"
29 #include "iobuf.h"
30 #include "memory.h"
31 #include "util.h"
32 #include "filter.h"
33
34
35
36
37 static int
38 read_line( byte *buf, size_t *r_buflen, IOBUF a )
39 {
40     int c;
41     int rc = 0;
42     byte *p;
43     size_t buflen;
44     int no_lf=0;
45     size_t n;
46
47     buflen = *r_buflen;
48     assert(buflen >= 20 );
49     buflen -= 3; /* leave some room for CR,LF and one extra */
50
51     for(c=0, n=0; n < buflen && (c=iobuf_get2(a)) != -1 && c != '\n'; )
52         buf[n++] = c;
53     buf[n] = 0;
54     if( c == -1 )
55         rc = -1;
56     else if( c != '\n' ) {
57         IOBUF b = iobuf_temp();
58         while( (c=iobuf_get2(a)) != -1 && c != '\n' ) {
59             iobuf_put(b,c);
60             if( c != ' ' && c != '\t' && c != '\r' )
61                 break;
62         }
63         if( c == '\n' ) { /* okay we can skip the rest of the line */
64             iobuf_close(b);
65         }
66         else {
67             iobuf_unget_and_close_temp(a,b);
68             no_lf = 1;
69         }
70     }
71
72     if( !no_lf ) {
73         /* append CR,LF after removing trailing wspaces */
74         for(p=buf+n-1; n; n--, p-- ) {
75             assert( *p != '\n' );
76             if( *p != ' ' && *p != '\t' && *p != '\r' ) {
77                 p[1] = '\r';
78                 p[2] = '\n';
79                 n += 2;
80                 break;
81             }
82         }
83         if( !n ) {
84             buf[0] = '\r';
85             buf[1] = '\n';
86             n = 2;
87         }
88     }
89
90
91     *r_buflen = n;
92     return rc;
93 }
94
95
96
97
98 /****************
99  * The filter is used to make canonical text: Lines are terminated by
100  * CR, LF, trailing white spaces are removed.
101  */
102 int
103 text_filter( void *opaque, int control,
104              IOBUF a, byte *buf, size_t *ret_len)
105 {
106     size_t size = *ret_len;
107     text_filter_context_t *tfx = opaque;
108     int rc=0;
109     size_t len, n, nn;
110
111     if( control == IOBUFCTRL_UNDERFLOW ) {
112         assert( size > 30 );
113         len = 0;
114         while( !rc && len < size ) {
115             if( tfx->idx < tfx->len ) { /* flush the last buffer */
116                 n = tfx->len;
117                 for(nn=tfx->idx; len < size && nn < n ; nn++ )
118                     buf[len++] = tfx->buf[nn];
119                 tfx->idx = nn;
120                 continue;
121             }
122             if( tfx->eof ) {
123                 rc = -1;
124                 continue;
125             }
126             n = DIM(tfx->buf);
127             tfx->idx = 0;
128             if( read_line( tfx->buf, &n, a ) == -1 )
129                 tfx->eof = 1;
130             tfx->len = n;
131         }
132         *ret_len = len;
133     }
134     else if( control == IOBUFCTRL_DESC )
135         *(char**)buf = "text_filter";
136     return rc;
137 }
138
139
140