/[winpt]/trunk/Src/wptGPGUtil.cpp
ViewVC logotype

Contents of /trunk/Src/wptGPGUtil.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 278 - (show annotations)
Mon Jan 15 22:02:04 2007 UTC (18 years, 1 month ago) by twoaday
File size: 19373 byte(s)
See ChangeLog.


1 /* wptGPGUtil.cpp - GPG util functions
2 * Copyright (C) 2005, 2006 Timo Schulz
3 * Copyright (C) 2005 g10 Code GmbH
4 *
5 * This file is part of WinPT.
6 *
7 * WinPT 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 * WinPT 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 #ifdef HAVE_CONFIG_H
18 #include <config.h>
19 #endif
20
21 #include <windows.h>
22 #include <sys/stat.h>
23 #include <string.h>
24 #include <errno.h>
25
26 #include "gpgme.h"
27 #include "wptTypes.h"
28 #include "wptErrors.h"
29 #include "wptW32API.h"
30 #include "wptGPG.h"
31 #include "wptRegistry.h"
32 #include "StringBuffer.h"
33 #include "openpgp.h"
34
35
36 static char*
37 char_alloc (size_t n)
38 {
39 char *p;
40
41 p = new char[n];
42 if (!p)
43 BUG (0);
44 memset (p, 0, n);
45 return p;
46 }
47
48
49 #define NROFHEXDIGITS 2
50 /* Convert two hexadecimal digits from STR to the value they
51 represent. Returns -1 if one of the characters is not a
52 hexadecimal digit. */
53 static int
54 hextobyte (const unsigned char *str)
55 {
56 int val = 0;
57 int i;
58
59 for (i = 0; i < NROFHEXDIGITS; i++) {
60 if (*str >= '0' && *str <= '9')
61 val += *str - '0';
62 else if (*str >= 'A' && *str <= 'F')
63 val += 10 + *str - 'A';
64 else if (*str >= 'a' && *str <= 'f')
65 val += 10 + *str - 'a';
66 else
67 return -1;
68 if (i < NROFHEXDIGITS - 1)
69 val *= 16;
70 str++;
71 }
72 return val;
73 }
74
75 /* Decode the C formatted string @src and store the result in the
76 buffer @destp which is @len bytes long. If @len is zero, then a
77 large enough buffer is allocated with malloc and @destp is set to
78 the result. Currently, @len is only used to specify if allocation
79 is desired or not, the caller is expected to make sure that @destp
80 is large enough if @len is not zero. */
81 gpgme_error_t
82 gpg_decode_c_string (const char *src, char **destp, size_t len)
83 {
84 char *dest;
85
86 /* Set up the destination buffer. */
87 if (len) {
88 if (len < strlen (src) + 1)
89 return gpg_error (GPG_ERR_TOO_SHORT);
90 dest = *destp;
91 }
92 else {
93 /* The converted string will never be larger than the original string. */
94 dest = char_alloc (strlen (src) + 1);
95 *destp = dest;
96 }
97
98 /* Convert the string. */
99 while (*src) {
100 if (*src != '\\') {
101 *(dest++) = *(src++);
102 continue;
103 }
104
105 switch (src[1]) {
106 #define DECODE_ONE(match,result) \
107 case match: \
108 src += 2; \
109 *(dest++) = result; \
110 break;
111
112 DECODE_ONE ('\'', '\'');
113 DECODE_ONE ('\"', '\"');
114 DECODE_ONE ('\?', '\?');
115 DECODE_ONE ('\\', '\\');
116 DECODE_ONE ('a', '\a');
117 DECODE_ONE ('b', '\b');
118 DECODE_ONE ('f', '\f');
119 DECODE_ONE ('n', '\n');
120 DECODE_ONE ('r', '\r');
121 DECODE_ONE ('t', '\t');
122 DECODE_ONE ('v', '\v');
123
124 case 'x': {
125 int val = hextobyte ((unsigned char*)&src[2]);
126 if (val == -1) { /* Should not happen. */
127 *(dest++) = *(src++);
128 *(dest++) = *(src++);
129 if (*src)
130 *(dest++) = *(src++);
131 if (*src)
132 *(dest++) = *(src++);
133 }
134 else {
135 if (!val) {
136 /* A binary zero is not representable in a C string. */
137 *(dest++) = '\\';
138 *(dest++) = '0';
139 }
140 else
141 *((unsigned char *) dest++) = val;
142 src += 4;
143 }
144 }
145
146 default: /* Should not happen. */
147 {
148 *(dest++) = *(src++);
149 *(dest++) = *(src++);
150 }
151 }
152 }
153 *(dest++) = 0;
154 return 0;
155 }
156
157
158 static char*
159 read_gpg_program (void)
160 {
161 return get_reg_entry (HKEY_CURRENT_USER,
162 "Software\\GNU\\GnuPG", "gpgProgram");
163 }
164
165
166 /* Create a temp file based on the name of @name.
167 Return value: handle to the file in case of success. */
168 static HANDLE
169 create_tmpfile (const char *name)
170 {
171 HANDLE out;
172 SECURITY_ATTRIBUTES sec_attr;
173 char tmp[MAX_PATH+64];
174
175 memset (&sec_attr, 0, sizeof (sec_attr));
176 sec_attr.bInheritHandle = TRUE;
177 sec_attr.lpSecurityDescriptor = NULL;
178 sec_attr.nLength = sizeof (sec_attr);
179
180 get_temp_name (tmp, DIM (tmp)-1, name);
181 out = CreateFile (tmp, GENERIC_READ|GENERIC_WRITE,
182 FILE_SHARE_WRITE, &sec_attr,
183 OPEN_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, NULL);
184 if (out == INVALID_HANDLE_VALUE)
185 log_debug ("create_tmpfile: CreateFile failed ec=%d\r\n",
186 (int)GetLastError ());
187 return out;
188 }
189
190
191 /* Create a pipe with a readable remote end and
192 write the data from @dat to the local end.
193 Return value: read handle on success. */
194 static HANDLE
195 create_in_pipe (const char *dat)
196 {
197 HANDLE r, w;
198 SECURITY_ATTRIBUTES sec_attr;
199 DWORD n;
200
201 memset (&sec_attr, 0, sizeof sec_attr);
202 sec_attr.bInheritHandle = TRUE;
203 sec_attr.nLength = sizeof sec_attr;
204
205 if (!CreatePipe (&r, &w, &sec_attr, 4096)) {
206 log_debug ("create_in_pipe: CreatePipeFailed ec=%d\r\n",
207 (int)GetLastError ());
208 return NULL;
209 }
210
211 WriteFile (w, dat, strlen (dat), &n, NULL);
212 CloseHandle (w);
213
214 return r;
215 }
216
217
218 /* Map the contents of the file handle @out to
219 a buffer and return it. */
220 static char*
221 map_tmpfile (HANDLE out, DWORD *nread)
222 {
223 DWORD n;
224 char *p;
225
226 FlushFileBuffers (out);
227 SetFilePointer (out, 0, NULL, FILE_BEGIN);
228 n = GetFileSize (out, NULL);
229 p = char_alloc (n+1);
230 ReadFile (out, p, n, &n, NULL);
231 p[n] = 0;
232 if (nread)
233 *nread = n;
234 return p;
235 }
236
237
238 /* Create a process from the command line in @cmd.
239 If @out is != NULL, the output of the process will
240 be redirected to @out. If @in is != NULL the input
241 will be read from @in.
242 Return value: 0 on success. */
243 static int
244 create_process (const char *cmd, HANDLE in, HANDLE out, HANDLE err)
245 {
246 STARTUPINFO si;
247 PROCESS_INFORMATION pi;
248
249 memset (&si, 0, sizeof (si));
250 si.cb = sizeof si;
251 if (in || out || err)
252 si.dwFlags = STARTF_USESTDHANDLES;
253 if (out)
254 si.hStdOutput = out;
255 if (in)
256 si.hStdInput = in;
257 if (err)
258 si.hStdError = err;
259 si.dwFlags |= STARTF_USESHOWWINDOW;
260 si.wShowWindow = SW_HIDE;
261 if (!CreateProcess (NULL, (char*)cmd, NULL, NULL, TRUE, 0,
262 NULL, NULL, &si, &pi)) {
263 log_debug ("create_process: CreateProcess failed ec=%d\r\n",
264 (int)GetLastError ());
265 return -1;
266 }
267 WaitForSingleObject (pi.hProcess, INFINITE);
268 CloseHandle (pi.hProcess);
269 CloseHandle (pi.hThread);
270 return 0;
271 }
272
273
274
275 /* We execute gpg and check the process return code.
276 A return code != 0 indicates a problem (error). */
277 int
278 gpg_check_return_code (const char *args)
279 {
280 STARTUPINFO si;
281 PROCESS_INFORMATION pi;
282 StringBuffer cmd;
283 char *p;
284 DWORD ec;
285
286 memset (&si, 0, sizeof (si));
287 si.cb = sizeof (si);
288 si.dwFlags = STARTF_USESHOWWINDOW;
289 si.wShowWindow = SW_HIDE;
290
291 p = read_gpg_program ();
292 if (!p)
293 return 1; /* general error */
294 cmd = p;
295 cmd = cmd + " " + args;
296 free_if_alloc (p);
297
298 if (!CreateProcess (NULL, (char*)cmd.getBuffer (), NULL, NULL,
299 FALSE, 0, NULL, NULL, &si, &pi))
300 return 1; /* general error */
301
302 WaitForSingleObject (pi.hProcess, INFINITE);
303 GetExitCodeProcess (pi.hProcess, &ec);
304
305 CloseHandle (pi.hProcess);
306 CloseHandle (pi.hThread);
307 return (int)ec;
308 }
309
310
311 /* Export a GPG secret key given by @keyid into the file @outfile.
312 Return value: 0 on success. */
313 gpgme_error_t
314 gpg_export_seckey (const char *keyid, const char *outfile)
315 {
316 gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
317 struct stat st;
318 char *p;
319 StringBuffer cmd;
320
321 p = read_gpg_program ();
322 if (!p)
323 return gpg_error (GPG_ERR_INV_ARG);
324 cmd = p;
325 cmd = cmd + " --armor --yes --output \"" + outfile + "\"";
326 cmd = cmd + " --export-secret-key " + keyid;
327
328 if (create_process (cmd.getBuffer (), NULL, NULL, NULL))
329 err = gpg_error (GPG_ERR_MODULE_NOT_FOUND);
330
331 if (stat (outfile, &st) == -1 || st.st_size == 0)
332 err = gpg_error (GPG_ERR_NO_DATA);
333
334 free_if_alloc (p);
335 return err;
336 }
337
338
339 /* If @export is 1, export the ownertrust data to the
340 buffer @data. Otherwise import the ownertrust data from @data.
341 Return value: 0 on success. */
342 gpgme_error_t
343 gpg_manage_ownertrust (char **data, int do_export)
344 {
345 gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
346 HANDLE out = NULL, in = NULL;
347 StringBuffer cmd;
348 char *p;
349
350 p = read_gpg_program ();
351 if (!p)
352 return gpg_error (GPG_ERR_INV_ARG);
353
354 cmd = p;
355 cmd = cmd + (do_export? " --export-ownertrust" : " --import-ownertrust");
356
357 if (do_export)
358 out = create_tmpfile ("tmp_gpg_ot_out");
359 else {
360 DWORD nw;
361
362 in = create_tmpfile ("tmp_gpg_ot_in");
363 WriteFile (in, *data, strlen (*data), &nw, NULL);
364 FlushFileBuffers (in);
365 }
366 if (create_process (cmd.getBuffer (), in, out, NULL))
367 err = gpg_error (GPG_ERR_MODULE_NOT_FOUND);
368
369 free_if_alloc (p);
370
371 if (in)
372 CloseHandle (in);
373 if (out) {
374 *data = map_tmpfile (out, NULL);
375 CloseHandle (out);
376 }
377
378 return err;
379 }
380
381
382 /* Call gpg --rebuild-keydb-caches to speed up signature listings. */
383 gpgme_error_t
384 gpg_rebuild_cache (char **r_inf)
385 {
386 gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
387 HANDLE out = NULL;
388 StringBuffer cmd;
389 char *p;
390
391 p = read_gpg_program ();
392 if (!p)
393 return gpg_error (GPG_ERR_INV_ARG);
394 cmd = p;
395 cmd = cmd + " --logger-fd=1 --batch --rebuild-keydb-caches";
396
397 if (r_inf)
398 out = create_tmpfile ("tmp_gpg_rebuild_cache");
399
400 if (create_process (cmd.getBuffer (), NULL, out, NULL))
401 err = gpg_error (GPG_ERR_MODULE_NOT_FOUND);
402
403 if (r_inf)
404 *r_inf = map_tmpfile (out, NULL);
405 if (out)
406 CloseHandle (out);
407 free_if_alloc (p);
408 return err;
409 }
410
411
412 /* Call gpg --version to retrieve the 'about' information. */
413 gpgme_error_t
414 gpg_get_version (char **r_inf)
415 {
416 gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
417 HANDLE out;
418 StringBuffer cmd;
419 char *p;
420
421 p = read_gpg_program ();
422 if (!p)
423 return gpg_error (GPG_ERR_INV_ARG);
424 cmd = p;
425 cmd = cmd + " --version";
426
427 out = create_tmpfile ("tmp_gpg_out");
428 if (create_process (cmd.getBuffer (), NULL, out, NULL))
429 err = gpg_error (GPG_ERR_MODULE_NOT_FOUND);
430
431 free_if_alloc (p);
432
433 *r_inf = map_tmpfile (out, NULL);
434 CloseHandle (out);
435 return err;
436 }
437
438
439 /* Return the colon file output of the given file @fname in @r_out.
440 Return value: 0 on success. */
441 gpgme_error_t
442 gpg_import_key_list (const char *fname, char **r_out)
443 {
444 gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
445 HANDLE out;
446 StringBuffer cmd;
447 char *p;
448
449 p = read_gpg_program ();
450 if (!p)
451 return gpg_error (GPG_ERR_INV_ARG);
452
453 cmd = p;
454 cmd = cmd + " --fixed-list-mode --with-colons ";
455 cmd = cmd + "\"" + fname + "\"";
456
457 out = create_tmpfile ("tmp_gpg_keys");
458 if (create_process (cmd.getBuffer (), NULL, out, NULL))
459 err = gpg_error (GPG_ERR_MODULE_NOT_FOUND);
460
461 free_if_alloc (p);
462
463 *r_out = map_tmpfile (out, NULL);
464 CloseHandle (out);
465 return err;
466 }
467
468
469 /* Generate a revocation certificate for the key with the keyid @keyid.
470 @inp_data contains all needed data to answer the questions of the
471 command handler. Each separate with a '\n'.
472 @r_revcert contains the revocation cert on success.
473 if @desig_revoke is 1, the designated revoker mode is used.
474 Return value: 0 on success. */
475 gpgme_error_t
476 gpg_revoke_cert (int desig_revoke, const char *inp_data,
477 const char *keyid, char **r_revcert)
478 {
479 gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
480 HANDLE in, out;
481 StringBuffer cmd;
482 char *rcrt;
483 char *p;
484
485 p = read_gpg_program ();
486 if (!p)
487 return gpg_error (GPG_ERR_INV_ARG);
488
489 cmd = p;
490 cmd = cmd + " --pgp7 --command-fd=0 --status-fd=2 ";
491 cmd = cmd + (desig_revoke? "--desig-revoke" : "--gen-revoke");
492 cmd = cmd + " " + keyid;
493
494 in = create_in_pipe (inp_data);
495 out = create_tmpfile ("tmp_gpg_revcert");
496 if (create_process (cmd.getBuffer (), in, out, NULL)) {
497 *r_revcert = NULL;
498 err = gpg_error (GPG_ERR_MODULE_NOT_FOUND);
499 }
500 else {
501 rcrt = map_tmpfile (out, NULL);
502 *r_revcert = rcrt;
503 if (rcrt && strlen (rcrt) == 0)
504 err = gpg_error (GPG_ERR_BAD_PASSPHRASE);
505 }
506
507 free_if_alloc (p);
508
509 CloseHandle (in);
510 CloseHandle (out);
511 return err;
512 }
513
514
515 /* Return the raw photo-id data combined with the status-fd
516 entry in @r_data. If @keyid is set, only the data for this
517 key will be returned.
518 Return value: 0 on success. */
519 gpgme_error_t
520 gpg_get_photoid_data (const char *keyid, char **r_status_data,
521 unsigned char **r_data, unsigned long *ndata)
522 {
523 gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
524 HANDLE herr, hdat;
525 StringBuffer cmd;
526 char *p;
527
528 if (ndata)
529 *ndata = 0;
530 p = read_gpg_program ();
531 if (!p)
532 return gpg_error (GPG_ERR_INV_ARG);
533 hdat = create_tmpfile ("tmp_gpg_uat_data");
534 herr = create_tmpfile ("tmp_gpg_uat_status");
535
536 /* XXX: add --list-options show-unsuable-uid to display
537 revoked attribute IDs */
538 cmd = p;
539 cmd = cmd + " --attribute-fd=" + ((int)hdat);
540 cmd = cmd + " --status-fd=2 --list-keys ";
541 if (keyid != NULL)
542 cmd = cmd + keyid;
543
544 if (create_process (cmd.getBuffer (), NULL, NULL, herr))
545 err = gpg_error (GPG_ERR_MODULE_NOT_FOUND);
546
547 free_if_alloc (p);
548
549 *r_data = (BYTE*)map_tmpfile (hdat, ndata);
550 *r_status_data = map_tmpfile (herr, NULL);
551 CloseHandle (hdat);
552 CloseHandle (herr);
553
554 return err;
555 }
556
557
558 /* Extract one or more keys from the key file @keyfile.
559 The keys to extract are give in @keys and the size of it is @nkeys.
560 @new_keyfile is a file with the extract keys.
561 Return value: 0 on success. */
562 gpgme_error_t
563 gpg_extract_keys (const char *keyfile, const char **keys, DWORD nkeys,
564 char **new_keyfile)
565 {
566 gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
567 StringBuffer cmd;
568 char *p;
569 char tmpnam[MAX_PATH], tmpdir[MAX_PATH];
570 int i;
571
572 /* copy key file to temp dir. */
573 GetTempPath (MAX_PATH-1, tmpdir);
574 get_temp_name (tmpnam, MAX_PATH-1, NULL);
575 CopyFile (keyfile, tmpnam, FALSE);
576
577 /* create temp file for output. */
578 *new_keyfile = new char[MAX_PATH];
579 if (!*new_keyfile)
580 BUG (NULL);
581 get_temp_name (*new_keyfile, MAX_PATH-1, "tmp_sel_keys");
582
583 p = read_gpg_program ();
584 if (!p)
585 return gpg_error (GPG_ERR_INV_ARG);
586
587 /* Use the temp key file as a keyring and export the selected
588 keys from it. */
589 cmd = p;
590 cmd = cmd + " --yes --output " + "\"" + *new_keyfile + "\"";
591 cmd = cmd + " --no-options --homedir " + tmpdir + " --keyring " + tmpnam + " --export ";
592 for (i=0; i < (int)nkeys; i++)
593 cmd = cmd + keys[i] + " ";
594
595 if (create_process (cmd.getBuffer (), NULL, NULL, NULL))
596 err = gpgme_error (GPG_ERR_MODULE_NOT_FOUND);
597
598 DeleteFile (tmpnam);
599 free_if_alloc (p);
600 return err;
601 }
602
603
604 /* Return the validity of the user attribute, informerly known
605 as photo-ID. If no uat was found, return 0 for unknown. */
606 gpgme_error_t
607 get_uat_validity (const char *keyid, gpgme_validity_t *r_valid)
608 {
609 gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
610 HANDLE out;
611 StringBuffer cmd;
612 char *p;
613 char *uat;
614
615 *r_valid = GPGME_VALIDITY_UNKNOWN;
616 p = read_gpg_program ();
617 if (!p)
618 return gpg_error (GPG_ERR_INV_ARG);
619 cmd = p;
620 cmd = cmd + " --with-colons --fixed-list-mode";
621 cmd = cmd + " --list-keys " + "\"" + keyid + "\"";
622
623 out = create_tmpfile ("tmp_gpg_keys");
624 if (create_process (cmd.getBuffer (), NULL, out, NULL))
625 err = gpg_error (GPG_ERR_MODULE_NOT_FOUND);
626
627 free_if_alloc (p);
628
629 p = map_tmpfile (out, NULL);
630 if ((uat = strstr (p, "uat:"))) {
631 switch (*(uat+4)) {
632 case 'm': *r_valid = GPGME_VALIDITY_MARGINAL; break;
633 case 'f':
634 case 'u': *r_valid = GPGME_VALIDITY_FULL; break;
635 default : *r_valid = GPGME_VALIDITY_UNDEFINED; break;
636 }
637 }
638
639 free_if_alloc (p);
640 CloseHandle (out);
641 return err;
642 }
643
644
645 static gpgme_error_t
646 clip_store_data (char *tmp_outname, DWORD outlen)
647 {
648 gpgme_data_t in;
649 gpgme_error_t err;
650
651 get_temp_name (tmp_outname, outlen-1, NULL);
652 err = gpg_data_new_from_clipboard (&in, 0);
653 if (err)
654 return err;
655 err = gpg_data_release_and_set_file (in, tmp_outname);
656 return err;
657 }
658
659
660 /* Extract all recipients from the file @file.
661 Return value: 0 on success. */
662 static gpgme_error_t
663 file_extract_recipient (const char *file, gpgme_recipient_t *r_list)
664 {
665 PACKET *pkt;
666 PKT_pubkey_enc *enc;
667 gpg_iobuf_t inp = NULL;
668 armor_filter_context_t afx;
669 gpgme_recipient_t l;
670 int rc = 0, quit=0;
671
672 if (!file || !r_list) {
673 log_debug ("do_list_packets: !r_list || !file");
674 return gpgme_error (GPG_ERR_INV_ARG);
675 }
676
677 *r_list = NULL;
678 inp = gpg_iobuf_open (file);
679 if (!inp)
680 return gpgme_err_code_from_errno (errno);
681 gpg_iobuf_ioctl (inp, 3, 1, NULL); /* disable cache */
682 if (gpg_use_armor_filter (inp)) {
683 memset (&afx, 0, sizeof (afx));
684 gpg_iobuf_push_filter (inp, gpg_armor_filter, &afx);
685 }
686 pkt = (PACKET *)calloc(1, sizeof *pkt);
687 gpg_init_packet (pkt);
688 while (!quit && (rc = gpg_parse_packet (inp, pkt)) != -1) {
689 switch (pkt->pkttype) {
690 case PKT_PUBKEY_ENC:
691 enc = pkt->pkt.pubkey_enc;
692 if (!enc)
693 break;
694 l = (gpgme_recipient_t)calloc (1, sizeof *l);
695 l->keyid = char_alloc (16+1);
696 _snprintf (l->keyid, 16, "%08lX%08lX",
697 enc->keyid[0], enc->keyid[1]);
698 l->pubkey_algo = (gpgme_pubkey_algo_t)enc->pubkey_algo;
699 l->status = 0;
700 l->next = (*r_list);
701 *r_list = l;
702 break;
703
704 case PKT_ENCRYPTED:
705 case PKT_ENCRYPTED_MDC:
706 case PKT_PLAINTEXT:
707 case PKT_COMPRESSED:
708 case PKT_PUBLIC_KEY:
709 case PKT_SECRET_KEY:
710 quit = 1;
711 break;
712
713 default:
714 break;
715 }
716 gpg_free_packet (pkt);
717 gpg_init_packet (pkt);
718 }
719 gpg_iobuf_close (inp);
720 safe_free (pkt);
721 return 0;
722 }
723
724
725 /* Either extract the list of recipients from the file @file or
726 if the string is NULL, try to extract them from the clipboard.
727 Return value: 0 on success. */
728 gpgme_error_t
729 gpg_get_recipients (const char *file, gpgme_recipient_t *r_list)
730 {
731 gpgme_error_t err;
732 char tmp[MAX_PATH+1];
733
734 if (!file) {
735 clip_store_data (tmp, DIM (tmp)-2);
736 err = file_extract_recipient (tmp, r_list);
737 DeleteFile (tmp);
738 }
739 else
740 err = file_extract_recipient (file, r_list);
741 return err;
742 }
743
744
745 /* Try to find a subpacket with the given id @subpktid
746 inside the key @key.
747 Return value: 0 on success. */
748 gpgme_error_t
749 gpg_find_key_subpacket (const char *key, int subpktid, char **value)
750 {
751 gpgme_error_t err = gpg_error (GPG_ERR_NO_ERROR);
752 StringBuffer cmd;
753 HANDLE out;
754 const char *spk;
755 char *p;
756
757 *value = NULL;
758 p = read_gpg_program ();
759 cmd = p;
760 cmd = cmd + " --with-colons --no-options --list-options ";
761 cmd = cmd + "show-sig-subpackets=" + subpktid + " --list-sigs " + key;
762
763 out = create_tmpfile ("tmp_gpg_subpackets");
764 if (create_process (cmd.getBuffer (), NULL, out, NULL))
765 err = gpg_error (GPG_ERR_MODULE_NOT_FOUND);
766
767 free_if_alloc (p);
768
769 p = map_tmpfile (out, NULL);
770 if (p && (spk=strstr (p, "spk"))) {
771 char *end = strstr (spk, "\n");
772
773 if (end) {
774 *value = char_alloc ((end-spk)+1);
775 memcpy (*value, spk, (end-spk)-1);
776 }
777 }
778
779 free_if_alloc (p);
780 CloseHandle (out);
781 return err;
782 }

Properties

Name Value
svn:eol-style native

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26