diff options
| -rw-r--r-- | gpgme/ChangeLog | 3 | ||||
| -rw-r--r-- | gpgme/Makefile.am | 1 | ||||
| -rw-r--r-- | gpgme/context.h | 9 | ||||
| -rw-r--r-- | gpgme/data.c | 3 | ||||
| -rw-r--r-- | gpgme/gpgme.c | 18 | ||||
| -rw-r--r-- | gpgme/gpgme.h | 42 | ||||
| -rw-r--r-- | gpgme/key.c | 287 | ||||
| -rw-r--r-- | gpgme/keylist.c | 3 | ||||
| -rw-r--r-- | gpgme/posix-io.c | 2 | ||||
| -rw-r--r-- | gpgme/recipient.c | 3 | ||||
| -rw-r--r-- | gpgme/trustlist.c | 309 | ||||
| -rw-r--r-- | gpgme/wait.c | 35 | ||||
| -rw-r--r-- | tests/Makefile.am | 3 | ||||
| -rw-r--r-- | tests/t-keylist.c | 22 | ||||
| -rw-r--r-- | tests/t-trustlist.c | 89 | 
15 files changed, 736 insertions, 93 deletions
| diff --git a/gpgme/ChangeLog b/gpgme/ChangeLog index e69de29b..79fed0f4 100644 --- a/gpgme/ChangeLog +++ b/gpgme/ChangeLog @@ -0,0 +1,3 @@ +2001-01-05  Werner Koch  <[email protected]> + +	* data.c (gpgme_data_rewind): Allow to rewind data_type_none. diff --git a/gpgme/Makefile.am b/gpgme/Makefile.am index 32b72b4d..8365678a 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 e1ff31f0..32ed8d50 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 73408f9f..48a2eaeb 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 0c814bd2..7a2fcbef 100644 --- a/gpgme/gpgme.c +++ b/gpgme/gpgme.c @@ -165,6 +165,24 @@ gpgme_set_textmode ( GpgmeCtx c, int 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    * @cb: A callback function diff --git a/gpgme/gpgme.h b/gpgme/gpgme.h index 7190af09..6cb7567a 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 909b5cff..f00f8dff 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; @@ -184,76 +299,6 @@ add_tag_and_string ( GpgmeData d, const char *tag, const char *string )  }  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 )  {      char buf[30]; @@ -300,7 +345,12 @@ gpgme_key_get_as_xml ( GpgmeKey key )      for ( u = key->uids; u; u = u->next ) {          _gpgme_data_append_string (d, "  <userid>\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, "  </userid>\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 5cb124e4..b4d43033 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 740e98f5..ec242d31 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 43d36987..02438e47 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 00000000..a877f4ea --- /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 <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <assert.h> + +#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 edd492ee..1cd2418f 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 de7a0456..27482bb8 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 e07da463..d17c8da3 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 ("<!-- Begin key object (%p) -->\n", key );          p = gpgme_key_get_as_xml ( key ); -        if ( p ) +        if ( p ) {              fputs ( p, stdout ); +            free (p); +        }          else              fputs("<!-- Ooops: gpgme_key_get_as_xml failed -->\n", stdout ); + +        s = gpgme_key_get_string_attr (key, GPGME_ATTR_KEYID, NULL, 0 ); +        printf ("<!-- keyid=%s -->\n", s ); +        s = gpgme_key_get_string_attr (key, GPGME_ATTR_ALGO, NULL, 0 ); +        printf ("<!-- algo=%s -->\n", s ); +        for (i=0; ; i++ ) { +            s = gpgme_key_get_string_attr (key, GPGME_ATTR_NAME, NULL, i ); +            if (!s) +                break; +            printf ("<!-- name.%d=%s -->\n", i, s ); +            s = gpgme_key_get_string_attr (key, GPGME_ATTR_EMAIL, NULL, i ); +            printf ("<!-- email.%d=%s -->\n", i, s ); +            s = gpgme_key_get_string_attr (key, GPGME_ATTR_COMMENT, NULL, i ); +            printf ("<!-- comment.%d=%s -->\n", i, s ); +        }          printf ("<!-- End key object (%p) -->\n", key );      }      if ( err != GPGME_EOF ) diff --git a/tests/t-trustlist.c b/tests/t-trustlist.c new file mode 100644 index 00000000..ad014869 --- /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 <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +#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; +} + + + | 
