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

Contents of /trunk/MyGPGME/editcard.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 23 - (show annotations)
Fri Sep 30 10:10:16 2005 UTC (19 years, 5 months ago) by twoaday
File MIME type: text/plain
File size: 20956 byte(s)
Almost finished phase 1 of the WinPT GPGME port.
Still need more cleanup, comments and tests.


1 /* editcard.c - OpenPGP Smartcard Support
2 * Copyright (C) 2003, 2004 Timo Schulz
3 *
4 * This file is part of MyGPGME.
5 *
6 * MyGPGME 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 * MyGPGME 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 Foundation,
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19 */
20
21 #include <stdio.h>
22
23 #include "gpgme-config.h"
24 #ifdef WITH_EDITCARD
25 #include "ops.h"
26 #include "context.h"
27 #include "util.h"
28 #include "types.h"
29
30
31 #define save_write(val) ((val)? (val) : "")
32
33 #define ON_EVENT(_code, _key) (code == (_code) && !strcmp (key, _key))
34
35
36 static void
37 card_status_handler (gpgme_ctx_t ctx, gpg_status_code_t code, char * args)
38 {
39 if (!ctx || ctx->out_of_core)
40 return;
41
42 switch (code) {
43
44 case STATUS_SC_OP_SUCCESS:
45 ctx->problem = 0;
46 break;
47
48 case STATUS_SC_OP_FAILURE:
49 ctx->problem = -1;
50 break;
51
52 case STATUS_CARDCTRL:
53 break;
54
55 case STATUS_KEY_CREATED:
56 safe_free (ctx->keygen_fpr);
57 ctx->keygen_fpr = strdup (args+2);
58 if (!ctx->keygen_fpr)
59 ctx->out_of_core = 1;
60 break;
61 }
62 } /* card_status_handler */
63
64
65 static const char *
66 statuscard_command_handler (void * opaque, gpg_status_code_t code,
67 const char * key)
68 {
69 gpgme_ctx_t ctx = opaque;
70 gpgme_editcard_t c = ctx->edit_opaque;
71
72 if (!c || ctx->out_of_core)
73 return NULL;
74
75 if (ON_EVENT (STATUS_GET_LINE, "cardctrl.insert_card.okay"))
76 {
77 if (c->card_cb )
78 return c->card_cb (1, c->cb_value);
79 }
80
81 return NULL;
82 } /* statuscard_command_handler */
83
84
85 static const char *
86 changepin_command_handler (void * opaque, gpg_status_code_t code,
87 const char * key)
88 {
89 gpgme_ctx_t ctx = opaque;
90 gpgme_editcard_t c = ctx->edit_opaque;
91 const char * s = "";
92
93 if( !c || ctx->out_of_core )
94 return NULL;
95
96 /*DEBUG3 ("type=%d code=%d key=%s\n", c->type, code, key);*/
97
98 if (ON_EVENT (STATUS_GET_LINE, "cardctrl.insert_card_okay"))
99 {
100 if (c->card_cb)
101 return c->card_cb (1, c->cb_value);
102 }
103 if (ON_EVENT (STATUS_GET_LINE, "cardedit.prompt")) {
104
105 }
106 if (ON_EVENT (STATUS_GET_LINE, "cardutil.change_pin.menu"))
107 {
108 if (c->cnt == 0) {
109 c->cnt++;
110 switch (ctx->edit_cmd) {
111 case GPGME_EDITCARD_CHUPIN: return "1";
112 case GPGME_EDITCARD_UNBPIN: return "2";
113 case GPGME_EDITCARD_CHAPIN: return "3";
114 default: c->cnt = 0; return "Q";
115 }
116 }
117 else if (c->cnt) {
118 c->cnt = 0;
119 return "Q";
120 }
121 }
122 if (ctx->edit_cmd == GPGME_EDITCARD_CHUPIN)
123 {
124 if (ON_EVENT (STATUS_GET_HIDDEN, "passphrase.pin.ask")) {
125 s = c->u.pin.pinold;
126 c->cnt++;
127 }
128 if (ON_EVENT (STATUS_GET_HIDDEN, "passphrase.pin.new.ask")) {
129 s = c->u.pin.pinnew;
130 c->cnt++;
131 }
132 if (ON_EVENT (STATUS_GET_HIDDEN, "passphrase.pin.repeat")) {
133 s = c->u.pin.pinnew;
134 c->cnt++;
135 }
136 return s;
137 }
138 else if (ctx->edit_cmd == GPGME_EDITCARD_CHAPIN)
139 {
140 if (ON_EVENT (STATUS_GET_HIDDEN, "passphrase.adminpin.ask")) {
141 s = c->u.pin.pinold;
142 c->cnt++;
143 }
144 if (ON_EVENT (STATUS_GET_HIDDEN, "passphrase.adminpin.new.ask")) {
145 s = c->u.pin.pinnew;
146 c->cnt++;
147 }
148 if (ON_EVENT (STATUS_GET_HIDDEN, "passphrase.pin.repeat")) {
149 s = c->u.pin.pinnew;
150 c->cnt++;
151 }
152 return s;
153 }
154 else if (ctx->edit_cmd == GPGME_EDITCARD_UNBPIN)
155 {
156 /* todo */
157 }
158
159 return NULL;
160 } /* changepin_command_handler */
161
162
163 static const char *
164 editcard_command_handler (void * opaque, gpg_status_code_t code, const char * key)
165 {
166 gpgme_ctx_t ctx = opaque;
167 gpgme_editcard_t c = ctx->edit_opaque;
168
169 /*DEBUG3 ("type=%d code=%d key=%s\n", c->type, code, key);*/
170
171 if (!c || ctx->out_of_core)
172 return NULL;
173
174 if (ON_EVENT (STATUS_GET_LINE, "cardctrl.insert_card.okay")) {
175 if (c->card_cb)
176 return c->card_cb (1, c->cb_value);
177 }
178
179 if (ON_EVENT (STATUS_GET_LINE, "cardedit.prompt"))
180 {
181 if (c->cnt == 0) /* first switch in the admin mode */
182 {
183 c->cnt++;
184 return "admin";
185 }
186 if (c->cnt == 1) /* then run the send command */
187 {
188 c->cnt++;
189 switch (ctx->edit_cmd)
190 {
191 case GPGME_EDITCARD_NAME: return "name";
192 case GPGME_EDITCARD_KEYURL: return "url";
193 case GPGME_EDITCARD_LOGIN: return "login";
194 case GPGME_EDITCARD_SEX: return "sex";
195 case GPGME_EDITCARD_LANG: return "lang";
196 case GPGME_EDITCARD_GENKEY: return "generate";
197 default: return "quit";
198 }
199 }
200 else if (c->cnt >= 2) /* done: send exit */
201 {
202 c->cnt = 0;
203 return "quit";
204 }
205 }
206 if (c->cnt > 0 && code == STATUS_GET_HIDDEN)
207 {
208 if (!strcmp (key, "passphrase.adminpin.ask"))
209 return c->apin;
210 if (!strcmp (key, "passphrase.pin.ask"))
211 return c->upin;
212 }
213 switch (ctx->edit_cmd)
214 {
215 case GPGME_EDITCARD_NAME:
216 if (ON_EVENT (STATUS_GET_LINE, "keygen.smartcard.surname"))
217 return save_write (c->u.edit.surname);
218 else if (ON_EVENT (STATUS_GET_LINE, "keygen.smartcard.givenname"))
219 return save_write (c->u.edit.givenname);
220 break;
221
222 case GPGME_EDITCARD_KEYURL:
223 if (ON_EVENT (STATUS_GET_LINE, "cardedit.change_url"))
224 return save_write (c->u.edit.keyurl);
225 break;
226
227 case GPGME_EDITCARD_LOGIN:
228 if (ON_EVENT (STATUS_GET_LINE, "cardedit.change_login"))
229 return save_write (c->u.edit.login);
230 break;
231
232 case GPGME_EDITCARD_SEX:
233 if (ON_EVENT (STATUS_GET_LINE, "cardedit.change_sex"))
234 {
235 if (c->u.edit.sex != 'M'
236 && c->u.edit.sex != 'F'
237 && c->u.edit.sex != ' ')
238 return " ";
239 else
240 {
241 static char buf[2];
242 buf[0] = c->u.edit.sex; buf[1] = 0;
243 return buf;
244 }
245 }
246 break;
247
248 case GPGME_EDITCARD_LANG:
249 if (ON_EVENT (STATUS_GET_LINE, "cardedit.change_lang"))
250 return save_write (c->u.edit.lang);
251 break;
252
253 case GPGME_EDITCARD_GENKEY:
254 if (ON_EVENT (STATUS_GET_HIDDEN, "passphrase.enter"))
255 return c->keygen.passwd;
256 if (ON_EVENT (STATUS_GET_BOOL, "cardedit.genkeys.backup_enc") ||
257 ON_EVENT (STATUS_GET_LINE, "cardedit.genkeys.backup_enc"))
258 return c->keygen.flags & GPGME_CARDFLAG_BAKENC? "Y" : "N";
259 if (ON_EVENT (STATUS_GET_BOOL, "cardedit.genkeys.replace_keys"))
260 {
261 if (! (c->keygen.flags & GPGME_CARDFLAG_REPLACE))
262 c->cancel = 1;
263 return c->keygen.flags & GPGME_CARDFLAG_REPLACE? "Y" : "N";
264 }
265 else if (ON_EVENT (STATUS_GET_LINE, "keygen.valid"))
266 return save_write (c->keygen.expdate);
267 else if (ON_EVENT (STATUS_GET_LINE, "keygen.name"))
268 return save_write (c->keygen.name);
269 else if (ON_EVENT (STATUS_GET_LINE, "keygen.email"))
270 return save_write (c->keygen.email);
271 else if (ON_EVENT (STATUS_GET_LINE, "keygen.comment"))
272 return save_write (c->keygen.comment);
273 break;
274
275 default:
276 return NULL;
277 }
278 return NULL;
279 } /* editcard_command_handler */
280
281
282 static gpgme_error_t
283 changepin_start (gpgme_ctx_t ctx)
284 {
285 gpgme_error_t rc;
286
287 ctx->pending = 1;
288
289 _gpgme_gpg_release (&ctx->gpg);
290 rc = _gpgme_gpg_new (&ctx->gpg);
291 if (rc)
292 return rc;
293
294 _gpgme_gpg_set_status_handler (ctx->gpg, card_status_handler, ctx);
295 _gpgme_gpg_set_command_handler (ctx->gpg, changepin_command_handler, ctx);
296
297 _gpgme_gpg_add_arg (ctx->gpg, "--change-pin");
298
299 rc = _gpgme_gpg_spawn (ctx->gpg, ctx);
300 if (rc) {
301 ctx->pending = 0;
302 _gpgme_gpg_release (&ctx->gpg);
303 }
304
305 return rc;
306 } /* changepin_start */
307
308
309 gpgme_error_t
310 gpgme_op_changepin( gpgme_ctx_t ctx )
311 {
312 gpgme_error_t rc;
313
314 rc = changepin_start (ctx);
315 if (!rc) {
316 gpgme_wait (ctx, 1);
317 ctx->pending = 0;
318 if (gpgme_get_process_rc (ctx))
319 rc = mk_error (Internal_GPG_Problem);
320 else if (ctx->problem)
321 rc = mk_error (SC_Failure);
322 }
323 return rc;
324 } /* gpgme_op_changepin */
325
326
327 gpgme_error_t
328 gpgme_changepin_set (gpgme_editcard_t chpin, int which,
329 const char * pinold, const char * pinnew)
330 {
331 if (!chpin)
332 return mk_error (Invalid_Value);
333 chpin->type = which;
334 chpin->u.pin.pinnew = pinnew;
335 chpin->u.pin.pinold = pinold;
336 return 0;
337 } /* gpgme_changepin_set */
338
339
340 static gpgme_error_t
341 editcard_start (gpgme_ctx_t ctx)
342 {
343 gpgme_error_t rc;
344
345 ctx->pending = 1;
346
347 _gpgme_gpg_release (&ctx->gpg);
348 rc = _gpgme_gpg_new (&ctx->gpg);
349 if (rc)
350 return rc;
351
352 _gpgme_gpg_set_status_handler (ctx->gpg, card_status_handler, ctx);
353 if (ctx->edit_cmd)
354 _gpgme_gpg_set_command_handler (ctx->gpg, editcard_command_handler, ctx);
355
356 _gpgme_gpg_add_arg (ctx->gpg, "--card-edit");
357
358 rc = _gpgme_gpg_spawn (ctx->gpg, ctx);
359 if (rc) {
360 ctx->pending = 0;
361 _gpgme_gpg_release (&ctx->gpg);
362 }
363
364 return rc;
365 } /* editcard_start */
366
367
368 gpgme_error_t
369 gpgme_op_editcard (gpgme_ctx_t ctx)
370 {
371 gpgme_error_t rc;
372
373 rc = editcard_start (ctx);
374 if (!rc) {
375 gpgme_wait (ctx, 1);
376 ctx->pending = 0;
377 if (((gpgme_editcard_t)ctx->edit_opaque)->cancel)
378 rc = mk_error (Canceled);
379 else if (ctx->keygen_fpr)
380 rc = mk_error (No_Error);
381 else if (gpgme_get_process_rc (ctx))
382 rc = mk_error (Internal_GPG_Problem);
383 else if (ctx->problem)
384 rc = mk_error (SC_Failure);
385 }
386 return rc;
387 } /* gpgme_op_editcard */
388
389
390 gpgme_error_t
391 gpgme_editcard_new (gpgme_editcard_t * r_ctx)
392 {
393 gpgme_editcard_t ctx;
394
395 if (!r_ctx)
396 return mk_error (Invalid_Value);
397 *r_ctx = NULL;
398 ctx = calloc (1, sizeof * ctx);
399 if (!ctx)
400 return mk_error (Out_Of_Core);
401 *r_ctx = ctx;
402 return 0;
403 } /* gpgme_editcard_new */
404
405
406 void
407 gpgme_editcard_release (gpgme_editcard_t ctx)
408 {
409 if (!ctx)
410 return;
411 safe_free (ctx->keygen.name);
412 safe_free (ctx->keygen.comment);
413 safe_free (ctx->keygen.email);
414 safe_free (ctx->keygen.expdate);
415 safe_free (ctx );
416 } /* gpgme_editcard_release */
417
418
419 gpgme_error_t
420 gpgme_editcard_set_passwd (gpgme_editcard_t ctx, const char * passwd)
421 {
422 if (!ctx)
423 return mk_error (Invalid_Value);
424 ctx->type = GPGME_EDITCARD_GENKEY;
425 ctx->keygen.passwd = passwd;
426 return 0;
427 }
428
429 gpgme_error_t
430 gpgme_editcard_set_keygen_params (gpgme_editcard_t ctx, int flags,
431 const char * name, const char * email,
432 const char * comment, const char * expdate)
433 {
434 char * p;
435
436 if (!ctx)
437 return mk_error (Invalid_Value);
438 if (!name || !email)
439 return mk_error (Invalid_Value);
440
441 ctx->type = GPGME_EDITCARD_GENKEY;
442 ctx->keygen.flags = flags;
443
444 p = ctx->keygen.name = strdup (name);
445 if (!p)
446 return mk_error (Out_Of_Core);
447 p = ctx->keygen.email = strdup (email);
448 if (!p)
449 return mk_error (Out_Of_Core);
450 p = ctx->keygen.comment = comment? strdup (comment) : strdup ("");
451 if (!p)
452 return mk_error (Out_Of_Core);
453 p = ctx->keygen.expdate = expdate? strdup (expdate) : strdup ("0");
454 if (!p)
455 return mk_error(Out_Of_Core);
456 return 0;
457 } /* gpgme_editcard_set_keygen_params */
458
459
460 void
461 gpgme_editcard_set_callback (gpgme_editcard_t ctx,
462 const char *(*cb) (int code, void * opaque),
463 void * cb_value)
464 {
465 if (!ctx)
466 return;
467 ctx->card_cb = cb;
468 ctx->cb_value = cb_value;
469 } /* gpgme_editcard_set_callback */
470
471
472 gpgme_error_t
473 gpgme_editcard_control (gpgme_editcard_t ctx, int cmd, const void * val)
474 {
475 const char * p;
476
477 if (!ctx)
478 return mk_error (Invalid_Value);
479
480 switch (cmd) {
481 case GPGME_EDITCARD_NAME:
482 ctx->u.edit.givenname = (const char *)val;
483 break;
484
485 case GPGME_EDITCARD_NAME2:
486 ctx->u.edit.surname = (const char *)val;
487 break;
488
489 case GPGME_EDITCARD_KEYURL:
490 ctx->u.edit.keyurl = (const char *)val;
491 break;
492
493 case GPGME_EDITCARD_LOGIN:
494 ctx->u.edit.login = (const char *)val;
495 break;
496
497 case GPGME_EDITCARD_SEX:
498 p = (const char *)val;
499 ctx->u.edit.sex = *p;
500 break;
501
502 case GPGME_EDITCARD_LANG:
503 ctx->u.edit.lang = (const char *)val;
504 break;
505
506 case GPGME_EDITCARD_APIN:
507 ctx->apin = (const char *)val;
508 break;
509
510 case GPGME_EDITCARD_UPIN:
511 ctx->upin = (const char *)val;
512 break;
513
514 default:
515 return mk_error (Invalid_Mode);
516 }
517 /* in some cases we do not want to change the command ID:
518 1. when the given name will be set but the surname command
519 already set the command ID.
520 2. the pin is stored because the pin is no real command */
521 if (cmd == GPGME_EDITCARD_NAME2
522 || cmd == GPGME_EDITCARD_APIN
523 || cmd == GPGME_EDITCARD_UPIN)
524 ;
525 else
526 ctx->type = cmd;
527 return 0;
528 } /* gpgme_editcard_control */
529
530
531 static void
532 statuscard_colon_handler( gpgme_ctx_t ctx, char * line )
533 {
534 enum rectype_t {
535 CARD_None = 0,
536 CARD_AID,
537 CARD_Version,
538 CARD_Vendor,
539 CARD_Serial,
540 CARD_Name,
541 CARD_Lang,
542 CARD_Sex,
543 CARD_Url,
544 CARD_Login,
545 CARD_MaxPinLen,
546 CARD_SigCount,
547 CARD_Fpr
548 };
549 enum rectype_t rectype;
550 gpgme_card_t card;
551 char * t, * p, * pend;
552 int field = 0;
553
554 if( ctx->out_of_core )
555 return;
556
557 if( !line )
558 return ; /* EOF */
559
560 if( !ctx->card && gpgme_card_new( &ctx->card ) ) {
561 ctx->out_of_core = 1;
562 return;
563 }
564 card = ctx->card;
565
566 for( p = line; p; p = pend ) {
567 field++;
568 pend = strchr( p, ':' );
569 if( pend )
570 *pend++ = 0;
571
572 if( field == 1 ) {
573 if( !strcmp( p, "AID" ) )
574 rectype = CARD_AID;
575 else if( !strcmp( p, "version" ) )
576 rectype = CARD_Version;
577 else if( !strcmp( p, "vendor" ) )
578 rectype = CARD_Vendor;
579 else if( !strcmp( p, "serial" ) )
580 rectype = CARD_Serial;
581 else if( !strcmp( p, "name" ) )
582 rectype = CARD_Name;
583 else if( !strcmp( p, "lang" ) )
584 rectype = CARD_Lang;
585 else if( !strcmp( p, "sex" ) )
586 rectype = CARD_Sex;
587 else if( !strcmp( p, "url" ) )
588 rectype = CARD_Url;
589 else if( !strcmp( p, "login" ) )
590 rectype = CARD_Login;
591 else if( !strcmp( p, "maxpinlen" ) )
592 rectype = CARD_MaxPinLen;
593 else if( !strcmp( p, "sigcount" ) )
594 rectype = CARD_SigCount;
595 else if( !strcmp( p, "fpr" ) )
596 rectype = CARD_Fpr;
597 else
598 rectype = CARD_None;
599 }
600 switch( rectype ) {
601 case CARD_AID:
602 if( field == 2 ) {
603 t = card->aid = strdup( p );
604 if( !t )
605 ctx->out_of_core = 1;
606 }
607 break;
608 case CARD_Version:
609 if( field == 2 ) {
610 t = card->version = strdup( p );
611 if( !t )
612 ctx->out_of_core = 1;
613 }
614 break;
615 case CARD_Vendor:
616 if( field == 3 ) {
617 t = card->vendor = strdup( p );
618 if( !t )
619 ctx->out_of_core = 1;
620 }
621 break;
622 case CARD_Serial:
623 if( field == 2 ) {
624 t = card->serial = strdup( p );
625 if( !t )
626 ctx->out_of_core = 1;
627 }
628 break;
629 case CARD_Name:
630 if( field == 2 ) {
631 t = card->givenname = strdup( p );
632 if( !t )
633 ctx->out_of_core = 1;
634 }
635 else if( field == 3 ) {
636 t = card->surname = strdup( p );
637 if( !t )
638 ctx->out_of_core = 1;
639 }
640 break;
641 case CARD_Lang:
642 if( field == 2 )
643 card->lang = strdup( p ) ;
644 break;
645 case CARD_Sex:
646 if( field == 2 )
647 card->sex = *p;
648 break;
649 case CARD_Url:
650 if( field == 2 ) {
651 safe_free( card->url );
652 card->url = calloc( 1, strlen( p ) + 1 );
653 if( !card->url ) {
654 ctx->out_of_core = 1;
655 return;
656 }
657 _gpgme_decode_c_string (p, &card->url, strlen (p) + 1);
658 }
659 break;
660 case CARD_Login:
661 if( field == 2 ) {
662 t = card->login = strdup( p );
663 if( !t )
664 ctx->out_of_core = 1;
665 }
666 break;
667 case CARD_MaxPinLen:
668 break;
669 case CARD_SigCount:
670 if( field == 2 )
671 card->sig_count = atol( p );
672 break;
673 case CARD_Fpr:
674 if( field == 2 || field == 3 || field == 4 ) {
675 t = card->fpr[ctx->tmp_i++] = strdup( p );
676 if( !t )
677 ctx->out_of_core = 1;
678 }
679 break;
680 }
681 }
682 } /* statuscard_colon_handler */
683
684
685 static gpgme_error_t
686 status_card_start( gpgme_ctx_t ctx, gpgme_data_t tmp_out )
687 {
688 gpgme_error_t rc;
689
690 if( !ctx || !tmp_out )
691 return mk_error( Invalid_Value );
692 _gpgme_data_set_mode( tmp_out, GPGME_DATA_MODE_IN );
693
694 ctx->pending = 1;
695
696 _gpgme_gpg_release( &ctx->gpg );
697 rc = _gpgme_gpg_new( &ctx->gpg );
698 if( rc )
699 return rc;
700
701 _gpgme_gpg_set_command_handler( ctx->gpg, statuscard_command_handler, ctx );
702 if( ctx->use_logging )
703 _gpgme_gpg_set_logging_handler( ctx->gpg, ctx );
704
705 _gpgme_gpg_add_arg( ctx->gpg, "--with-colons" );
706 _gpgme_gpg_add_arg( ctx->gpg, "--card-status" );
707 _gpgme_gpg_add_arg( ctx->gpg, "--output" );
708 _gpgme_gpg_add_arg( ctx->gpg, "-" );
709 _gpgme_gpg_add_data( ctx->gpg, tmp_out, 1 );
710
711 rc = _gpgme_gpg_spawn( ctx->gpg, ctx );
712 if( rc ) {
713 ctx->pending = 0;
714 _gpgme_gpg_release( &ctx->gpg );
715 }
716 return rc;
717 } /* status_card_start */
718
719
720 gpgme_error_t
721 gpgme_op_statuscard( gpgme_ctx_t ctx, gpgme_card_t * ret_card )
722 {
723 gpgme_data_t tmp = NULL;
724 gpgme_error_t rc;
725 char buf[200];
726
727 if (!ret_card || !ctx)
728 return mk_error (Invalid_Value);
729
730 rc = gpgme_data_new (&tmp);
731 if (rc)
732 return rc;
733
734 rc = status_card_start( ctx, tmp );
735 if( !rc ) {
736 gpgme_wait( ctx, 1 );
737 ctx->pending = 0;
738 if( gpgme_get_process_rc( ctx ) )
739 rc = mk_error( Internal_GPG_Problem );
740 }
741
742 gpgme_data_rewind( tmp );
743 while( !rc && gpgme_data_readline( tmp, buf, sizeof buf-2 ) )
744 statuscard_colon_handler( ctx, buf );
745 gpgme_data_release( tmp );
746 ctx->tmp_i = 0;
747 *ret_card = ctx->card;
748 return rc;
749 } /* gpgme_op_statuscard */
750
751
752 gpgme_error_t
753 gpgme_card_new( gpgme_card_t * ret_card )
754 {
755 gpgme_card_t c;
756
757 if (!ret_card)
758 return mk_error( Invalid_Value );
759 *ret_card = NULL;
760 c = calloc( 1, sizeof * c );
761 if( !c )
762 return mk_error( Out_Of_Core );
763 *ret_card = c;
764 return 0;
765 } /* gpgme_card_new */
766
767
768 void
769 gpgme_card_release( gpgme_card_t card )
770 {
771 int i;
772
773 if( !card )
774 return;
775 safe_free( card->aid );
776 safe_free( card->version );
777 safe_free( card->lang );
778 safe_free( card->login );
779 for( i=0; i < 3; i++ )
780 safe_free( card->fpr[i] );
781 safe_free( card->surname );
782 safe_free( card->givenname );
783 safe_free( card->serial );
784 safe_free( card->vendor );
785 safe_free( card->url );
786 safe_free( card );
787 } /* gpgme_card_release */
788
789
790 const char *
791 gpgme_card_get_string_attr( gpgme_card_t card, gpgme_attr_t what,
792 void ** reserved, int idx )
793 {
794 const char * s;
795
796 if (!card)
797 return NULL;
798
799 switch( what ) {
800 case GPGME_ATTR_CARD_AID:
801 s=card->aid;
802 break;
803
804 case GPGME_ATTR_CARD_VER:
805 if (idx == 0)
806 s=card->version;
807 else {
808 if (card->ver[0] == 0) {
809 int pos = card->version[0] == '0' ? 1 : 0;
810 int n = 0;
811 memcpy (card->ver, card->version+pos, 2-pos);
812 card->ver[2-pos] = '.';
813 if (card->version[2] == '0')
814 n = 1;
815 memcpy (card->ver+(2-pos+1), card->version+2+n, 2-n);
816 }
817 s = card->ver;
818 }
819 break;
820
821 case GPGME_ATTR_CARD_VENDOR:
822 s=card->vendor;
823 break;
824
825 case GPGME_ATTR_CARD_NAME:
826 s=card->givenname;
827 break;
828
829 case GPGME_ATTR_CARD_NAME2:
830 s=card->surname;
831 break;
832
833 case GPGME_ATTR_CARD_LANG:
834 s=card->lang;
835 break;
836
837 case GPGME_ATTR_CARD_URL:
838 s=card->url;
839 break;
840
841 case GPGME_ATTR_CARD_LOGIN:
842 s=card->login;
843 break;
844
845 case GPGME_ATTR_CARD_FPR:
846 if (idx >= 0 && idx <= 3)
847 s=card->fpr[idx];
848 else
849 s=NULL;
850 break;
851
852 case GPGME_ATTR_CARD_SERIAL:
853 s=card->serial;
854 if (idx == 1) {
855 while (s && *s && *s == '0')
856 s++;
857 }
858 break;
859
860 default:
861 s=NULL;
862 break;
863 }
864 return s;
865 } /* gpgme_card_get_string_attr */
866
867
868 unsigned long
869 gpgme_card_get_ulong_attr( gpgme_card_t card, gpgme_attr_t what,
870 void ** reserved, int idx )
871 {
872 unsigned long t;
873 const char *s;
874
875 if( !card )
876 return 0;
877
878 switch (what) {
879 case GPGME_ATTR_CARD_SIGCOUNT:
880 t = card->sig_count;
881 break;
882
883 case GPGME_ATTR_CARD_SEX:
884 t = card->sex;
885 break;
886
887 case GPGME_ATTR_CARD_SERIAL:
888 s = card->serial;
889 while (s && *s && *s == '0')
890 s++;
891 t = atol (s);
892 break;
893
894 default:
895 t = 0;
896 break;
897 }
898 return t;
899 } /* gpgme_card_get_ulong_attr */
900
901 #endif /* WITH_EDITCARD */

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26