Add progress CB and subkey listing
authorWerner Koch <wk@gnupg.org>
Tue, 19 Dec 2000 10:07:32 +0000 (10:07 +0000)
committerWerner Koch <wk@gnupg.org>
Tue, 19 Dec 2000 10:07:32 +0000 (10:07 +0000)
13 files changed:
README
configure.in
gpgme/context.h
gpgme/genkey.c
gpgme/gpgme.c
gpgme/gpgme.h
gpgme/key.c
gpgme/key.h
gpgme/keylist.c
gpgme/w32-io.c
gpgme/wait.c
tests/Makefile.am
tests/t-genkey.c

diff --git a/README b/README
index 080d6bcd560a16dbcd5ddf1937f96ac719ebe49c..b244fc5525c42aa4e6e767ffb623fa47332bff61 100644 (file)
--- a/README
+++ b/README
@@ -12,6 +12,7 @@ ftp.gnupg.org/pub/gcrypt/alpha/gnupg/gnupg-1.1.2.tar.gz) and install
 the agent from the agent subdirectory or use the new 
 gpgme_set_passphrase_cb() 
 
+
 Please subscribe to the gnupg-devel@gnupg.org mailing list if you want
 to do serious work. 
 
index 41a8b18cea63a804918877d58b2a26e249c9c9a4..710b04346d9ee9687f8da77637d41f54c2368369 100644 (file)
@@ -13,10 +13,10 @@ AM_MAINTAINER_MODE
 #    AGE, set REVISION to 0.
 # 3. Interfaces removed (BAD, breaks upward compatibility): Increment
 #    CURRENT, set AGE and REVISION to 0.
-AM_INIT_AUTOMAKE(gpgme,0.1.2)
-LIBGPGME_LT_CURRENT=0
-LIBGPGME_LT_AGE=0
-LIBGPGME_LT_REVISION=3
+AM_INIT_AUTOMAKE(gpgme,0.1.3)
+LIBGPGME_LT_CURRENT=1
+LIBGPGME_LT_AGE=1
+LIBGPGME_LT_REVISION=0
 ##############################################
 
 AC_SUBST(LIBGPGME_LT_CURRENT)
index 6bba537276f35cbe804daf18430f7575a648393d..86554e04d4b4fe9fcfa1d28405600899015e7f59 100644 (file)
@@ -72,6 +72,9 @@ struct gpgme_context_s {
     GpgmePassphraseCb passphrase_cb;
     void *passphrase_cb_value;
 
+    GpgmeProgressCb progress_cb;
+    void *progress_cb_value;
+
     GpgmeData help_data_1;
 };
 
index d0abae99ccfabfed4a8c1fe93ba3f41f8367a957..b002372c9b59475f6c2319de678059cbe9bfd789 100644 (file)
 static void
 genkey_status_handler ( GpgmeCtx ctx, GpgStatusCode code, char *args )
 {
-    if ( code == STATUS_PROGRESS )
+    if ( code == STATUS_PROGRESS && *args ) {
+        if (ctx->progress_cb) {
+            char *p;
+            int type=0, current=0, total=0;
+            
+            if ( (p = strchr (args, ' ')) ) {
+                *p++ = 0;
+                if (*p) {
+                    type = *(byte*)p;
+                    if ( (p = strchr (p+1, ' ')) ) {
+                        *p++ = 0;
+                        if (*p) {
+                            current = atoi (p);
+                            if ( (p = strchr (p+1, ' ')) ) {
+                                *p++ = 0;
+                                total = atoi (p);
+                            }
+                        }
+                    }
+                }
+            }           
+            if ( type != 'X' )
+                ctx->progress_cb ( ctx->progress_cb_value, args, type,
+                                   current, total );
+        }
         return;
+    }
 
     fprintf (stderr, "genkey_status: code=%d args=`%s'\n",
              code, args );
index 23eef199988c52870b4b8acbfb1d30b24d93de1e..97c82504a4c46c4bedb77102e9ea0ea054b68d83 100644 (file)
@@ -183,7 +183,28 @@ gpgme_set_passphrase_cb ( GpgmeCtx c, GpgmePassphraseCb cb, void *cb_value )
     c->passphrase_cb_value = cb_value;
 }
 
