More changes and and some new functions
authorWerner Koch <wk@gnupg.org>
Mon, 8 Jan 2001 20:40:25 +0000 (20:40 +0000)
committerWerner Koch <wk@gnupg.org>
Mon, 8 Jan 2001 20:40:25 +0000 (20:40 +0000)
15 files changed:
gpgme/ChangeLog
gpgme/Makefile.am
gpgme/context.h
gpgme/data.c
gpgme/gpgme.c
gpgme/gpgme.h
gpgme/key.c
gpgme/keylist.c
gpgme/posix-io.c
gpgme/recipient.c
gpgme/trustlist.c [new file with mode: 0644]
gpgme/wait.c
tests/Makefile.am
tests/t-keylist.c
tests/t-trustlist.c [new file with mode: 0644]

index e69de29..79fed0f 100644 (file)
@@ -0,0 +1,3 @@
+2001-01-05  Werner Koch  <wk@gnupg.org>
+
+       * data.c (gpgme_data_rewind): Allow to rewind data_type_none.
index 32b72b4..8365678 100644 (file)
@@ -23,6 +23,7 @@ libgpgme_la_SOURCES = \
        sign.c \
         key.c key.h \
        keylist.c \
+       trustlist.c \
        import.c \
         export.c \
        genkey.c \
index e1ff31f..32ed8d5 100644 (file)
@@ -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];
 };
 
index 73408f9..48a2eae 100644 (file)
@@ -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) {
index 0c814bd..7a2fcbe 100644 (file)
@@ -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
index 7190af0..6cb7567 100644 (file)
@@ -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
index 909b5cf..f00f8df 100644 (file)
 #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;
+}
 
 
index 5cb124e..b4d4303 100644 (file)
@@ -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" );
     
index 740e98f..ec242d3 100644 (file)
@@ -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 );
index 43d3698..02438e4 100644 (file)
@@ -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 (file)
index 0000000..a877f4e
--- /dev/null
@@ -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;
+}
+
index edd492e..1cd2418 100644 (file)
@@ -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 ();
+}
index de7a045..27482bb 100644 (file)
@@ -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 \
index e07da46..d17c8da 100644 (file)
@@ -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 (file)
index 0000000..ad01486
--- /dev/null
@@ -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;
+}
+
+
+