/[winpt]/trunk/MyGPGME/data.c
ViewVC logotype

Contents of /trunk/MyGPGME/data.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 22 - (show annotations)
Wed Aug 10 11:33:35 2005 UTC (19 years, 6 months ago) by twoaday
File MIME type: text/plain
File size: 26631 byte(s)
2005-08-06  Timo Schulz  <twoaday@freakmail.de>
 
        * wptGPGME.cpp (keycache_update): Reload OpenPGP parts
        of the secret key.
        (keycache_init): cache name of secret keyring.
        * wptKeyList.cpp (keylist_upd_key): Do not add long keyid.
        (get_key_type): Do not assume 'ultimate' means key pair.
        * wptKeyEditDlgs.cpp (diff_time): New.
        (keyedit_addsubkey_dlg_proc): Changed design and use
        diff_time. Drop checks for invalid keylength (< 1024, > 4096)
        because the combo box automatically handles this.
        * wptKeyManager.cpp (km_set_implicit_trust): Return error code.
        * wptGPG.cpp (get_backup_name): New.
        (gnupg_backup_keyrings): Rotate backup names, from 0..3.
        * wptClipImportDialog.cpp (clip_import_dlg_proc): Free memory.
        * wptKeyManagerDlg.cpp (keymanager_dlg_proc): Use 0x short keyid and
        not the long keyid.