-
-
+/**
+ * gpgme_set_pprogress_cb:
+ * @c: the context 
+ * @cb: A callback function
+ * @cb_value: The value passed to the callback function
+ * 
+ * This function sets a callback function to be used as a progress indicator.
+ *
+ * The callback function is defined as:
+ * <literal>
+ * typedef void (*GpgmeProgressCb) (void*cb_value,
+ *                                  const char *what, int type,
+ *                                  int curretn, int total);
+ * </literal>
+ * For details on the progress events, see the entry for the PROGRESS
+ * status in the file doc/DETAILS of the GnuPG distribution.
+ **/
+void
+gpgme_set_progress_cb ( GpgmeCtx c, GpgmeProgressCb cb, void *cb_value )
+{
+    c->progress_cb = cb;
+    c->progress_cb_value = cb_value;
+}
 
 
index e4f1e95abb50ec9659fbbc146c3d50c6012d75d9..7c0e4c4708d17eae99db0d5ed0557ec7f2420b5e 100644 (file)
@@ -34,7 +34,7 @@ extern "C" {
  * let autoconf (using the AM_PATH_GPGME macro) check that this
  * header matches the installed library.
  * Warning: Do not edit the next line.  configure will do that for you! */
-#define GPGME_VERSION "0.1.2"
+#define GPGME_VERSION "0.1.3"
 
 
 
@@ -99,19 +99,24 @@ typedef enum {
 } GpgmeSigMode;
 
 
-typedef const char *(*GpgmePassphraseCb)(void*, const char *desc, void *r_hd);
+typedef const char *(*GpgmePassphraseCb)(void*,
+                                         const char *desc, void *r_hd);
+typedef void (*GpgmeProgressCb)(void *opaque,
+                                const char *what, 
+                                int type, int current, int total );
 
 
 /* Context management */
 GpgmeError gpgme_new (GpgmeCtx *r_ctx);
-void       gpgme_release ( GpgmeCtx c );
-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_passphrase_cb ( GpgmeCtx c,
-                               GpgmePassphraseCb cb, void *cb_value );
+void       gpgme_release (GpgmeCtx c);
+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_passphrase_cb (GpgmeCtx c,
+                              GpgmePassphraseCb cb, void *cb_value);
+void gpgme_set_progress_cb (GpgmeCtx c, GpgmeProgressCb cb, void *cb_value);
 
 
 
index c58e859d60e7853d2e874150db308830abc41ce1..909b5cff4deaf21dcb1bb873b323d09a1ad1f70d 100644 (file)
@@ -45,16 +45,43 @@ _gpgme_key_new( GpgmeKey *r_key )
     return 0;
 }
 
