Update head to match stable 1.0
[gnupg.git] / g10 / plaintext.c
1 /* plaintext.c -  process plaintext packets
2  * Copyright (C) 1998, 1999, 2000, 2001, 2002 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 #ifdef HAVE_DOSISH_SYSTEM
28   #include <fcntl.h> /* for setmode() */
29 #endif
30
31 #include "util.h"
32 #include "memory.h"
33 #include "options.h"
34 #include "packet.h"
35 #include "ttyio.h"
36 #include "filter.h"
37 #include "main.h"
38 #include "status.h"
39 #include "i18n.h"
40
41
42
43 /****************
44  * Handle a plaintext packet.  If MFX is not NULL, update the MDs
45  * Note: we should use the filter stuff here, but we have to add some
46  *       easy mimic to set a read limit, so we calculate only the
47  *       bytes from the plaintext.
48  */
49 int
50 handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx,
51                   int nooutput, int clearsig )
52 {
53     char *fname = NULL;
54     FILE *fp = NULL;
55     int rc = 0;
56     int c;
57     int convert = pt->mode == 't';
58
59     /* create the filename as C string */
60     if( nooutput )
61         ;
62     else if( opt.outfile ) {
63         fname = m_alloc( strlen( opt.outfile ) + 1);
64         strcpy(fname, opt.outfile );
65     }
66     else if( pt->namelen == 8 && !memcmp( pt->name, "_CONSOLE", 8 ) ) {
67         log_info(_("data not saved; use option \"--output\" to save it\n"));
68         nooutput = 1;
69     }
70     else if( !opt.use_embedded_filename ) {
71         fname = make_outfile_name( iobuf_get_real_fname(pt->buf) );
72         if( !fname )
73             fname = ask_outfile_name( pt->name, pt->namelen );
74         if( !fname ) {
75             rc = G10ERR_CREATE_FILE;
76             goto leave;
77         }
78     }
79     else {
80         fname = make_printable_string( pt->name, pt->namelen, 0 );
81     }
82
83     if( nooutput )
84         ;
85     else if( !*fname || (*fname=='-' && !fname[1])) {
86         /* no filename or "-" given; write to stdout */
87         fp = stdout;
88       #ifdef HAVE_DOSISH_SYSTEM
89         setmode ( fileno(fp) , O_BINARY );
90       #endif
91     }
92     else {
93         while( !overwrite_filep (fname) ) {
94             char *tmp = ask_outfile_name (NULL, 0);
95             if ( !tmp || !*tmp ) {
96                 m_free (tmp);
97                 rc = G10ERR_CREATE_FILE;
98                 goto leave;
99             }
100             m_free (fname);
101             fname = tmp;
102         }
103     }
104
105     if( fp || nooutput )
106         ;
107     else if( !(fp = fopen(fname,"wb")) ) {
108         log_error(_("error creating `%s': %s\n"), fname, strerror(errno) );
109         rc = G10ERR_CREATE_FILE;
110 #ifdef __riscos__
111         if (errno == 106)
112             log_info("perhaps the output file has the same name as the input file?\n");
113 #endif /* __riscos__ */
114         goto leave;
115     }
116
117     if( !pt->is_partial ) {
118         /* we have an actual length (which might be zero). */
119         assert( !clearsig );
120         if( convert ) { /* text mode */
121             for( ; pt->len; pt->len-- ) {
122                 if( (c = iobuf_get(pt->buf)) == -1 ) {
123                     log_error("Problem reading source (%u bytes remaining)\n",
124                               (unsigned)pt->len);
125                     rc = G10ERR_READ_FILE;
126                     goto leave;
127                 }
128                 if( mfx->md )
129                     md_putc(mfx->md, c );
130               #ifndef HAVE_DOSISH_SYSTEM
131                 if( c == '\r' )  /* convert to native line ending */
132                     continue;    /* fixme: this hack might be too simple */
133               #endif
134                 if( fp ) {
135                     if( putc( c, fp ) == EOF ) {
136                         log_error("Error writing to `%s': %s\n",
137                                   fname, strerror(errno) );
138                         rc = G10ERR_WRITE_FILE;
139                         goto leave;
140                     }
141                 }
142             }
143         }
144         else { /* binary mode */
145             byte *buffer = m_alloc( 32768 );
146             while( pt->len ) {
147                 int len = pt->len > 32768 ? 32768 : pt->len;
148                 len = iobuf_read( pt->buf, buffer, len );
149                 if( len == -1 ) {
150                     log_error("Problem reading source (%u bytes remaining)\n",
151                               (unsigned)pt->len);
152                     rc = G10ERR_READ_FILE;
153                     m_free( buffer );
154                     goto leave;
155                 }
156                 if( mfx->md )
157                     md_write( mfx->md, buffer, len );
158                 if( fp ) {
159                     if( fwrite( buffer, 1, len, fp ) != len ) {
160                         log_error("Error writing to `%s': %s\n",
161                                   fname, strerror(errno) );
162                         rc = G10ERR_WRITE_FILE;
163                         m_free( buffer );
164                         goto leave;
165                     }
166                 }
167                 pt->len -= len;
168             }
169             m_free( buffer );
170         }
171     }
172     else if( !clearsig ) {
173         if( convert ) { /* text mode */
174             while( (c = iobuf_get(pt->buf)) != -1 ) {
175                 if( mfx->md )
176                     md_putc(mfx->md, c );
177               #ifndef HAVE_DOSISH_SYSTEM
178                 if( convert && c == '\r' )
179                     continue; /* fixme: this hack might be too simple */
180               #endif
181                 if( fp ) {
182                     if( putc( c, fp ) == EOF ) {
183                         log_error("Error writing to `%s': %s\n",
184                                   fname, strerror(errno) );
185                         rc = G10ERR_WRITE_FILE;
186                         goto leave;
187                     }
188                 }
189             }
190         }
191         else { /* binary mode */
192             byte *buffer = m_alloc( 32768 );
193             int eof;
194             for( eof=0; !eof; ) {
195                 /* Why do we check for len < 32768:
196                  * If we won't, we would practically read 2 EOFs but
197                  * the first one has already popped the block_filter
198                  * off and therefore we don't catch the boundary.
199                  * So, always assume EOF if iobuf_read returns less bytes
200                  * then requested */
201                 int len = iobuf_read( pt->buf, buffer, 32768 );
202                 if( len == -1 )
203                     break;
204                 if( len < 32768 )
205                     eof = 1;
206                 if( mfx->md )
207                     md_write( mfx->md, buffer, len );
208                 if( fp ) {
209                     if( fwrite( buffer, 1, len, fp ) != len ) {
210                         log_error("Error writing to `%s': %s\n",
211                                   fname, strerror(errno) );
212                         rc = G10ERR_WRITE_FILE;
213                         m_free( buffer );
214                         goto leave;
215                     }
216                 }
217             }
218             m_free( buffer );
219         }
220         pt->buf = NULL;
221     }
222     else {  /* clear text signature - don't hash the last cr,lf  */
223         int state = 0;
224
225         while( (c = iobuf_get(pt->buf)) != -1 ) {
226             if( fp ) {
227                 if( putc( c, fp ) == EOF ) {
228                     log_error("Error writing to `%s': %s\n",
229                                                 fname, strerror(errno) );
230                     rc = G10ERR_WRITE_FILE;
231                     goto leave;
232                 }
233             }
234             if( !mfx->md )
235                 continue;
236             if( state == 2 ) {
237                 md_putc(mfx->md, '\r' );
238                 md_putc(mfx->md, '\n' );
239                 state = 0;
240             }
241             if( !state ) {
242                 if( c == '\r'  )
243                     state = 1;
244                 else if( c == '\n'  )
245                     state = 2;
246                 else
247                     md_putc(mfx->md, c );
248             }
249             else if( state == 1 ) {
250                 if( c == '\n'  )
251                     state = 2;
252                 else {
253                     md_putc(mfx->md, '\r' );
254                     if( c == '\r'  )
255                         state = 1;
256                     else {
257                         state = 0;
258                         md_putc(mfx->md, c );
259                     }
260                 }
261             }
262         }
263         pt->buf = NULL;
264     }
265
266     if( fp && fp != stdout && fclose(fp) ) {
267         log_error("Error closing `%s': %s\n", fname, strerror(errno) );
268         fp = NULL;
269         rc = G10ERR_WRITE_FILE;
270         goto leave;
271     }
272     fp = NULL;
273
274   leave:
275     if( fp && fp != stdout )
276         fclose(fp);
277     m_free(fname);
278     return rc;
279 }
280
281 static void
282 do_hash( MD_HANDLE md, MD_HANDLE md2, IOBUF fp, int textmode )
283 {
284     text_filter_context_t tfx;
285     int c;
286
287     if( textmode ) {
288         memset( &tfx, 0, sizeof tfx);
289         iobuf_push_filter( fp, text_filter, &tfx );
290     }
291     if( md2 ) { /* work around a strange behaviour in pgp2 */
292         /* It seems that at least PGP5 converts a single CR to a CR,LF too */
293         int lc = -1;
294         while( (c = iobuf_get(fp)) != -1 ) {
295             if( c == '\n' && lc == '\r' )
296                 md_putc(md2, c);
297             else if( c == '\n' ) {
298                 md_putc(md2, '\r');
299                 md_putc(md2, c);
300             }
301             else if( c != '\n' && lc == '\r' ) {
302                 md_putc(md2, '\n');
303                 md_putc(md2, c);
304             }
305             else
306                 md_putc(md2, c);
307
308             if( md )
309                 md_putc(md, c );
310             lc = c;
311         }
312     }
313     else {
314         while( (c = iobuf_get(fp)) != -1 ) {
315             if( md )
316                 md_putc(md, c );
317         }
318     }
319 }
320
321
322 /****************
323  * Ask for the detached datafile and calculate the digest from it.
324  * INFILE is the name of the input file.
325  */
326 int
327 ask_for_detached_datafile( MD_HANDLE md, MD_HANDLE md2,
328                            const char *inname, int textmode )
329 {
330     char *answer = NULL;
331     IOBUF fp;
332     int rc = 0;
333
334     fp = open_sigfile( inname ); /* open default file */
335     if( !fp && !opt.batch ) {
336         int any=0;
337         tty_printf(_("Detached signature.\n"));
338         do {
339             m_free(answer);
340             answer = cpr_get("detached_signature.filename",
341                            _("Please enter name of data file: "));
342             cpr_kill_prompt();
343             if( any && !*answer ) {
344                 rc = G10ERR_READ_FILE;
345                 goto leave;
346             }
347             fp = iobuf_open(answer);
348             if( !fp && errno == ENOENT ) {
349                 tty_printf("No such file, try again or hit enter to quit.\n");
350                 any++;
351             }
352             else if( !fp ) {
353                 log_error("can't open `%s': %s\n", answer, strerror(errno) );
354                 rc = G10ERR_READ_FILE;
355                 goto leave;
356             }
357         } while( !fp );
358     }
359
360     if( !fp ) {
361         if( opt.verbose )
362             log_info(_("reading stdin ...\n"));
363         fp = iobuf_open( NULL );
364         assert(fp);
365     }
366     do_hash( md, md2, fp, textmode );
367     iobuf_close(fp);
368
369
370   leave:
371     m_free(answer);
372     return rc;
373 }
374
375
376
377 /****************
378  * Hash the given files and append the hash to hash context md.
379  * If FILES is NULL, hash stdin.
380  */
381 int
382 hash_datafiles( MD_HANDLE md, MD_HANDLE md2, STRLIST files,
383                 const char *sigfilename, int textmode )
384 {
385     IOBUF fp;
386     STRLIST sl;
387
388     if( !files ) {
389         /* check whether we can open the signed material */
390         fp = open_sigfile( sigfilename );
391         if( fp ) {
392             do_hash( md, md2, fp, textmode );
393             iobuf_close(fp);
394             return 0;
395         }
396         log_error (_("no signed data\n"));
397         return G10ERR_OPEN_FILE;
398     }
399
400
401     for (sl=files; sl; sl = sl->next ) {
402         fp = iobuf_open( sl->d );
403         if( !fp ) {
404             log_error(_("can't open signed data `%s'\n"),
405                                                 print_fname_stdin(sl->d));
406             return G10ERR_OPEN_FILE;
407         }
408         do_hash( md, md2, fp, textmode );
409         iobuf_close(fp);
410     }
411
412     return 0;
413 }
414
415
416
417
418