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