+
+struct subkey_s *
+_gpgme_key_add_subkey (GpgmeKey key)
+{
+    struct subkey_s *k, *kk;
+
+    k = xtrycalloc (1, sizeof *k);
+    if (!k)
+        return NULL;
+
+    if( !(kk=key->keys.next) )
+        key->keys.next = k;
+    else {
+        while ( kk->next )
+            kk = kk->next;
+        kk->next = k;
+    }
+    return k;
+}
+
+
 void
 _gpgme_key_release ( GpgmeKey key )
 {
     struct user_id_s *u, *u2;
+    struct subkey_s *k, *k2;
 
     if (!key)
         return;
 
-    xfree (key->fingerprint);
-    for ( u = key->uids; u; u = u2 ) {
+    xfree (key->keys.fingerprint);
+    for (k = key->keys.next; k; k = k2 ) {
+        k2 = k->next;
+        xfree (k->fingerprint);
+        xfree (k);
+    }
+    for (u = key->uids; u; u = u2 ) {
         u2 = u->next;
         xfree (u);
     }
@@ -250,6 +277,7 @@ gpgme_key_get_as_xml ( GpgmeKey key )
 {
     GpgmeData d;
     struct user_id_s *u;
+    struct subkey_s *k;
 
     if ( !key )
         return NULL;
@@ -259,25 +287,33 @@ gpgme_key_get_as_xml ( GpgmeKey key )
     
     _gpgme_data_append_string ( d, "<GnupgKeyblock>\n"
                                    "  <mainkey>\n" );
-    add_tag_and_string (d, "keyid", key->keyid );   
-    if (key)
-        add_tag_and_string (d, "fpr", key->fingerprint );
-    add_tag_and_uint (d, "algo", key->key_algo );
-    add_tag_and_uint (d, "len", key->key_len );
-    add_tag_and_time (d, "created", key->timestamp );
+    add_tag_and_string (d, "keyid", key->keys.keyid );   
+    if (key->keys.fingerprint)
+        add_tag_and_string (d, "fpr", key->keys.fingerprint );
+    add_tag_and_uint (d, "algo", key->keys.key_algo );
+    add_tag_and_uint (d, "len", key->keys.key_len );
+    add_tag_and_time (d, "created", key->keys.timestamp );
     /*add_tag_and_time (d, "expires", key->expires );*/
     _gpgme_data_append_string (d, "  </mainkey>\n");
 
-    /* No the user IDs */
+    /* Now the user IDs */
     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 );
         _gpgme_data_append_string (d, "  </userid>\n");
     }
-    _gpgme_data_append_string (d, "  <subkey>\n");
-    _gpgme_data_append_string (d, "  </subkey>\n");
     
+    for (k=key->keys.next; k; k = k->next ) {
+        _gpgme_data_append_string (d, "  <subkey>\n");
+        add_tag_and_string (d, "keyid", k->keyid );   
+        if (k->fingerprint)
+            add_tag_and_string (d, "fpr", k->fingerprint );
+        add_tag_and_uint (d, "algo", k->key_algo );
+        add_tag_and_uint (d, "len", k->key_len );
+        add_tag_and_time (d, "created", k->timestamp );
+        _gpgme_data_append_string (d, "  </subkey>\n");
+    }
     _gpgme_data_append_string ( d, "</GnupgKeyblock>\n" );
 
     return _gpgme_data_release_and_return_string (d);
@@ -285,3 +321,5 @@ gpgme_key_get_as_xml ( GpgmeKey key )
 
 
 
+
+
index f95c9092ddf8fe7ddf21a283d3b26dc519e73161..8c68779f1a6607c9f93892592de5ea7c5119685b 100644 (file)
@@ -25,8 +25,8 @@
 #include "types.h"
 #include "context.h"
 
-
-struct gpgme_key_s {
+struct subkey_s {
+    struct subkey_s *next;
     struct {
         unsigned int revoked:1 ;
         unsigned int expired:1 ;
@@ -37,11 +37,19 @@ struct gpgme_key_s {
     char keyid[16+1]; 
     char *fingerprint; /* malloced hex digits */
     time_t timestamp; /* -1 for invalid, 0 for not available */
-    struct user_id_s *uids;
-    
 };
 
+struct gpgme_key_s {
+    struct {
+        unsigned int revoked:1 ;
+        unsigned int expired:1 ;
+        unsigned int disabled:1 ;
+    } gloflags; 
+    struct subkey_s   keys; 
+    struct user_id_s *uids;
+};
 
+struct subkey_s *_gpgme_key_add_subkey (GpgmeKey key);
 GpgmeError _gpgme_key_append_name ( GpgmeKey key, const char *s );
 
 
index cbd7cb4868958564d70f95dabcc6ffb866ed3b85..5cb124e46308081733d007dc04eb935cb626741e 100644 (file)
@@ -91,14 +91,14 @@ parse_timestamp ( char *p )
 
 
 static void
-set_trust_info ( GpgmeKey key, const char *s )
+set_mainkey_trust_info ( GpgmeKey key, const char *s )
 {
     /* look at letters and stop at the first digit */
     for (; *s && !my_isdigit (*s); s++ ) {
         switch (*s) {
-          case 'e': key->flags.expired = 1; break;
-          case 'r': key->flags.revoked = 1; break;
-          case 'd': key->flags.disabled = 1; break;
+          case 'e': key->keys.flags.expired = 1; break;
+          case 'r': key->keys.flags.revoked = 1; break;
+          case 'd': key->keys.flags.disabled = 1; break;
           case 'n': key->uids->validity = 1; break;
           case 'm': key->uids->validity = 2; break;
           case 'f': key->uids->validity = 3; break;
@@ -107,6 +107,19 @@ set_trust_info ( GpgmeKey key, const char *s )
     }
 }
 
+static void
+set_subkey_trust_info ( struct subkey_s *k, const char *s )
+{
+    /* look at letters and stop at the first digit */
+    for (; *s && !my_isdigit (*s); s++ ) {
+        switch (*s) {
+          case 'e': k->flags.expired = 1; break;
+          case 'r': k->flags.revoked = 1; break;
+          case 'd': k->flags.disabled = 1; break;
+        }
+    }
+}
+
 
 /* Note: we are allowed to modify line */
 static void
@@ -120,15 +133,13 @@ keylist_colon_handler ( GpgmeCtx ctx, char *line )
     GpgmeKey key = ctx->tmp_key;
     int i;
     const char *trust_info = NULL;
-    
+    struct subkey_s *sk = NULL;
 
     if ( ctx->out_of_core )
         return;
     if (!line)
         return; /* EOF */
 
-    /*fprintf (stderr, "line=`%s'\n", line );*/
-
     for (p = line; p; p = pend) {
         field++;
         pend = strchr (p, ':');
@@ -142,8 +153,14 @@ keylist_colon_handler ( GpgmeCtx ctx, char *line )
                 rectype = RT_UID;
                 key = ctx->tmp_key;
             }
-            else if ( !strcmp ( p, "sub" ) )
+            else if ( !strcmp ( p, "sub" ) && key ) {
+                /* start a new subkey */
                 rectype = RT_SUB;
+                if ( !(sk = _gpgme_key_add_subkey (key)) ) {
+                    ctx->out_of_core=1;
+                    return;
+                }
+            }
             else if ( !strcmp ( p, "pub" ) ) {
                 /* start a new keyblock */
                 if ( _gpgme_key_new ( &key ) ) {
@@ -166,28 +183,27 @@ keylist_colon_handler ( GpgmeCtx ctx, char *line )
                 rectype = RT_NONE;
             
         }
-        else if ( rectype == RT_PUB /*|| rectype == RT_SUB*/ ) {
+        else if ( rectype == RT_PUB ) {
             switch (field) {
               case 2: /* trust info */
-                if ( rectype == RT_PUB ) 
-                    trust_info = p;  /*save for later */
+                trust_info = p;  /*save for later */
                 break;
               case 3: /* key length */
                 i = atoi (p); 
                 if ( i > 1 ) /* ignore invalid values */
-                    key->key_len = i; 
+                    key->keys.key_len = i; 
                 break;
               case 4: /* pubkey algo */
                 i = atoi (p);
                 if ( i > 1 && i < 128 )
-                    key->key_algo = i;
+                    key->keys.key_algo = i;
                 break;
               case 5: /* long keyid */
-                if ( strlen (p) == DIM(key->keyid)-1 )
-                    strcpy (key->keyid, p);
+                if ( strlen (p) == DIM(key->keys.keyid)-1 )
+                    strcpy (key->keys.keyid, p);
                 break;
               case 6: /* timestamp (1998-02-28) */
-                key->timestamp = parse_timestamp (p);
+                key->keys.timestamp = parse_timestamp (p);
                 break;
               case 7: /* valid for n days */
                 break;
@@ -196,13 +212,11 @@ keylist_colon_handler ( GpgmeCtx ctx, char *line )
               case 9: /* ownertrust */
                 break;
               case 10: /* This is the first name listed */
-                if ( rectype == RT_PUB ) {
-                    if ( _gpgme_key_append_name ( key, p) )
-                        ctx->out_of_core = 1;
-                    else {
-                        if (trust_info)
-                            set_trust_info (key, trust_info);
-                    }
+                if ( _gpgme_key_append_name ( key, p) )
+                    ctx->out_of_core = 1;
+                else {
+                    if (trust_info)
+                        set_mainkey_trust_info (key, trust_info);
                 }
                 break;
               case 11:  /* signature class  */
@@ -212,6 +226,43 @@ keylist_colon_handler ( GpgmeCtx ctx, char *line )
                 break;
             }
         }
+        else if ( rectype == RT_SUB && sk ) {
+            switch (field) {
+              case 2: /* trust info */
+                set_subkey_trust_info ( sk, p);
+                break;
+              case 3: /* key length */
+                i = atoi (p); 
+                if ( i > 1 ) /* ignore invalid values */
+                    sk->key_len = i; 
+                break;
+              case 4: /* pubkey algo */
+                i = atoi (p);
+                if ( i > 1 && i < 128 )
+                    sk->key_algo = i;
+                break;
+              case 5: /* long keyid */
+                if ( strlen (p) == DIM(sk->keyid)-1 )
+                    strcpy (sk->keyid, p);
+                break;
+              case 6: /* timestamp (1998-02-28) */
+                sk->timestamp = parse_timestamp (p);
+                break;
+              case 7: /* valid for n days */
+                break;
+              case 8: /* reserved (LID) */
+                break;
+              case 9: /* ownertrust */
+                break;
+              case 10:/* user ID n/a for a subkey */
+                break;
+              case 11:  /* signature class  */
+                break;
+              case 12:
+                pend = NULL;  /* we can stop here */
+                break;
+            }
+        }
         else if ( rectype == RT_UID ) {
             switch (field) {
               case 2: /* trust info */
@@ -222,7 +273,7 @@ keylist_colon_handler ( GpgmeCtx ctx, char *line )
                     ctx->out_of_core = 1;
                 else {
                     if (trust_info)
-                        set_trust_info (key, trust_info);
+                        set_mainkey_trust_info (key, trust_info);
                 }
                 pend = NULL;  /* we can stop here */
                 break;
@@ -231,9 +282,9 @@ keylist_colon_handler ( GpgmeCtx ctx, char *line )
         else if ( rectype == RT_FPR ) {
             switch (field) {
               case 10: /* fingerprint (take only the first one)*/
-                if ( !key->fingerprint && *p ) {
-                    key->fingerprint = xtrystrdup (p);
-                    if ( !key->fingerprint )
+                if ( !key->keys.fingerprint && *p ) {
+                    key->keys.fingerprint = xtrystrdup (p);
+                    if ( !key->keys.fingerprint )
                         ctx->out_of_core = 1;
                 }
                 pend = NULL; /* that is all we want */
@@ -266,7 +317,7 @@ finish_key ( GpgmeCtx ctx )
     }
     q->key = key;
     q->next = NULL;
-    /* fixme: lock queue */
+    /* fixme: lock queue. Use a tail pointer? */
     if ( !(q2 = ctx->key_queue) )
         ctx->key_queue = q;
     else {
@@ -373,12 +424,3 @@ gpgme_op_keylist_next ( GpgmeCtx c, GpgmeKey *r_key )
 
 
 
-
-
-
-
-
-
-
-
-
index 477362248115ad94413f85361c76dc3803c2c679..237c038608ccc608fda69c022913425c1b420b1a 100644 (file)
@@ -559,8 +559,8 @@ _gpgme_io_select ( struct io_select_fd_s *fds, size_t nfds )
                          (int)GetLastError ());
             }
             else if ( navail ) {
-                fprintf (stderr, "** fd %d has %d bytes to read\n",
-                         fds[i].fd, navail );
+                /*fprintf (stderr, "** fd %d has %d bytes to read\n",
+                  fds[i].fd, navail );*/
                 fds[i].signaled = 1;
                 count++;
             }
index b024b09217e9a08c0d2e2f534b77634bfe51d437..edd492ee0a2e2ecc7626d1bef1d758d5eecfc64d 100644 (file)
@@ -234,7 +234,7 @@ do_select ( void )
     if ( n <= 0 ) 
         return 0; /* error or timeout */
 
-    for (i=0; i < fd_table_size /*&& n*/; i++ ) {
+    for (i=0; i < fd_table_size && n; i++ ) {
         if ( fd_table[i].fd != -1 && fd_table[i].signaled 
              && !fd_table[i].frozen ) {
             q = fd_table[i].opaque;
@@ -328,7 +328,7 @@ _gpgme_freeze_fd ( int fd )
     for (i=0; i < fd_table_size; i++ ) {
         if ( fd_table[i].fd == fd ) {
             fd_table[i].frozen = 1;
-            fprintf (stderr, "** FD %d frozen\n", fd );
+            /*fprintf (stderr, "** FD %d frozen\n", fd );*/
             break;
         }
     }
@@ -344,7 +344,7 @@ _gpgme_thaw_fd ( int fd )
     for (i=0; i < fd_table_size; i++ ) {
         if ( fd_table[i].fd == fd ) {
             fd_table[i].frozen = 0;
-            fprintf (stderr, "** FD %d thawed\n", fd );
+            /*fprintf (stderr, "** FD %d thawed\n", fd );*/
             break;
         }
     }
index 3f5f2349db67c4822beada2874aade2da7516f95..de7a0456bae473870c58bfc0eec8431629ac7563 100644 (file)
@@ -2,8 +2,8 @@
 
 TESTS_ENVIRONMENT = GNUPGHOME=. 
 
-TESTS = t-encrypt t-sign t-decrypt t-verify t-keylist t-export t-import \
-       t-genkey
+TESTS = t-encrypt t-sign t-decrypt t-verify t-keylist t-export t-import 
+
 
 EXTRA_DIST = mkdemodirs pubdemo.asc secdemo.asc cipher-1.asc geheim.txt \
             pubkey-1.asc seckey-1.asc
@@ -13,7 +13,8 @@ INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/intl
 INCLUDES = 
 LDADD = ../gpgme/libgpgme.la
 
-noinst_PROGRAMS = $(TESTS)
+# We don't run t-genkey in the test suite, because it taes too long
+noinst_PROGRAMS = $(TESTS) t-genkey
 
 distclean-local:
        $(srcdir)/mkdemodirs --clean
index 710dfa0bc1336fb7b44db830c9066ef169bacdd6..d22b95ea1b5142a7e8b82543ce313542cf3751cc 100644 (file)
                              } while(0)
 
 
+static void
+progress ( void *self, const char *what, int type, int current, int total)
+{
+    fprintf (stderr, "progress `%s' %d %d %d\n", what, type, current, total);
+}
+
+
 int 
 main (int argc, char **argv )
 {
@@ -45,6 +52,8 @@ main (int argc, char **argv )
     err = gpgme_new (&ctx);
     fail_if_err (err);
 
+    gpgme_set_progress_cb (ctx, progress, NULL);
+
     format = "<GnupgKeyParms format=\"internal\">\n"
              "Key-Type: DSA\n"
              "Key-Length: 1024\n"