From: Werner Koch Date: Mon, 8 Jan 2001 20:40:25 +0000 (+0000) Subject: More changes and and some new functions X-Git-Tag: gpgme-0-1-4~1 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=d6cd1f97cab9cbb08560825444c1f848ac45f840;p=gpgme.git More changes and and some new functions --- diff --git a/gpgme/ChangeLog b/gpgme/ChangeLog index e69de29..79fed0f 100644 --- a/gpgme/ChangeLog +++ b/gpgme/ChangeLog @@ -0,0 +1,3 @@ +2001-01-05 Werner Koch + + * data.c (gpgme_data_rewind): Allow to rewind data_type_none. diff --git a/gpgme/Makefile.am b/gpgme/Makefile.am index 32b72b4..8365678 100644 --- a/gpgme/Makefile.am +++ b/gpgme/Makefile.am @@ -23,6 +23,7 @@ libgpgme_la_SOURCES = \ sign.c \ key.c key.h \ keylist.c \ + trustlist.c \ import.c \ export.c \ genkey.c \ diff --git a/gpgme/context.h b/gpgme/context.h index e1ff31f..32ed8d5 100644 --- a/gpgme/context.h +++ b/gpgme/context.h @@ -37,6 +37,10 @@ struct key_queue_item_s { struct key_queue_item_s *next; GpgmeKey key; }; +struct trust_queue_item_s { + struct trust_queue_item_s *next; + GpgmeTrustItem item; +}; /* Currently we need it at several places, so we put the definition @@ -57,6 +61,7 @@ struct gpgme_context_s { int verbosity; /* level of verbosity to use */ int use_armor; int use_textmode; + int keylist_mode; ResultType result_type; union { @@ -70,6 +75,7 @@ struct gpgme_context_s { GpgmeKey tmp_key; /* used by keylist.c */ volatile int key_cond; /* something new is available */ struct key_queue_item_s *key_queue; + struct trust_queue_item_s *trust_queue; GpgmePassphraseCb passphrase_cb; void *passphrase_cb_value; @@ -101,6 +107,9 @@ struct user_id_s { struct user_id_s *next; int validity; /* 0 = undefined, 1 = not, 2 = marginal, 3 = full, 4 = ultimate */ + const char *name_part; /* all 3 point into strings behind name */ + const char *email_part; /* or to read-only strings */ + const char *comment_part; char name[1]; }; diff --git a/gpgme/data.c b/gpgme/data.c index 73408f9..48a2eae 100644 --- a/gpgme/data.c +++ b/gpgme/data.c @@ -410,7 +410,8 @@ gpgme_data_rewind ( GpgmeData dh ) if ( !dh ) return mk_error (Invalid_Value); - if (dh->type == GPGME_DATA_TYPE_MEM ) { + if ( dh->type == GPGME_DATA_TYPE_NONE + || dh->type == GPGME_DATA_TYPE_MEM ) { dh->readpos = 0; } else if (dh->type == GPGME_DATA_TYPE_CB) { diff --git a/gpgme/gpgme.c b/gpgme/gpgme.c index 0c814bd..7a2fcbe 100644 --- a/gpgme/gpgme.c +++ b/gpgme/gpgme.c @@ -164,6 +164,24 @@ gpgme_set_textmode ( GpgmeCtx c, int yes ) c->use_textmode = yes; } +/** + * gpgme_set_keylist_mode: + * @c: the context + * @mode: listing mode + * + * This function changes the default behaviour of the keylisting functions. + * Defines values for @mode are: %0 = normal, %1 = fast listing without + * information about key validity. + **/ +void +gpgme_set_keylist_mode ( GpgmeCtx c, int mode ) +{ + if (c) + return; + c->keylist_mode = mode; +} + + /** * gpgme_set_passphrase_cb: * @c: the context diff --git a/gpgme/gpgme.h b/gpgme/gpgme.h index 7190af0..6cb7567 100644 --- a/gpgme/gpgme.h +++ b/gpgme/gpgme.h @@ -58,6 +58,9 @@ typedef struct gpgme_recipients_s *GpgmeRecipients; struct gpgme_key_s; typedef struct gpgme_key_s *GpgmeKey; +struct gpgme_trust_item_s; +typedef struct gpgme_trust_item_s *GpgmeTrustItem; + typedef enum { GPGME_EOF = -1, @@ -107,6 +110,23 @@ typedef enum { GPGME_SIG_MODE_CLEAR = 2 } GpgmeSigMode; +typedef enum { + GPGME_ATTR_KEYID = 1, + GPGME_ATTR_FPR = 2, + GPGME_ATTR_ALGO = 3, + GPGME_ATTR_LEN = 4, + GPGME_ATTR_CREATED = 5, + GPGME_ATTR_EXPIRE = 6, + GPGME_ATTR_OTRUST = 7, + GPGME_ATTR_USERID = 8, + GPGME_ATTR_NAME = 9, + GPGME_ATTR_EMAIL = 10, + GPGME_ATTR_COMMENT = 11, + GPGME_ATTR_VALIDITY= 12, + GPGME_ATTR_LEVEL = 13, + GPGME_ATTR_TYPE = 14 +} GpgmeAttr; + typedef const char *(*GpgmePassphraseCb)(void*, const char *desc, void *r_hd); @@ -124,6 +144,7 @@ GpgmeCtx gpgme_wait (GpgmeCtx c, int hang); char *gpgme_get_notation (GpgmeCtx c); void gpgme_set_armor (GpgmeCtx c, int yes); void gpgme_set_textmode (GpgmeCtx c, int yes); +void gpgme_set_keylist_mode ( GpgmeCtx c, int mode ); void gpgme_set_passphrase_cb (GpgmeCtx c, GpgmePassphraseCb cb, void *cb_value); void gpgme_set_progress_cb (GpgmeCtx c, GpgmeProgressCb cb, void *cb_value); @@ -166,8 +187,21 @@ GpgmeError gpgme_data_write ( GpgmeData dh, const char *buffer, size_t length ); -/* Key functions */ +/* Key and trust functions */ char *gpgme_key_get_as_xml ( GpgmeKey key ); +const char *gpgme_key_get_string_attr ( GpgmeKey key, GpgmeAttr what, + const void *reserved, int idx ); +unsigned long gpgme_key_get_ulong_attr ( GpgmeKey key, GpgmeAttr what, + const void *reserved, int idx ); + +void gpgme_trust_item_release ( GpgmeTrustItem item ); +const char *gpgme_trust_item_get_string_attr ( GpgmeTrustItem item, + GpgmeAttr what, + const void *reserved, int idx ); +int gpgme_trust_item_get_int_attr ( GpgmeTrustItem item, GpgmeAttr what, + const void *reserved, int idx ); + + /* Basic GnuPG functions */ @@ -194,6 +228,10 @@ GpgmeError gpgme_op_genkey_start ( GpgmeCtx c, const char *parms, GpgmeError gpgme_op_keylist_start ( GpgmeCtx c, const char *pattern, int secret_only ); GpgmeError gpgme_op_keylist_next ( GpgmeCtx c, GpgmeKey *r_key ); +GpgmeError gpgme_op_trustlist_start ( GpgmeCtx c, + const char *pattern, int max_level ); +GpgmeError gpgme_op_trustlist_next ( GpgmeCtx c, GpgmeTrustItem *r_item ); + /* Convenience functions for normal usage */ @@ -215,7 +253,7 @@ GpgmeError gpgme_op_genkey ( GpgmeCtx c, const char *parms, /* miscellaneous functions */ const char *gpgme_check_version ( const char *req_version ); const char *gpgme_strerror (GpgmeError err); -const char *gpgme_get_prompt ( GpgmeCtx c, int which ); +void gpgme_register_idle ( void (*fnc)(void) ); #ifdef __cplusplus diff --git a/gpgme/key.c b/gpgme/key.c index 909b5cf..f00f8df 100644 --- a/gpgme/key.c +++ b/gpgme/key.c @@ -31,6 +31,23 @@ #define my_isdigit(a) ( (a) >='0' && (a) <= '9' ) +static const char * +pkalgo_to_string ( int algo ) +{ + switch (algo) { + case 1: + case 2: + case 3: return "RSA"; + case 16: + case 20: return "ElG"; + case 17: return "DSA"; + default: return "Unknown"; + } +} + + + + GpgmeError _gpgme_key_new( GpgmeKey *r_key ) { @@ -88,6 +105,97 @@ _gpgme_key_release ( GpgmeKey key ) xfree (key); } +static char * +set_user_id_part ( char *tail, const char *buf, size_t len ) +{ + while ( len && (buf[len-1] == ' ' || buf[len-1] == '\t') ) + len--; + for ( ; len; len--) + *tail++ = *buf++; + *tail++ = 0; + return tail; +} + + +static void +parse_user_id ( struct user_id_s *uid, char *tail ) +{ + const char *s, *start=NULL; + int in_name = 0; + int in_email = 0; + int in_comment = 0; + + for (s=uid->name; *s; s++ ) { + if ( in_email ) { + if ( *s == '<' ) + in_email++; /* not legal but anyway */ + else if (*s== '>') { + if ( !--in_email ) { + if (!uid->email_part) { + uid->email_part = tail; + tail = set_user_id_part ( tail, start, s-start ); + } + } + } + } + else if ( in_comment ) { + if ( *s == '(' ) + in_comment++; + else if (*s== ')') { + if ( !--in_comment ) { + if (!uid->comment_part) { + uid->comment_part = tail; + tail = set_user_id_part ( tail, start, s-start ); + } + } + } + } + else if ( *s == '<' ) { + if ( in_name ) { + if ( !uid->name_part ) { + uid->name_part = tail; + tail = set_user_id_part (tail, start, s-start ); + } + in_name = 0; + } + in_email = 1; + start = s+1; + } + else if ( *s == '(' ) { + if ( in_name ) { + if ( !uid->name_part ) { + uid->name_part = tail; + tail = set_user_id_part (tail, start, s-start ); + } + in_name = 0; + } + in_comment = 1; + start = s+1; + } + else if ( !in_name && *s != ' ' && *s != '\t' ) { + in_name = 1; + start = s; + } + } + + if ( in_name ) { + if ( !uid->name_part ) { + uid->name_part = tail; + tail = set_user_id_part (tail, start, s-start ); + } + } + + /* let unused parts point to an EOS */ + tail--; + if (!uid->name_part) + uid->name_part = tail; + if (!uid->email_part) + uid->email_part = tail; + if (!uid->comment_part) + uid->comment_part = tail; + +} + /* * Take a name from the --with-colon listing, remove certain escape sequences * sequences and put it into the list of UIDs @@ -99,12 +207,17 @@ _gpgme_key_append_name ( GpgmeKey key, const char *s ) char *d; assert (key); - /* we can malloc a buffer of the same length, because the converted - * string will never be larger */ - uid = xtrymalloc ( sizeof *uid + strlen (s) ); + /* we can malloc a buffer of the same length, because the + * converted string will never be larger. Actually we allocate it + * twice the size, so that we are able to store the parsed stuff + * there too */ + uid = xtrymalloc ( sizeof *uid + 2*strlen (s)+3 ); if ( !uid ) return mk_error (Out_Of_Core); uid->validity = 0; + uid->name_part = NULL; + uid->email_part = NULL; + uid->comment_part = NULL; d = uid->name; while ( *s ) { @@ -152,6 +265,8 @@ _gpgme_key_append_name ( GpgmeKey key, const char *s ) *d++ = *s++; } } + *d++ = 0; + parse_user_id ( uid, d ); uid->next = key->uids; key->uids = uid; @@ -183,76 +298,6 @@ add_tag_and_string ( GpgmeData d, const char *tag, const char *string ) add_ctag (d, tag); } -static void -add_user_id_name ( GpgmeData d, const char *buf, size_t len ) -{ - while ( len && (buf[len-1] == ' ' || buf[len-1] == '\t') ) - len--; - if (len) { - add_otag (d, "name" ); - _gpgme_data_append_for_xml ( d, buf, len ); - add_ctag (d, "name"); - } -} - - -static void -add_user_id ( GpgmeData d, const char *string ) -{ - const char *s, *start=NULL; - int in_name = 0; - int in_email = 0; - int in_comment = 0; - - for (s=string; *s; s++ ) { - if ( in_email ) { - if ( *s == '<' ) - in_email++; /* not legal but anyway */ - else if (*s== '>') { - if ( !--in_email ) { - _gpgme_data_append_for_xml ( d, start, s-start ); - add_ctag (d, "email"); - } - } - } - else if ( in_comment ) { - if ( *s == '(' ) - in_comment++; - else if (*s== ')') { - if ( !--in_comment ) { - _gpgme_data_append_for_xml ( d, start, s-start ); - add_ctag (d, "comment"); - } - } - } - else if ( *s == '<' ) { - if ( in_name ) { - add_user_id_name (d, start, s-start ); - in_name = 0; - } - in_email = 1; - add_otag ( d, "email" ); - start = s+1; - } - else if ( *s == '(' ) { - if ( in_name ) { - add_user_id_name (d, start, s-start ); - in_name = 0; - } - in_comment = 1; - add_otag ( d, "comment" ); - start = s+1; - } - else if ( !in_name && *s != ' ' && *s != '\t' ) { - in_name = 1; - start = s; - } - } - - if ( in_name ) - add_user_id_name (d, start, s-start ); -} - static void add_tag_and_uint ( GpgmeData d, const char *tag, unsigned int val ) { @@ -300,7 +345,12 @@ gpgme_key_get_as_xml ( GpgmeKey key ) for ( u = key->uids; u; u = u->next ) { _gpgme_data_append_string (d, " \n"); add_tag_and_string ( d, "raw", u->name ); - add_user_id ( d, u->name ); + if ( *u->name_part ) + add_tag_and_string ( d, "name", u->name_part ); + if ( *u->email_part ) + add_tag_and_string ( d, "email", u->email_part ); + if ( *u->comment_part ) + add_tag_and_string ( d, "comment", u->comment_part ); _gpgme_data_append_string (d, " \n"); } @@ -320,6 +370,95 @@ gpgme_key_get_as_xml ( GpgmeKey key ) } +const char * +gpgme_key_get_string_attr ( GpgmeKey key, GpgmeAttr what, + const void *reserved, int idx ) +{ + const char *val = NULL; + struct user_id_s *u; + + if (!key) + return NULL; + if (reserved) + return NULL; + if (idx < 0) + return NULL; + + switch (what) { + case GPGME_ATTR_KEYID: + val = key->keys.keyid; + break; + case GPGME_ATTR_FPR: + val = key->keys.fingerprint; + break; + case GPGME_ATTR_ALGO: + val = pkalgo_to_string (key->keys.key_algo); + break; + case GPGME_ATTR_LEN: + case GPGME_ATTR_CREATED: + case GPGME_ATTR_EXPIRE: + break; /* use another get function */ + case GPGME_ATTR_OTRUST: + val = "[fixme]"; + break; + case GPGME_ATTR_USERID: + for (u=key->uids; u && idx; u=u->next, idx-- ) + ; + val = u? u->name : NULL; + break; + case GPGME_ATTR_NAME: + for (u=key->uids; u && idx; u=u->next, idx-- ) + ; + val = u? u->name_part : NULL; + break; + case GPGME_ATTR_EMAIL: + for (u=key->uids; u && idx; u=u->next, idx-- ) + ; + val = u? u->email_part : NULL; + break; + case GPGME_ATTR_COMMENT: + for (u=key->uids; u && idx; u=u->next, idx-- ) + ; + val = u? u->comment_part : NULL; + break; + case GPGME_ATTR_VALIDITY: + val = "[foxme]"; + break; + case GPGME_ATTR_LEVEL: /* not used here */ + case GPGME_ATTR_TYPE: + break; + } + return val; +} + + +unsigned long +gpgme_key_get_ulong_attr ( GpgmeKey key, GpgmeAttr what, + const void *reserved, int idx ) +{ + unsigned long val = 0; + if (!key) + return 0; + if (reserved) + return 0; + if (idx < 0) + return 0; + + switch (what) { + case GPGME_ATTR_ALGO: + val = (unsigned long)key->keys.key_algo; + break; + case GPGME_ATTR_LEN: + val = (unsigned long)key->keys.key_len; + break; + case GPGME_ATTR_CREATED: + val = key->keys.timestamp < 0? 0L:(unsigned long)key->keys.timestamp; + break; + default: + break; + } + return val; +} diff --git a/gpgme/keylist.c b/gpgme/keylist.c index 5cb124e..b4d4303 100644 --- a/gpgme/keylist.c +++ b/gpgme/keylist.c @@ -368,7 +368,8 @@ gpgme_op_keylist_start ( GpgmeCtx c, const char *pattern, int secret_only ) _gpgme_gpg_add_arg ( c->gpg, "--verbose" ); _gpgme_gpg_add_arg ( c->gpg, "--with-colons" ); _gpgme_gpg_add_arg ( c->gpg, "--with-fingerprint" ); - /*_gpgme_gpg_add_arg ( c->gpg, "--fast-list-mode" );*/ + if (c->keylist_mode == 1) + _gpgme_gpg_add_arg ( c->gpg, "--no-expensive-trust-checks" ); _gpgme_gpg_add_arg ( c->gpg, secret_only? "--list-secret-keys":"--list-keys" ); diff --git a/gpgme/posix-io.c b/gpgme/posix-io.c index 740e98f..ec242d3 100644 --- a/gpgme/posix-io.c +++ b/gpgme/posix-io.c @@ -229,7 +229,7 @@ _gpgme_io_select ( struct io_select_fd_s *fds, size_t nfds ) static fd_set readfds; static fd_set writefds; int any, i, max_fd, n, count; - struct timeval timeout = { 1, 0 }; /* Use a one second timeout */ + struct timeval timeout = { 0, 50 }; /* Use a 50ms timeout */ FD_ZERO ( &readfds ); FD_ZERO ( &writefds ); diff --git a/gpgme/recipient.c b/gpgme/recipient.c index 43d3698..02438e4 100644 --- a/gpgme/recipient.c +++ b/gpgme/recipient.c @@ -57,6 +57,9 @@ gpgme_recipients_add_name (GpgmeRecipients rset, const char *name ) r = xtrymalloc ( sizeof *r + strlen (name) ); if (!r) return mk_error (Out_Of_Core); + r->name_part = ""; + r->email_part = ""; + r->comment_part = ""; strcpy (r->name, name ); r->next = rset->list; rset->list = r; diff --git a/gpgme/trustlist.c b/gpgme/trustlist.c new file mode 100644 index 0000000..a877f4e --- /dev/null +++ b/gpgme/trustlist.c @@ -0,0 +1,309 @@ +/* trustlist.c - key listing + * Copyright (C) 2000 Werner Koch (dd9jn) + * + * This file is part of GPGME. + * + * GPGME is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GPGME is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include +#include +#include +#include +#include +#include + +#include "util.h" +#include "context.h" +#include "ops.h" + +#define my_isdigit(a) ( (a) >='0' && (a) <= '9' ) + +struct gpgme_trust_item_s { + int level; + char keyid[16+1]; + int type; + char ot[2]; + char val[2]; + char *name; +}; + + +static GpgmeTrustItem +trust_item_new (void) +{ + GpgmeTrustItem item; + + item = xtrycalloc (1, sizeof *item); + return item; +} + + + +static void +trustlist_status_handler ( GpgmeCtx ctx, GpgStatusCode code, char *args ) +{ + if ( ctx->out_of_core ) + return; + + switch (code) { + case STATUS_EOF: + break; + + default: + break; + } +} + + + +/* + * This handler is used to parse the output of --list-trust-path: + * Format: + * level:keyid:type:recno:ot:val:mc:cc:name: + * With TYPE = U for a user ID + * K for a key + * The RECNO is either the one of the dir record or the one of the uid record. + * OT is the the usual trust letter and only availabel on K lines. + * VAL is the calcualted validity + * MC is the marginal trust counter and only available on U lines + * CC is the same for the complete count + * NAME ist the username and only printed on U lines + */ +static void +trustlist_colon_handler ( GpgmeCtx ctx, char *line ) +{ + char *p, *pend; + int field = 0; + GpgmeTrustItem item = NULL; + struct trust_queue_item_s *q, *q2; + + if ( ctx->out_of_core ) + return; + if (!line) + return; /* EOF */ + + for (p = line; p; p = pend) { + field++; + pend = strchr (p, ':'); + if (pend) + *pend++ = 0; + + switch (field) { + case 1: /* level */ + q = xtrymalloc ( sizeof *q ); + if ( !q ) { + ctx->out_of_core = 1; + return; + } + q->next = NULL; + q->item = item = trust_item_new (); + if (!q->item) { + xfree (q); + ctx->out_of_core = 1; + return; + } + /* fixme: lock queue, keep a tail pointer */ + if ( !(q2 = ctx->trust_queue) ) + ctx->trust_queue = q; + else { + for ( ; q2->next; q2 = q2->next ) + ; + q2->next = q; + } + /* fixme: unlock queue */ + item->level = atoi (p); + break; + case 2: /* long keyid */ + if ( strlen (p) == DIM(item->keyid)-1 ) + strcpy (item->keyid, p); + break; + case 3: /* type */ + item->type = *p == 'K'? 1 : *p == 'U'? 2 : 0; + break; + case 5: /* owner trust */ + item->ot[0] = *p; + item->ot[1] = 0; + break; + case 6: /* validity */ + item->val[0] = *p; + item->val[1] = 0; + break; + case 10: /* user ID */ + item->name = xtrystrdup (p); + if (!item->name) + ctx->out_of_core = 1; + break; + } + } + + if (field) + ctx->key_cond = 1; +} + + + +GpgmeError +gpgme_op_trustlist_start ( GpgmeCtx c, const char *pattern, int max_level ) +{ + GpgmeError rc = 0; + + fail_on_pending_request( c ); + if ( !pattern || !*pattern ) { + return mk_error (Invalid_Value); + } + + c->pending = 1; + + _gpgme_release_result (c); + c->out_of_core = 0; + + if ( c->gpg ) { + _gpgme_gpg_release ( c->gpg ); + c->gpg = NULL; + } + + rc = _gpgme_gpg_new ( &c->gpg ); + if (rc) + goto leave; + + _gpgme_gpg_set_status_handler ( c->gpg, trustlist_status_handler, c ); + rc = _gpgme_gpg_set_colon_line_handler ( c->gpg, + trustlist_colon_handler, c ); + if (rc) + goto leave; + + /* build the commandline */ + _gpgme_gpg_add_arg ( c->gpg, "--with-colons" ); + _gpgme_gpg_add_arg ( c->gpg, "--list-trust-path" ); + + /* Tell the gpg object about the data */ + _gpgme_gpg_add_arg ( c->gpg, "--" ); + _gpgme_gpg_add_arg ( c->gpg, pattern ); + + /* and kick off the process */ + rc = _gpgme_gpg_spawn ( c->gpg, c ); + + leave: + if (rc) { + c->pending = 0; + _gpgme_gpg_release ( c->gpg ); c->gpg = NULL; + } + return rc; +} + + +GpgmeError +gpgme_op_trustlist_next ( GpgmeCtx c, GpgmeTrustItem *r_item ) +{ + struct trust_queue_item_s *q; + + if (!r_item) + return mk_error (Invalid_Value); + *r_item = NULL; + if (!c) + return mk_error (Invalid_Value); + if ( !c->pending ) + return mk_error (No_Request); + if ( c->out_of_core ) + return mk_error (Out_Of_Core); + + if ( !c->trust_queue ) { + _gpgme_wait_on_condition (c, 1, &c->key_cond ); + if ( c->out_of_core ) + return mk_error (Out_Of_Core); + if ( !c->key_cond ) + return mk_error (EOF); + c->key_cond = 0; + assert ( c->trust_queue ); + } + q = c->trust_queue; + c->trust_queue = q->next; + + *r_item = q->item; + xfree (q); + return 0; +} + + +void +gpgme_trust_item_release ( GpgmeTrustItem item ) +{ + if (!item) + return; + xfree (item->name); + xfree (item); +} + + +const char * +gpgme_trust_item_get_string_attr ( GpgmeTrustItem item, GpgmeAttr what, + const void *reserved, int idx ) +{ + const char *val = NULL; + + if (!item) + return NULL; + if (reserved) + return NULL; + if (idx) + return NULL; + + switch (what) { + case GPGME_ATTR_KEYID: + val = item->keyid; + break; + case GPGME_ATTR_OTRUST: + val = item->ot; + break; + case GPGME_ATTR_VALIDITY: + val = item->val; + break; + case GPGME_ATTR_USERID: + val = item->name; + break; + default: + break; + } + return val; +} + + +int +gpgme_trust_item_get_int_attr ( GpgmeTrustItem item, GpgmeAttr what, + const void *reserved, int idx ) +{ + int val = 0; + + if (!item) + return 0; + if (reserved) + return 0; + if (idx) + return 0; + + switch (what) { + case GPGME_ATTR_LEVEL: + val = item->level; + break; + case GPGME_ATTR_TYPE: + val = item->type; + break; + default: + break; + } + return val; +} + diff --git a/gpgme/wait.c b/gpgme/wait.c index edd492e..1cd2418 100644 --- a/gpgme/wait.c +++ b/gpgme/wait.c @@ -62,7 +62,10 @@ struct wait_item_s { static int fd_table_size; static struct io_select_fd_s *fd_table; +static void (*idle_function) (void); + static int do_select ( void ); +static void run_idle (void); static struct wait_item_s * @@ -208,6 +211,8 @@ _gpgme_wait_on_condition ( GpgmeCtx c, int hang, volatile int *cond ) } } } + if (hang) + run_idle (); } while (hang); return c; } @@ -352,17 +357,23 @@ _gpgme_thaw_fd ( int fd ) } +/** + * gpgme_register_idle: + * @fnc: Callers idle function + * + * Register a function with GPGME called by GPGME whenever it feels + * that is is idle. NULL may be used to remove this function. + **/ +void +gpgme_register_idle ( void (*fnc)(void) ) +{ + idle_function = fnc; +} - - - - - - - - - - - - +static void +run_idle () +{ + if (idle_function) + idle_function (); +} diff --git a/tests/Makefile.am b/tests/Makefile.am index de7a045..27482bb 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -2,7 +2,8 @@ TESTS_ENVIRONMENT = GNUPGHOME=. -TESTS = t-encrypt t-sign t-decrypt t-verify t-keylist t-export t-import +TESTS = t-encrypt t-sign t-decrypt t-verify t-keylist t-export t-import \ + t-trustlist EXTRA_DIST = mkdemodirs pubdemo.asc secdemo.asc cipher-1.asc geheim.txt \ diff --git a/tests/t-keylist.c b/tests/t-keylist.c index e07da46..d17c8da 100644 --- a/tests/t-keylist.c +++ b/tests/t-keylist.c @@ -42,12 +42,32 @@ doit ( GpgmeCtx ctx, const char *pattern ) while ( !(err = gpgme_op_keylist_next ( ctx, &key )) ) { char *p; + const char *s; + int i; + printf ("\n", key ); p = gpgme_key_get_as_xml ( key ); - if ( p ) + if ( p ) { fputs ( p, stdout ); + free (p); + } else fputs("\n", stdout ); + + s = gpgme_key_get_string_attr (key, GPGME_ATTR_KEYID, NULL, 0 ); + printf ("\n", s ); + s = gpgme_key_get_string_attr (key, GPGME_ATTR_ALGO, NULL, 0 ); + printf ("\n", s ); + for (i=0; ; i++ ) { + s = gpgme_key_get_string_attr (key, GPGME_ATTR_NAME, NULL, i ); + if (!s) + break; + printf ("\n", i, s ); + s = gpgme_key_get_string_attr (key, GPGME_ATTR_EMAIL, NULL, i ); + printf ("\n", i, s ); + s = gpgme_key_get_string_attr (key, GPGME_ATTR_COMMENT, NULL, i ); + printf ("\n", i, s ); + } printf ("\n", key ); } if ( err != GPGME_EOF ) diff --git a/tests/t-trustlist.c b/tests/t-trustlist.c new file mode 100644 index 0000000..ad01486 --- /dev/null +++ b/tests/t-trustlist.c @@ -0,0 +1,89 @@ +/* t-trustlist.c - regression test + * Copyright (C) 2000 Werner Koch (dd9jn) + * + * This file is part of GPGME. + * + * GPGME is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GPGME is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include +#include +#include +#include + +#include "../gpgme/gpgme.h" + +#define fail_if_err(a) do { if(a) { \ + fprintf (stderr, "%s:%d: GpgmeError %s\n", \ + __FILE__, __LINE__, gpgme_strerror(a)); \ + exit (1); } \ + } while(0) + +static void +doit ( GpgmeCtx ctx, const char *pattern ) +{ + GpgmeError err; + GpgmeTrustItem item; + + err = gpgme_op_trustlist_start (ctx, pattern, 0 ); + fail_if_err (err); + + while ( !(err = gpgme_op_trustlist_next ( ctx, &item )) ) { + printf ("l=%d k=%s t=%d o=%s v=%s u=%s\n", + gpgme_trust_item_get_int_attr (item, GPGME_ATTR_LEVEL, NULL, 0 ), + gpgme_trust_item_get_string_attr (item, GPGME_ATTR_KEYID, NULL, 0 ), + gpgme_trust_item_get_int_attr (item, GPGME_ATTR_TYPE, NULL, 0 ), + gpgme_trust_item_get_string_attr (item, GPGME_ATTR_OTRUST, NULL, 0 ), + gpgme_trust_item_get_string_attr (item, GPGME_ATTR_VALIDITY, NULL, 0 ), + gpgme_trust_item_get_string_attr (item, GPGME_ATTR_USERID, NULL, 0 ) + ); + gpgme_trust_item_release (item); + } + if ( err != GPGME_EOF ) + fail_if_err (err); +} + + +int +main (int argc, char **argv ) +{ + GpgmeCtx ctx; + GpgmeError err; + int loop = 0; + const char *pattern; + + if( argc ) { + argc--; argv++; + } + + if (argc && !strcmp( *argv, "--loop" ) ) { + loop = 1; + argc--; argv++; + } + pattern = argc? *argv : NULL; + + err = gpgme_new (&ctx); + fail_if_err (err); + do { + fprintf (stderr, "** pattern=`%s'\n", pattern ); + doit ( ctx, pattern ); + } while ( loop ); + gpgme_release (ctx); + + return 0; +} + + +