edit-key is now complete
[gnupg.git] / g10 / textfilter.c
1 /* textfilter.c
2  *      Copyright (C) 1998 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 2 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, 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         if( !n || buf[n-1] != '\n' )
57             no_lf = 1;
58     }
59     else if( c != '\n' ) {
60         IOBUF b = iobuf_temp();
61         while( (c=iobuf_get2(a)) != -1 && c != '\n' ) {
62             iobuf_put(b,c);
63             if( c != ' ' && c != '\t' && c != '\r' )
64                 break;
65         }
66         if( c == '\n' ) { /* okay we can skip the rest of the line */
67             iobuf_close(b);
68         }
69         else {
70             iobuf_unget_and_close_temp(a,b);
71             no_lf = 1;
72         }
73     }
74
75     if( !no_lf ) {
76         /* append CR,LF after removing trailing wspaces */
77         for(p=buf+n-1; n; n--, p-- ) {
78             assert( *p != '\n' );
79             if( *p != ' ' && *p != '\t' && *p != '\r' ) {
80                 p[1] = '\r';
81                 p[2] = '\n';
82                 n += 2;
83                 break;
84             }
85         }
86         if( !n ) {
87             buf[0] = '\r';
88             buf[1] = '\n';
89             n = 2;
90         }
91     }
92
93
94     *r_buflen = n;
95     return rc;
96 }
97
98
99
100
101 /****************
102  * The filter is used to make canonical text: Lines are terminated by
103  * CR, LF, trailing white spaces are removed.
104  */
105 int
106 text_filter( void *opaque, int control,
107              IOBUF a, byte *buf, size_t *ret_len)
108 {
109     size_t size = *ret_len;
110     text_filter_context_t *tfx = opaque;
111     int rc=0;
112     size_t len, n, nn;
113
114     if( control == IOBUFCTRL_UNDERFLOW ) {
115         assert( size > 30 );
116         len = 0;
117         while( !rc && len < size ) {
118             if( tfx->idx < tfx->len ) { /* flush the last buffer */
119                 n = tfx->len;
120                 for(nn=tfx->idx; len < size && nn < n ; nn++ )
121                     buf[len++] = tfx->buf[nn];
122                 tfx->idx = nn;
123                 continue;
124             }
125             if( tfx->eof ) {
126                 rc = -1;
127                 continue;
128             }
129             n = DIM(tfx->buf);
130             tfx->idx = 0;
131             if( read_line( tfx->buf, &n, a ) == -1 )
132                 tfx->eof = 1;
133             tfx->len = n;
134         }
135         *ret_len = len;
136     }
137     else if( control == IOBUFCTRL_DESC )
138         *(char**)buf = "text_filter";
139     return rc;
140 }
141
142
143