* g10.c (main): Alias --charset as --display-charset to help avoid the
[gnupg.git] / g10 / plaintext.c
1 /* plaintext.c -  process plaintext packets
2  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003,
3  *               2004 Free Software Foundation, Inc.
4  *
5  * This file is part of GnuPG.
6  *
7  * GnuPG is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * GnuPG is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20  */
21
22 #include <config.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <errno.h>
27 #include <assert.h>
28 #include <sys/types.h>
29 #ifdef HAVE_DOSISH_SYSTEM
30 #include <fcntl.h> /* for setmode() */
31 #endif
32
33 #include "util.h"
34 #include "memory.h"
35 #include "options.h"
36 #include "packet.h"
37 #include "ttyio.h"
38 #include "filter.h"
39 #include "main.h"
40 #include "status.h"
41 #include "i18n.h"
42
43
44 /****************
45  * Handle a plaintext packet.  If MFX is not NULL, update the MDs
46  * Note: we should use the filter stuff here, but we have to add some
47  *       easy mimic to set a read limit, so we calculate only the
48  *       bytes from the plaintext.
49  */
50 int
51 handle_plaintext( PKT_plaintext *pt, md_filter_context_t *mfx,
52                   int nooutput, int clearsig )
53 {
54     char *fname = NULL;
55     FILE *fp = NULL;
56     static off_t count=0;
57     int rc = 0;
58     int c;
59     int convert = (pt->mode == 't' || pt->mode == 'u');
60 #ifdef __riscos__
61     int filetype = 0xfff;
62 #endif
63
64     /* Let people know what the plaintext info is. This allows the
65        receiving program to try and do something different based on
66        the format code (say, recode UTF-8 to local). */
67     if(!nooutput && is_status_enabled())
68       {
69         char status[20];
70
71         sprintf(status,"%X %lu ",(byte)pt->mode,(ulong)pt->timestamp);
72         write_status_text_and_buffer(STATUS_PLAINTEXT,
73                                      status,pt->name,pt->namelen,0);
74
75         if(!pt->is_partial)
76           {
77             sprintf(status,"%lu",(ulong)pt->len);
78             write_status_text(STATUS_PLAINTEXT_LENGTH,status);
79           }
80       }
81
82     /* create the filename as C string */
83     if( nooutput )
84         ;
85     else if( opt.outfile ) {
86         fname = m_alloc( strlen( opt.outfile ) + 1);
87         strcpy(fname, opt.outfile );
88     }
89     else if( pt->namelen == 8 && !memcmp( pt->name, "_CONSOLE", 8 ) ) {
90         log_info(_("data not saved; use option \"--output\" to save it\n"));
91         nooutput = 1;
92     }
93     else if( !opt.use_embedded_filename ) {
94         fname = make_outfile_name( iobuf_get_real_fname(pt->buf) );
95         if( !fname )
96             fname = ask_outfile_name( pt->name, pt->namelen );
97         if( !fname ) {
98             rc = G10ERR_CREATE_FILE;
99             goto leave;
100         }
101     }
102     else {
103         fname = make_printable_string( pt->name, pt->namelen, 0 );
104     }
105
106     if( nooutput )
107         ;
108     else if( !*fname || (*fname=='-' && !fname[1])) {
109         /* no filename or "-" given; write to stdout */
110         fp = stdout;
111 #ifdef HAVE_DOSISH_SYSTEM
112         setmode ( fileno(fp) , O_BINARY );
113 #endif
114     }
115     else {
116         while( !overwrite_filep (fname) ) {
117             char *tmp = ask_outfile_name (NULL, 0);
118             if ( !tmp || !*tmp ) {
119                 m_free (tmp);
120                 rc = G10ERR_CREATE_FILE;
121                 goto leave;
122             }
123             m_free (fname);
124             fname = tmp;
125         }
126     }
127
128 #ifndef __riscos__
129     if( fp || nooutput )
130         ;
131     else if( !(fp = fopen(fname,"wb")) ) {
132         log_error(_("error creating `%s': %s\n"), fname, strerror(errno) );
133         rc = G10ERR_CREATE_FILE;
134         goto leave;
135     }
136 #else /* __riscos__ */
137     /* If no output filename was given, i.e. we constructed it,
138        convert all '.' in fname to '/' but not vice versa as
139        we don't create directories! */
140     if( !opt.outfile )
141         for( c=0; fname[c]; ++c )
142             if( fname[c] == '.' )
143                 fname[c] = '/';
144
145     if( fp || nooutput )
146         ;
147     else {
148         fp = fopen(fname,"wb");
149         if( !fp ) {
150             log_error(_("error creating `%s': %s\n"), fname, strerror(errno) );
151             rc = G10ERR_CREATE_FILE;
152             if (errno == 106)
153                 log_info("Do output file and input file have the same name?\n");
154             goto leave;
155         }
156
157         /* If there's a ,xxx extension in the embedded filename,
158            use that, else check whether the user input (in fname)
159            has a ,xxx appended, then use that in preference */
160         if( (c = riscos_get_filetype_from_string( pt->name,
161                                                   pt->namelen )) != -1 )
162             filetype = c;
163         if( (c = riscos_get_filetype_from_string( fname,
164                                                   strlen(fname) )) != -1 )
165             filetype = c;
166         riscos_set_filetype_by_number(fname, filetype);
167     }
168 #endif /* __riscos__ */
169
170     if( !pt->is_partial ) {
171         /* we have an actual length (which might be zero). */
172         assert( !clearsig );
173         if( convert ) { /* text mode */
174             for( ; pt->len; pt->len-- ) {
175                 if( (c = iobuf_get(pt->buf)) == -1 ) {
176                     log_error("Problem reading source (%u bytes remaining)\n",
177                               (unsigned)pt->len);
178                     rc = G10ERR_READ_FILE;
179                     goto leave;
180                 }
181                 if( mfx->md )
182                     md_putc(mfx->md, c );
183 #ifndef HAVE_DOSISH_SYSTEM
184                 if( c == '\r' )  /* convert to native line ending */
185                     continue;    /* fixme: this hack might be too simple */
186 #endif
187                 if( fp )
188                   {
189                     if(opt.max_output && (++count)>opt.max_output)
190                       {
191                         log_error("Error writing to `%s': %s\n",
192                                   fname,"exceeded --max-output limit\n");
193                         rc = G10ERR_WRITE_FILE;
194                         goto leave;
195                       }
196                     else if( putc( c, fp ) == EOF )
197                       {
198                         log_error("Error writing to `%s': %s\n",
199                                   fname, strerror(errno) );
200                         rc = G10ERR_WRITE_FILE;
201                         goto leave;
202                       }
203                   }
204             }
205         }
206         else { /* binary mode */
207             byte *buffer = m_alloc( 32768 );
208             while( pt->len ) {
209                 int len = pt->len > 32768 ? 32768 : pt->len;
210                 len = iobuf_read( pt->buf, buffer, len );
211                 if( len == -1 ) {
212                     log_error("Problem reading source (%u bytes remaining)\n",
213                               (unsigned)pt->len);
214                     rc = G10ERR_READ_FILE;
215                     m_free( buffer );
216                     goto leave;
217                 }
218                 if( mfx->md )
219                     md_write( mfx->md, buffer, len );
220                 if( fp )
221                   {
222                     if(opt.max_output && (count+=len)>opt.max_output)
223                       {
224                         log_error("Error writing to `%s': %s\n",
225                                   fname,"exceeded --max-output limit\n");
226                         rc = G10ERR_WRITE_FILE;
227                         m_free( buffer );
228                         goto leave;
229                       }
230                     else if( fwrite( buffer, 1, len, fp ) != len )
231                       {
232                         log_error("Error writing to `%s': %s\n",
233                                   fname, strerror(errno) );
234                         rc = G10ERR_WRITE_FILE;
235                         m_free( buffer );
236                         goto leave;
237                       }
238                   }
239                 pt->len -= len;
240             }
241             m_free( buffer );
242         }
243     }
244     else if( !clearsig ) {
245         if( convert ) { /* text mode */
246             while( (c = iobuf_get(pt->buf)) != -1 ) {
247                 if( mfx->md )
248                     md_putc(mfx->md, c );
249 #ifndef HAVE_DOSISH_SYSTEM
250                 if( convert && c == '\r' )
251                     continue; /* fixme: this hack might be too simple */
252 #endif
253                 if( fp )
254                   {
255                     if(opt.max_output && (++count)>opt.max_output)
256                       {
257                         log_error("Error writing to `%s': %s\n",
258                                   fname,"exceeded --max-output limit\n");
259                         rc = G10ERR_WRITE_FILE;
260                         goto leave;
261                       }
262                     else if( putc( c, fp ) == EOF )
263                       {
264                         log_error("Error writing to `%s': %s\n",
265                                   fname, strerror(errno) );
266                         rc = G10ERR_WRITE_FILE;
267                         goto leave;
268                       }
269                   }
270             }
271         }
272         else { /* binary mode */
273             byte *buffer = m_alloc( 32768 );
274             int eof;
275             for( eof=0; !eof; ) {
276                 /* Why do we check for len < 32768:
277                  * If we won't, we would practically read 2 EOFs but
278                  * the first one has already popped the block_filter
279                  * off and therefore we don't catch the boundary.
280                  * So, always assume EOF if iobuf_read returns less bytes
281                  * then requested */
282                 int len = iobuf_read( pt->buf, buffer, 32768 );
283                 if( len == -1 )
284                     break;
285                 if( len < 32768 )
286                     eof = 1;
287                 if( mfx->md )
288                     md_write( mfx->md, buffer, len );
289                 if( fp )
290                   {
291                     if(opt.max_output && (count+=len)>opt.max_output)
292                       {
293                         log_error("Error writing to `%s': %s\n",
294                                   fname,"exceeded --max-output limit\n");
295                         rc = G10ERR_WRITE_FILE;
296                         m_free( buffer );
297                         goto leave;
298                       }
299                     else if( fwrite( buffer, 1, len, fp ) != len ) {
300                       log_error("Error writing to `%s': %s\n",
301                                 fname, strerror(errno) );
302                       rc = G10ERR_WRITE_FILE;
303                       m_free( buffer );
304                       goto leave;
305                     }
306                   }
307             }
308             m_free( buffer );
309         }
310         pt->buf = NULL;
311     }
312     else {  /* clear text signature - don't hash the last cr,lf  */
313         int state = 0;
314
315         while( (c = iobuf_get(pt->buf)) != -1 ) {
316             if( fp )
317               {
318                 if(opt.max_output && (++count)>opt.max_output)
319                   {
320                     log_error("Error writing to `%s': %s\n",
321                               fname,"exceeded --max-output limit\n");
322                     rc = G10ERR_WRITE_FILE;
323                     goto leave;
324                   }
325                 else if( putc( c, fp ) == EOF )
326                   {
327                     log_error("Error writing to `%s': %s\n",
328                               fname, strerror(errno) );
329                     rc = G10ERR_WRITE_FILE;
330                     goto leave;
331                   }
332               }
333             if( !mfx->md )
334                 continue;
335             if( state == 2 ) {
336                 md_putc(mfx->md, '\r' );
337                 md_putc(mfx->md, '\n' );
338                 state = 0;
339             }
340             if( !state ) {
341                 if( c == '\r'  )
342                     state = 1;
343                 else if( c == '\n'  )
344                     state = 2;
345                 else
346                     md_putc(mfx->md, c );
347             }
348             else if( state == 1 ) {
349                 if( c == '\n'  )
350                     state = 2;
351                 else {
352                     md_putc(mfx->md, '\r' );
353                     if( c == '\r'  )
354                         state = 1;
355                     else {
356                         state = 0;
357                         md_putc(mfx->md, c );
358                     }
359                 }
360             }
361         }
362         pt->buf = NULL;
363     }
364
365     if( fp && fp != stdout && fclose(fp) ) {
366         log_error("Error closing `%s': %s\n", fname, strerror(errno) );
367         fp = NULL;
368         rc = G10ERR_WRITE_FILE;
369         goto leave;
370     }
371     fp = NULL;
372
373   leave:
374     if( fp && fp != stdout )
375         fclose(fp);
376     m_free(fname);
377     return rc;
378 }
379
380 static void
381 do_hash( MD_HANDLE md, MD_HANDLE md2, IOBUF fp, int textmode )
382 {
383     text_filter_context_t tfx;
384     int c;
385
386     if( textmode ) {
387         memset( &tfx, 0, sizeof tfx);
388         iobuf_push_filter( fp, text_filter, &tfx );
389     }
390     if( md2 ) { /* work around a strange behaviour in pgp2 */
391         /* It seems that at least PGP5 converts a single CR to a CR,LF too */
392         int lc = -1;
393         while( (c = iobuf_get(fp)) != -1 ) {
394             if( c == '\n' && lc == '\r' )
395                 md_putc(md2, c);
396             else if( c == '\n' ) {
397                 md_putc(md2, '\r');
398                 md_putc(md2, c);
399             }
400             else if( c != '\n' && lc == '\r' ) {
401                 md_putc(md2, '\n');
402                 md_putc(md2, c);
403             }
404             else
405                 md_putc(md2, c);
406
407             if( md )
408                 md_putc(md, c );
409             lc = c;
410         }
411     }
412     else {
413         while( (c = iobuf_get(fp)) != -1 ) {
414             if( md )
415                 md_putc(md, c );
416         }
417     }
418 }
419
420
421 /****************
422  * Ask for the detached datafile and calculate the digest from it.
423  * INFILE is the name of the input file.
424  */
425 int
426 ask_for_detached_datafile( MD_HANDLE md, MD_HANDLE md2,
427                            const char *inname, int textmode )
428 {
429     progress_filter_context_t pfx;
430     char *answer = NULL;
431     IOBUF fp;
432     int rc = 0;
433
434     fp = open_sigfile( inname, &pfx ); /* open default file */
435
436     if( !fp && !opt.batch ) {
437         int any=0;
438         tty_printf(_("Detached signature.\n"));
439         do {
440             m_free(answer);
441             answer = cpr_get("detached_signature.filename",
442                            _("Please enter name of data file: "));
443             cpr_kill_prompt();
444             if( any && !*answer ) {
445                 rc = G10ERR_READ_FILE;
446                 goto leave;
447             }
448             fp = iobuf_open(answer);
449             if( !fp && errno == ENOENT ) {
450                 tty_printf("No such file, try again or hit enter to quit.\n");
451                 any++;
452             }
453             else if( !fp ) {
454                 log_error("can't open `%s': %s\n", answer, strerror(errno) );
455                 rc = G10ERR_READ_FILE;
456                 goto leave;
457             }
458         } while( !fp );
459     }
460
461     if( !fp ) {
462         if( opt.verbose )
463             log_info(_("reading stdin ...\n"));
464         fp = iobuf_open( NULL );
465         assert(fp);
466     }
467     do_hash( md, md2, fp, textmode );
468     iobuf_close(fp);
469
470   leave:
471     m_free(answer);
472     return rc;
473 }
474
475
476
477 /****************
478  * Hash the given files and append the hash to hash context md.
479  * If FILES is NULL, hash stdin.
480  */
481 int
482 hash_datafiles( MD_HANDLE md, MD_HANDLE md2, STRLIST files,
483                 const char *sigfilename, int textmode )
484 {
485     progress_filter_context_t pfx;
486     IOBUF fp;
487     STRLIST sl;
488
489     if( !files ) {
490         /* check whether we can open the signed material */
491         fp = open_sigfile( sigfilename, &pfx );
492         if( fp ) {
493             do_hash( md, md2, fp, textmode );
494             iobuf_close(fp);
495             return 0;
496         }
497         log_error (_("no signed data\n"));
498         return G10ERR_OPEN_FILE;
499     }
500
501
502     for (sl=files; sl; sl = sl->next ) {
503         fp = iobuf_open( sl->d );
504         if( !fp ) {
505             log_error(_("can't open signed data `%s'\n"),
506                                                 print_fname_stdin(sl->d));
507             return G10ERR_OPEN_FILE;
508         }
509         handle_progress (&pfx, fp, sl->d);
510         do_hash( md, md2, fp, textmode );
511         iobuf_close(fp);
512     }
513
514     return 0;
515 }