1 /* data.c
2 * Copyright (C) 2000-2003 Werner Koch (dd9jn), g10 Code GmbH
3 * Copyright (C) 2001-2004 Timo Schulz
4 *
5 * This file is part of MyGPGME.
6 *
7 * MyGPGME 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 * MyGPGME 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 <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <assert.h>
26 #include <errno.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
29 #include <process.h>
30 #include <io.h>
31 #include <windows.h>
32
33 #include "util.h"
34 #include "context.h"
35 #include "ops.h"
36
37 #define ALLOC_CHUNK 1024
38 #define MAX_FILESIZE 16777216
39
40 static char pgm_string[128] = "OpenPrivacy";
41
42
43 /**
44 * gpgme_data_new:
45 * @r_dh: returns the new data object
46 *
47 * Create a new data object without any content.
48 *
49 * Return value: An error value or 0 on success
50 **/
51 gpgme_error_t
52 gpgme_data_new (gpgme_data_t * r_dh)
53 {
54 gpgme_data_t dh;
55
56 if (!r_dh)
57 return mk_error (Invalid_Value);
58 *r_dh = NULL;
59 dh = calloc (1, sizeof *dh);
60 if (!dh)
61 return mk_error (Out_Of_Core);
62 dh->mode = GPGME_DATA_MODE_INOUT;
63 *r_dh = dh;
64 return 0;
65 } /* gpgme_data_new */
66
67
68 /**
69 * gpgme_data_new_from_mem:
70 * @r_dh: Returns a new data object.
71 * @buffer: Initialize with this.
72 * @size: Size of the buffer
73 * @copy: Flag wether a copy of the buffer should be used.
74 *
75 * Create a new data object and initialize with data
76 * from the memory. A @copy with value %TRUE creates a copy of the
77 * memory, a value of %FALSE uses the original memory of @buffer and the
78 * caller has to make sure that this buffer is valid until gpgme_release_data()
79 * is called.
80 *
81 * Return value:
82 **/
83 gpgme_error_t
84 gpgme_data_new_from_mem (gpgme_data_t * r_dh,
85 const char * buffer, size_t size, int copy)
86 {
87 gpgme_data_t dh;
88 gpgme_error_t err;
89 char * p;
90
91 if (!r_dh || !buffer)
92 return mk_error (Invalid_Value);
93 *r_dh = NULL;
94 err = gpgme_data_new (&dh);
95 if (err)
96 return err;
97 dh->len = size;
98 if (copy) {
99 p = dh->private_buffer = malloc (size? size : 1);
100 if (!p) {
101 gpgme_data_release (dh);
102 return mk_error (Out_Of_Core);
103 }
104 dh->private_len = size;
105 memcpy (dh->private_buffer, buffer, size);
106 dh->data = dh->private_buffer;
107 dh->writepos = size;
108 }
109 else
110 dh->data = buffer;
111 dh->type = GPGME_DATA_TYPE_MEM;
112 *r_dh = dh;
113 return 0;
114 }
115
116
117 gpgme_error_t
118 gpgme_data_new_with_read_cb (gpgme_data_t *r_dh,
119 int (*read_cb)(void*,char *,size_t,size_t*),
120 void *read_cb_value)
121 {
122 gpgme_data_t dh;
123 gpgme_error_t err;
124
125 if (!r_dh || !read_cb)
126 return mk_error (Invalid_Value);
127 *r_dh = NULL;
128 err = gpgme_data_new (&dh);
129 if (err)
130 return err;
131 dh->type = GPGME_DATA_TYPE_CB;
132 dh->mode = GPGME_DATA_MODE_OUT;
133 dh->read_cb = read_cb;
134 dh->read_cb_value = read_cb_value;
135
136 *r_dh = dh;
137 return 0;
138 }
139
140 /**
141 * gpgme_data_new_from_file:
142 * @r_dh: returns the new data object
143 * @fname: filename
144 *
145 * Create a new data object and initialize it with the content of
146 * the file @file. If @copy is %True the file is immediately read in
147 * adn closed. @copy of %False is not yet supportted.
148 *
149 * Return value: An error code or 0 on success. If the error code is
150 * %GPGME_File_Error, the OS error code is held in %errno.
151 **/
152 gpgme_error_t
153 gpgme_data_new_from_file (gpgme_data_t * r_dh, const char * fname)
154 {
155 gpgme_data_t dh;
156 gpgme_error_t err;
157 struct stat st;
158 FILE *fp;
159
160 if (!r_dh)
161 return mk_error (Invalid_Value);
162 *r_dh = NULL;
163 if (!fname)
164 return mk_error (Invalid_Value);
165
166 err = gpgme_data_new (&dh);
167 if (err)
168 return err;
169
170 fp = my_fopen (fname, "rb");
171 if (!fp) {
172 int save_errno = errno;
173 gpgme_data_release (dh);
174 errno = save_errno;
175 return mk_error (File_Error);
176 }
177
178 if (fstat (fileno (fp), &st)) {
179 int save_errno = errno;
180 fclose (fp);
181 gpgme_data_release (dh);
182 errno = save_errno;
183 return mk_error (File_Error);
184 }
185
186 /* Check to disallow to load large files */
187 if (st.st_size > MAX_FILESIZE) {
188 fclose (fp);
189 gpgme_data_release (dh);
190 return mk_error (General_Error);
191 }
192 dh->private_buffer = malloc (st.st_size? st.st_size : 1);
193 if (!dh->private_buffer) {
194 fclose (fp);
195 gpgme_data_release (dh);
196 return mk_error (Out_Of_Core);
197 }
198 dh->private_len = st.st_size;
199
200 if (fread (dh->private_buffer, dh->private_len, 1, fp) != 1) {
201 int save_errno = errno;
202 fclose (fp);
203 gpgme_data_release (dh);
204 errno = save_errno;
205 return mk_error (File_Error);
206 }
207 fclose (fp);
208
209 dh->len = dh->private_len;
210 dh->data = dh->private_buffer;
211 dh->writepos = dh->len;
212 dh->type = GPGME_DATA_TYPE_MEM;
213
214 *r_dh = dh;
215 return 0;
216 }
217
218
219 gpgme_error_t
220 gpgme_data_new_from_filepart (gpgme_data_t *r_dh, const char *fname, FILE *fp,
221 long offset, ulong length)
222 {
223 gpgme_data_t dh;
224 gpgme_error_t err;
225
226 if (!r_dh)
227 return mk_error (Invalid_Value);
228 *r_dh = NULL;
229 if ( fname && fp ) /* these are mutual exclusive */
230 return mk_error (Invalid_Value);
231 if (!fname && !fp)
232 return mk_error (Invalid_Value);
233 if (!length)
234 return mk_error (Invalid_Value);
235
236 err = gpgme_data_new ( &dh );
237 if (err)
238 return err;
239
240 if (!fp) {
241 fp = my_fopen (fname, "rb");
242 if (!fp) {
243 int save_errno = errno;
244 gpgme_data_release (dh);
245 errno = save_errno;
246 return mk_error (File_Error);
247 }
248 }
249
250 if ( fseek ( fp, offset, SEEK_SET) ) {
251 int save_errno = errno;
252 if (fname)
253 fclose (fp);
254 gpgme_data_release (dh);
255 errno = save_errno;
256 return mk_error (File_Error);
257 }
258
259
260 dh->private_buffer = malloc ( length? length : 1 );
261 if( !dh->private_buffer ) {
262 if( fname )
263 fclose( fp );
264 gpgme_data_release (dh);
265 return mk_error (Out_Of_Core);
266 }
267 dh->private_len = length;
268
269 if ( fread ( dh->private_buffer, dh->private_len, 1, fp ) != 1 ) {
270 int save_errno = errno;
271 if (fname)
272 fclose (fp);
273 gpgme_data_release (dh);
274 errno = save_errno;
275 return mk_error (File_Error);
276 }
277
278 if (fname)
279 fclose (fp);
280
281 dh->len = dh->private_len;
282 dh->data = dh->private_buffer;
283 dh->writepos = dh->len;
284 dh->type = GPGME_DATA_TYPE_MEM;
285
286 *r_dh = dh;
287 return 0;
288 }
289
290
291 /**
292 * gpgme_data_release:
293 * @dh: Data object
294 *
295 * Release the data object @dh. @dh may be NULL in which case nothing
296 * happens.
297 **/
298 void
299 gpgme_data_release (gpgme_data_t dh)
300 {
301 if (dh) {
302 safe_free (dh->private_buffer);
303 safe_free (dh);
304 }
305 } /* gpgme_data_release */
306
307
308 char *
309 _gpgme_data_release_and_return_string (gpgme_data_t dh)
310 {
311 char *val = NULL;
312
313 if (!dh)
314 return val;
315
316 if (!_gpgme_data_append (dh, "", 1)) { /* append EOS */
317 val = dh->private_buffer;
318 if (!val && dh->data) {
319 val = malloc (dh->len);
320 if (val)
321 memcpy (val, dh->data, dh->len);
322 }
323 }
324 safe_free (dh);
325 return val;
326 }
327
328
329 /**
330 * gpgme_data_release_and_get_mem:
331 * @dh: the data object
332 * @r_len: returns the length of the memory
333 *
334 * Release the data object @dh and return its content and the length
335 * of that content. The caller has to free this data. @dh maybe NULL
336 * in which case NULL is returned. If there is not enough memory for
337 * allocating the return value, NULL is returned and the object is
338 * released.
339 *
340 * Return value: a pointer to an allocated buffer of length @r_len.
341 **/
342 char *
343 gpgme_data_release_and_get_mem (gpgme_data_t dh, size_t *r_len)
344 {
345 char *val = NULL;
346
347 if (r_len)
348 *r_len = 0;
349 if (dh) {
350 size_t len = dh->len;
351 val = dh->private_buffer;
352 if ( !val && dh->data ) {
353 val = malloc (len);
354 if ( val )
355 memcpy (val, dh->data, len);
356 }
357 safe_free (dh);
358 if (val && r_len)
359 *r_len = len;
360 }
361 return val;
362 }
363
364
365 /**
366 * gpgme_data_get_type:
367 * @dh: the data object
368 *
369 * Get the type of the data object.
370 * Data types are prefixed with %GPGME_DATA_TYPE_
371 *
372 * Return value: the data type
373 **/
374 gpgme_data_type_t
375 gpgme_data_get_type ( gpgme_data_t dh )
376 {
377 if ( !dh || (!dh->data && !dh->read_cb))
378 return GPGME_DATA_TYPE_NONE;
379
380 return dh->type;
381 }
382
383 void
384 _gpgme_data_set_mode( gpgme_data_t dh, gpgme_data_mode_t mode )
385 {
386 assert( dh );
387 dh->mode = mode;
388 }
389
390
391 gpgme_data_mode_t
392 _gpgme_data_get_mode( gpgme_data_t dh )
393 {
394 assert( dh );
395 return dh->mode;
396 }
397
398 /**
399 * gpgme_data_rewind:
400 * @dh: the data object
401 *
402 * Prepare the data object in a way, that a gpgme_data_read() does start
403 * at the beginning of the data. This has to be done for all types
404 * of data objects.
405 *
406 * Return value: An error code or 0 on success
407 **/
408 gpgme_error_t
409 gpgme_data_rewind ( gpgme_data_t dh )
410 {
411 if ( !dh )
412 return mk_error (Invalid_Value);
413
414 if ( dh->type == GPGME_DATA_TYPE_NONE
415 || dh->type == GPGME_DATA_TYPE_MEM ) {
416 dh->readpos = 0;
417 }
418 else if (dh->type == GPGME_DATA_TYPE_CB) {
419 dh->len = dh->readpos = 0;
420 dh->read_cb_eof = 0;
421 /* FIXME: do a special call to the read function to trigger a rewind
422 there */
423 }
424 else
425 return mk_error (General_Error);
426 return 0;
427 }
428
429 /**
430 * gpgme_data_read:
431 * @dh: the data object
432 * @buffer: A buffer
433 * @length: The length of that bufer
434 * @nread: Returns the number of bytes actually read.
435 *
436 * Copy data from the current read position (which may be set by
437 * gpgme_data_rewind()) to the supplied @buffer, max. @length bytes
438 * are copied and the actual number of bytes are returned in @nread.
439 * If there are no more bytes available %GPGME_EOF is returned and @nread
440 * is set to 0.
441 *
442 * Return value: An errorcode or 0 on success, EOF is indcated by the
443 * error code GPGME_EOF.
444 **/
445 gpgme_error_t
446 gpgme_data_read ( gpgme_data_t dh, char *buffer, size_t length, size_t *nread )
447 {
448 size_t nbytes;
449
450 if ( !dh )
451 return mk_error (Invalid_Value);
452 if (dh->type == GPGME_DATA_TYPE_MEM ) {
453 nbytes = dh->len - dh->readpos;
454 if ( !nbytes ) {
455 *nread = 0;
456 return mk_error(EOF);
457 }
458 if (nbytes > length)
459 nbytes = length;
460 memcpy ( buffer, dh->data + dh->readpos, nbytes );
461 *nread = nbytes;
462 dh->readpos += nbytes;
463 }
464 else if (dh->type == GPGME_DATA_TYPE_CB) {
465 nbytes = dh->len - dh->readpos;
466 if ( nbytes ) {
467 /* we have unread data - return this */
468 if (nbytes > length)
469 nbytes = length;
470 memcpy ( buffer, dh->data + dh->readpos, nbytes );
471 *nread = nbytes;
472 dh->readpos += nbytes;
473 }
474 else { /* get the data from the callback */
475 if (!dh->read_cb || dh->read_cb_eof) {
476 *nread = 0;
477 return mk_error (EOF);
478 }
479 if (dh->read_cb (dh->read_cb_value, buffer, length, nread )) {
480 *nread = 0;
481 dh->read_cb_eof = 1;
482 return mk_error (EOF);
483 }
484 }
485 }
486 else
487 return mk_error (General_Error);
488 return 0;
489 }
490
491
492 gpgme_error_t
493 _gpgme_data_eof( gpgme_data_t dh )
494 {
495 if( !dh )
496 return mk_error( Invalid_Value );
497 if( dh->type == GPGME_DATA_TYPE_MEM ) {
498 size_t nbytes = dh->len - dh->readpos;
499 if( !nbytes )
500 return mk_error( EOF );
501 }
502 return 0;
503 }
504
505
506 gpgme_error_t
507 _gpgme_data_unread (gpgme_data_t dh, const char *buffer, size_t length )
508 {
509 if( !dh )
510 return mk_error (Invalid_Value);
511 if( dh->type == GPGME_DATA_TYPE_MEM ) {
512 /* check that we don't unread more than we have yet read */
513 if( dh->readpos < length )
514 return mk_error( Invalid_Value );
515 /* No need to use the buffer for this data type */
516 dh->readpos -= length;
517 }
518 else {
519 return mk_error( General_Error );
520 }
521 return 0;
522 }
523
524
525 /*
526 * This function does make sense when we know that it contains no nil chars.
527 */
528 char *
529 _gpgme_data_get_as_string ( gpgme_data_t dh )
530 {
531 char *val = NULL;
532
533 if (dh) {
534 val = malloc ( dh->len+1 );
535 if ( val ) {
536 memcpy ( val, dh->data, dh->len );
537 val[dh->len] = 0;
538 }
539 }
540 return val;
541 }
542
543
544 /**
545 * gpgme_data_write:
546 * @dh: the context
547 * @buffer: data to be written to the data object
548 * @length: length o this data
549 *
550 * Write the content of @buffer to the data object @dh at the current write
551 * position.
552 *
553 * Return value: 0 on succress or an errorcode
554 **/
555 gpgme_error_t
556 gpgme_data_write (gpgme_data_t dh, const char *buffer, size_t length)
557 {
558 if (!dh || !buffer)
559 return mk_error (Invalid_Value);
560
561 return _gpgme_data_append (dh, buffer, length );
562 }
563
564
565 gpgme_error_t
566 _gpgme_data_append ( gpgme_data_t dh, const char *buffer, size_t length )
567 {
568 assert (dh);
569
570 if ( dh->type == GPGME_DATA_TYPE_NONE ) {
571 /* convert it to a mem data type */
572 assert (!dh->private_buffer);
573 dh->type = GPGME_DATA_TYPE_MEM;
574 dh->private_len = length < ALLOC_CHUNK? ALLOC_CHUNK : length;
575 dh->private_buffer = malloc ( dh->private_len );
576 if( !dh->private_buffer ) {
577 dh->private_len = 0;
578 return mk_error (Out_Of_Core);
579 }
580 dh->writepos = 0;
581 dh->data = dh->private_buffer;
582 }
583 else if ( dh->type != GPGME_DATA_TYPE_MEM )
584 return mk_error (Invalid_Type);
585
586 if ( dh->mode != GPGME_DATA_MODE_INOUT
587 && dh->mode != GPGME_DATA_MODE_IN )
588 return mk_error (Invalid_Mode);
589
590 if ( !dh->private_buffer ) {
591 /* we have to copy it now */
592 assert (dh->data);
593 dh->private_len = dh->len+length;
594 if (dh->private_len < ALLOC_CHUNK)
595 dh->private_len = ALLOC_CHUNK;
596 dh->private_buffer = malloc ( dh->private_len );
597 if (!dh->private_buffer) {
598 dh->private_len = 0;
599 return mk_error (Out_Of_Core);
600 }
601 memcpy ( dh->private_buffer, dh->data, dh->len );
602 dh->writepos = dh->len;
603 dh->data = dh->private_buffer;
604 }
605
606 /* allocate more memory if needed */
607 if ( dh->writepos + length > dh->private_len ) {
608 char *p;
609 size_t newlen = dh->private_len
610 + (dh->len < ALLOC_CHUNK? ALLOC_CHUNK : length);
611 p = realloc ( dh->private_buffer, newlen );
612 if ( !p )
613 return mk_error (Out_Of_Core);
614 dh->private_buffer = p;
615 dh->private_len = newlen;
616 dh->data = dh->private_buffer;
617 assert ( !(dh->writepos + length > dh->private_len) );
618 }
619
620 memcpy ( dh->private_buffer + dh->writepos, buffer, length );
621 dh->writepos += length;
622 dh->len += length;
623
624 return 0;
625 }
626
627 gpgme_error_t
628 _gpgme_data_append_string ( gpgme_data_t dh, const char *s )
629 {
630 return _gpgme_data_append ( dh, s, s? strlen(s):0 );
631 }
632
633
634 gpgme_error_t
635 _gpgme_data_read_from_tmpfile( gpgme_data_t dh )
636 {
637 FILE *fp;
638 size_t n;
639 unsigned char buf[512];
640
641 gpgme_data_rewind( dh );
642 fp = fopen( _gpgme_get_tmpfile(0), "rb" );
643 if( fp == NULL )
644 return mk_error( File_Error );
645 while( !feof(fp) ) {
646 memset(buf, 0, sizeof buf );
647 n = fread(buf, 1, sizeof buf - 1, fp );
648 if( n > 0 )
649 gpgme_data_write( dh, buf, n );
650 }
651 fclose( fp );
652 return 0;
653 } /* _gpgme_data_read_from_tmpfile */
654
655
656 gpgme_error_t
657 _gpgme_data_write_to_tmpfile( gpgme_data_t dh )
658 {
659 FILE *fp;
660 char *p;
661
662 gpgme_data_rewind( dh );
663 fp = fopen( _gpgme_get_tmpfile(1), "wb" );
664 if( fp == NULL )
665 return mk_error( File_Error );
666 p = _gpgme_data_get_as_string( dh );
667 if( p ) {
668 fwrite( p, 1, strlen( p ), fp );
669 safe_free( p );
670 }
671 fclose( fp );
672 return 0;
673 } /* _gpgme_data_write_to_tmpfile */
674
675 char*
676 gpgme_data_get_as_string( gpgme_data_t dh )
677 {
678 return _gpgme_data_get_as_string( dh );
679 } /* gpgme_data_get_as_string */
680
681 char*
682 gpgme_data_release_and_return_string( gpgme_data_t dh )
683 {
684 return _gpgme_data_release_and_return_string( dh );
685 } /* gpgme_data_release_and_return_string */
686
687 gpgme_error_t
688 gpgme_data_release_and_set_file (gpgme_data_t dh, const char *fname)
689 {
690 char *p = NULL;
691 FILE *fp;
692
693 fp = my_fopen (fname, "wb");
694 if (fp == NULL)
695 return mk_error (File_Error);
696
697 p = _gpgme_data_release_and_return_string (dh);
698 if (p) {
699 fwrite (p, 1, strlen (p), fp);
700 fflush (fp);
701 memset (p, 0xFF, strlen (p));
702 safe_free (p);
703 }
704 fclose (fp);
705 return 0;
706 } /* gpgme_data_release_and_set_file */
707
708
709 size_t
710 gpgme_data_readline( gpgme_data_t dh, char * line, size_t nbytes )
711 {
712 char ch = 0;
713 size_t nread = 0, pos = 0;
714
715 if( !dh )
716 return 0;
717
718 memset( line, 0, nbytes );
719 while( !gpgme_data_read( dh, &ch, 1, &nread ) ) {
720 if( !nread )
721 break;
722 if( ch == '\n' ) {
723 line[pos++] = ch;
724 line[pos++] = '\0';
725 break;
726 }
727 line[pos++] = ch;
728 if( pos > nbytes ) {
729 line[pos++] = '\0';
730 break;
731 }
732 }
733
734 return pos;
735 } /* gpgme_data_readline */
736
737
738 static char*
739 wrap_lines_soft( char *buf, int wraplen )
740 {
741 char *curpos, *lastspc, *lastbrk;
742
743 for( curpos = lastspc = lastbrk = buf; *curpos; curpos++ ) {
744 if( *curpos == ' ' )
745 lastspc = curpos;
746 else {
747 if( *curpos == '\n' ) {
748 lastbrk = curpos;
749 lastspc = lastbrk;
750 }
751 }
752 if( (curpos - lastbrk) >= wraplen ) {
753 *lastspc = '\n';
754 lastbrk = lastspc;
755 }
756 }
757
758 return buf;
759 } /* wrap_lines_soft */
760
761 static char*
762 wrap_lines( char *buf, size_t bufsize, size_t wraplen )
763 {
764 char *soft, *hard, *p;
765 size_t pos = 0, size = 0;
766
767 soft = wrap_lines_soft( buf, wraplen );
768 if( !soft )
769 return NULL;
770 hard = malloc (bufsize + (bufsize/10));
771 if( !hard )
772 return NULL;
773 strcpy (hard, soft);
774 while( soft ) {
775 p = strchr( soft, '\n' );
776 if( p == NULL )
777 break;
778 pos = p - soft + 1;
779 if( soft[pos-2] != '\r' ) {
780 memcpy( hard + size, soft, pos-1 );
781 size += (pos-1);
782 memcpy( hard + size, "\r\n", 2 );
783 size += 2;
784 }
785 else {
786 memcpy( hard+size, soft, pos );
787 size += pos;
788 }
789 soft += pos;
790 }
791
792 memcpy( hard + size, "\0", 1 );
793 return hard;
794 } /* wrap_lines */
795
796
797 int
798 gpgme_data_wrap_lines( gpgme_data_t *r_dh, size_t wraplen )
799 {
800 gpgme_error_t err = 0;
801 gpgme_data_t mdh;
802 char *raw, *p;
803 size_t nlen;
804
805 err = gpgme_data_new( &mdh );
806 if( err )
807 return err;
808
809 raw = _gpgme_data_get_as_string( *r_dh );
810 if( !raw ) {
811 gpgme_data_release( mdh );
812 return mk_error( General_Error );
813 }
814 nlen = strlen( raw );
815 if( !strchr( raw, '\n' ) && nlen < wraplen ) {
816 gpgme_data_release( mdh );
817 safe_free( raw );
818 return 0;
819 }
820
821 p = wrap_lines( raw, nlen, wraplen );
822 if( p )
823 _gpgme_data_append_string( mdh, p );
824 gpgme_data_release( *r_dh );
825 *r_dh = mdh;
826 safe_free( raw );
827 safe_free( p );
828 return 0;
829 } /* gpgme_data_wrap_lines */
830
831
832 gpgme_error_t
833 gpgme_data_mail_quote (gpgme_data_t *r_dh)
834 {
835 gpgme_data_t dh;
836 char buf[128];
837
838 if (!*r_dh)
839 return mk_error (Invalid_Value);
840 gpgme_data_new (&dh);
841 while (gpgme_data_readline (*r_dh, buf, 127)) {
842 gpgme_data_write (dh, "> ", 2);
843 gpgme_data_write (dh, buf, strlen (buf));
844 }
845 gpgme_data_release (*r_dh);
846 *r_dh = dh;
847 return 0;
848 }
849
850
851 gpgme_error_t
852 gpgme_data_extract_plaintext( gpgme_data_t sig, gpgme_data_t *r_plain )
853 {
854 gpgme_data_t plain;
855 gpgme_error_t err;
856 char line[128+32];
857 int pos = 0;
858 int sig_begin = 0;
859
860 err = gpgme_data_new( &plain );
861 if( err ) {
862 if( r_plain )
863 *r_plain = NULL;
864 return err;
865 }
866
867 while( gpgme_data_readline( sig, line, 128 ) ) {
868 if( !strncmp( line, "-----BEGIN PGP SIGNED MESSAGE", 29 )
869 || !strncmp( line, "Version:", 8 )
870 || !strncmp( line, "Comment:", 8 )
871 || !strncmp( line, "Charset:", 8 )
872 || !strncmp( line, "Hash:", 5 )
873 || !strncmp (line, "MessageID", 9))
874 continue;
875 if( strlen( line ) <= 2 )
876 break; /* parsed all headers, now we reached the body */
877 }
878 /* fixme: handle multi dash escaped sequences! */
879 while( gpgme_data_readline( sig, line, 128 ) ) {
880 if( !strncmp( line, "-----BEGIN PGP SIGNATURE", 24 ) )
881 break; /* end of plaintext */
882 if( !strncmp( line, "- -", 3 ) )
883 pos = 2;
884 _gpgme_data_append_string( plain, line + pos );
885 pos = 0;
886 }
887 if( r_plain )
888 *r_plain = plain;
889 else
890 gpgme_data_release( plain );
891 return err;
892 } /* gpgme_data_extract_plaintext */
893
894
895 gpgme_error_t
896 gpgme_data_change_version( gpgme_data_t *r_dh )
897 {
898 gpgme_error_t err = 0;
899 gpgme_data_t mdh;
900 char line[128+32];
901
902 err = gpgme_data_new( &mdh );
903 if( err ) {
904 if( r_dh )
905 *r_dh = NULL;
906 return err;
907 }
908 while( gpgme_data_readline( *r_dh, line, 128 ) ) {
909 if( strlen( line ) > 14
910 && !strncmp( line, "Version: GnuPG", 14 )
911 && !strstr( line, pgm_string ) ) {
912 line[strlen( line ) - 2] = '\0';
913 strcat( line, " - " );
914 strcat( line, pgm_string );
915 strcat( line, "\r\n" );
916 }
917 _gpgme_data_append_string( mdh, line );
918 }
919 gpgme_data_release( *r_dh );
920 if( r_dh )
921 *r_dh = mdh;
922 else
923 gpgme_data_release( mdh );
924 return err;
925 } /* gpgme_data_change_version */
926
927
928 /* Convert two hexadecimal digits from STR to the value they
929 represent. Returns -1 if one of the characters is not a
930 hexadecimal digit. */
931 static int
932 _gpgme_hextobyte (const unsigned char *str)
933 {
934 int val = 0;
935 int i;
936
937 #define NROFHEXDIGITS 2
938 for (i = 0; i < NROFHEXDIGITS; i++) {
939 if (*str >= '0' && *str <= '9')
940 val += *str - '0';
941 else if (*str >= 'A' && *str <= 'F')
942 val += 10 + *str - 'A';
943 else if (*str >= 'a' && *str <= 'f')
944 val += 10 + *str - 'a';
945 else
946 return -1;
947 if (i < NROFHEXDIGITS - 1)
948 val *= 16;
949 str++;
950 }
951 return val;
952 }
953
954
955 /* Decode the C formatted string SRC and store the result in the
956 buffer *DESTP which is LEN bytes long. If LEN is zero, then a
957 large enough buffer is allocated with malloc and *DESTP is set to
958 the result. Currently, LEN is only used to specify if allocation
959 is desired or not, the caller is expected to make sure that *DESTP
960 is large enough if LEN is not zero. */
961 gpgme_error_t
962 _gpgme_decode_c_string (const char *src, char **destp, size_t len)
963 {
964 char *dest;
965
966 /* Set up the destination buffer. */
967 if (len)
968 {
969 if (len < strlen (src) + 1)
970 return GPGME_General_Error;
971
972 dest = *destp;
973 }
974 else
975 {
976 /* The converted string will never be larger than the original
977 string. */
978 dest = malloc (strlen (src) + 1);
979 if (!dest)
980 return GPGME_Out_Of_Core;
981 *destp = dest;
982 }
983
984 /* Convert the string. */
985 while (*src)
986 {
987 if (*src != '\\')
988 {
989 *(dest++) = *(src++);
990 continue;
991 }
992
993 switch (src[1])
994 {
995 #define DECODE_ONE(match,result) \
996 case match: \
997 src += 2; \
998 *(dest++) = result; \
999 break;
1000
1001 DECODE_ONE ('\'', '\'');
1002 DECODE_ONE ('\"', '\"');
1003 DECODE_ONE ('\?', '\?');
1004 DECODE_ONE ('\\', '\\');
1005 DECODE_ONE ('a', '\a');
1006 DECODE_ONE ('b', '\b');
1007 DECODE_ONE ('f', '\f');
1008 DECODE_ONE ('n', '\n');
1009 DECODE_ONE ('r', '\r');
1010 DECODE_ONE ('t', '\t');
1011 DECODE_ONE ('v', '\v');
1012
1013 case 'x':
1014 {
1015 int val = _gpgme_hextobyte (&src[2]);
1016
1017 if (val == -1)
1018 {
1019 /* Should not happen. */
1020 *(dest++) = *(src++);
1021 *(dest++) = *(src++);
1022 if (*src)
1023 *(dest++) = *(src++);
1024 if (*src)
1025 *(dest++) = *(src++);
1026 }
1027 else
1028 {
1029 if (!val)
1030 {
1031 /* A binary zero is not representable in a C
1032 string. */
1033 *(dest++) = '\\';
1034 *(dest++) = '0';
1035 }
1036 else
1037 *((unsigned char *) dest++) = val;
1038 src += 4;
1039 }
1040 }
1041
1042 default:
1043 {
1044 /* Should not happen. */
1045 *(dest++) = *(src++);
1046 *(dest++) = *(src++);
1047 }
1048 }
1049 }
1050 *(dest++) = 0;
1051
1052 return 0;
1053 }
1054
1055
1056 void
1057 gpgme_set_pgm_string (const char * name)
1058 {
1059 if (!name || !*name)
1060 return;
1061 memset (pgm_string, 0, sizeof pgm_string);
1062 strncpy (pgm_string, name, sizeof pgm_string-1);
1063 } /* gpgme_set_pgm_string */

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26