Changes by Jose and Tommy.
authorWerner Koch <wk@gnupg.org>
Mon, 28 May 2001 17:35:10 +0000 (17:35 +0000)
committerWerner Koch <wk@gnupg.org>
Mon, 28 May 2001 17:35:10 +0000 (17:35 +0000)
gpgme/ChangeLog
gpgme/decrypt.c
gpgme/encrypt.c
gpgme/key.c
gpgme/key.h
gpgme/keylist.c
gpgme/rungpg.c
gpgme/verify.c
gpgme/version.c
tests/t-verify.c

index 017ab28..a8242e5 100644 (file)
@@ -1,3 +1,26 @@
+2001-05-28  Werner Koch  <wk@gnupg.org>
+
+       * version.c (gpgme_check_engine): Stop version number parsing at
+       the opening angle and not the closing one.  By Tommy Reynolds.
+
+2001-05-01  José Carlos García Sogo <jose@jaimedelamo.eu.org>
+
+       * encrypt.c (gpgme_op_encrypt_start): Deleted the assert ( !c->gpg )
+       line, because it gave an error if another operation had been made 
+       before using the same context.
+       
+       * decrypt.c (gpgme_op_decrypt_start): The same as above. Also added 
+       one line to release the gpg object in the context (if any).
+       
+2001-04-26  Werner Koch  <wk@gnupg.org>
+
+       * key.c, key.h (_gpgme_key_cache_init): New.
+       (_gpgme_key_cache_add): New.
+       (_gpgme_key_cache_get): New.
+       * version.c (do_subsystem_inits): Init the cache.
+       * keylist.c (finish_key): Put key into the cache
+       * verify.c (gpgme_get_sig_key): First look into the cache.
+
 2001-04-19  Werner Koch  <wk@gnupg.org>
 
        * keylist.c (parse_timestamp): Adjusted for the changed
  This file is distributed in the hope that it will be useful, but
  WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-       
\ No newline at end of file
+       
index 526a815..5982301 100644 (file)
@@ -195,9 +195,9 @@ gpgme_op_decrypt_start ( GpgmeCtx c,
     c->out_of_core = 0;
 
     /* do some checks */
-    assert ( !c->gpg );
-        
     /* create a process object */
+    _gpgme_gpg_release ( c->gpg );
     rc = _gpgme_gpg_new ( &c->gpg );
     if (rc)
         goto leave;
index 5234cc8..3fe60a6 100644 (file)
@@ -49,7 +49,6 @@ gpgme_op_encrypt_start ( GpgmeCtx c, GpgmeRecipients recp,
     c->pending = 1;
 
     /* do some checks */
-    assert ( !c->gpg );
     if ( !gpgme_recipients_count ( recp ) ) {
         /* Fixme: In this case we should do symmentric encryption */
         rc = mk_error (No_Recipients);
index f61d2c1..966675e 100644 (file)
 #define ALLOC_CHUNK 1024
 #define my_isdigit(a) ( (a) >='0' && (a) <= '9' )
 
+#if SIZEOF_UNSIGNED_INT < 4
+#error unsigned int too short to be used as a hash value
+#endif
+
+struct key_cache_item_s {
+    struct key_cache_item_s *next;
+    GpgmeKey key;
+};
+
+static int key_cache_initialized;
+static struct key_cache_item_s **key_cache;
+static size_t key_cache_size;
+static size_t key_cache_max_chain_length;
+static struct key_cache_item_s *key_cache_unused_items;
+
+static int
+hextobyte ( const byte *s )
+{
+    int c;
+
+    if ( *s >= '0' && *s <= '9' )
+       c = 16 * (*s - '0');
+    else if ( *s >= 'A' && *s <= 'F' )
+       c = 16 * (10 + *s - 'A');
+    else if ( *s >= 'a' && *s <= 'f' )
+       c = 16 * (10 + *s - 'a');
+    else
+       return -1;
+    s++;
+    if ( *s >= '0' && *s <= '9' )
+       c += *s - '0';
+    else if ( *s >= 'A' && *s <= 'F' )
+       c += 10 + *s - 'A';
+    else if ( *s >= 'a' && *s <= 'f' )
+       c += 10 + *s - 'a';
+    else
+       return -1;
+    return c;
+}
+
+static int
+hash_key (const char *fpr, unsigned int *rhash)
+{
+    unsigned int hash;
+    int c;
+
+    if ( !fpr )                         return -1;
+    if ( (c = hextobyte(fpr)) == -1 )   return -1;
+    hash = c;
+    if ( (c = hextobyte(fpr+2)) == -1 ) return -1;
+    hash |= c << 8;
+    if ( (c = hextobyte(fpr+4)) == -1 ) return -1;
+    hash |= c << 16;
+    if ( (c = hextobyte(fpr+6)) == -1 ) return -1;
+    hash |= c << 24;
+
+    *rhash = hash;
+    return 0;
+}
+
+void
+_gpgme_key_cache_init (void)
+{
+    if (key_cache_initialized)
+        return;
+    key_cache_size = 503;
+    key_cache = xtrycalloc (key_cache_size, sizeof *key_cache);
+    if (!key_cache) {
+        key_cache_size = 0;
+        key_cache_initialized = 1;
+        return;
+    }
+    /*
+     * The upper bound for our cache size is 
+     * key_cache_max_chain_length * key_cache_size 
+     */
+    key_cache_max_chain_length = 10;
+    key_cache_initialized = 1;
+}
+
+
+void
+_gpgme_key_cache_add (GpgmeKey key)
+{
+    struct subkey_s *k;
+#warning debug code
+    if (!key || getenv("gpgme_no_cache") )
+        return;
+
+    /* FIXME: add locking */
+    if (!key_cache_initialized)
+        _gpgme_key_cache_init ();
+    if (!key_cache_size)
+        return; /* cache was not enabled */
+
+    /* put the key under each fingerprint into the cache.  We use the
+     * first 4 digits to calculate the hash */
+    for (k=&key->keys; k; k = k->next ) {
+        size_t n;
+        unsigned int hash;
+        struct key_cache_item_s *item;
+
+        if ( hash_key (k->fingerprint, &hash) )
+            continue;
+
+        hash %= key_cache_size;
+        for (item=key_cache[hash],n=0; item; item = item->next, n++) {
+            struct subkey_s *k2;
+            if (item->key == key) 
+                break; /* already in cache */
+            /* now do a deeper check */
+            for (k2=&item->key->keys; k2; k2 = k2->next ) {
+                if( k2->fingerprint
+                    && !strcmp (k->fingerprint, k2->fingerprint) ) {
+                    /* okay, replace it with the new copy */
+                    gpgme_key_unref (item->key);
+                    item->key = key;
+                    gpgme_key_ref (item->key);
+                    return;
+                }
+            }
+        }
+        if (item)
+            continue; 
+        
+        if (n > key_cache_max_chain_length ) { /* remove the last entries */
+            struct key_cache_item_s *last = NULL;
+
+            for (item=key_cache[hash];
+                 item && n < key_cache_max_chain_length;
+                 last = item, item = item->next, n++ ) {
+                ;
+            }
+            if (last) {
+                struct key_cache_item_s *next;
+
+                assert (last->next == item);
+                last->next = NULL;
+                for ( ;item; item=next) {
+                    next = item->next;
+                    gpgme_key_unref (item->key);
+                    item->key = NULL;
+                    item->next = key_cache_unused_items;
+                    key_cache_unused_items = item;
+                }
+            }
+        }
+
+        item = key_cache_unused_items;
+        if (item) {
+            key_cache_unused_items = item->next;
+            item->next = NULL;
+        }
+        else {
+            item = xtrymalloc (sizeof *item);
+            if (!item)
+                return; /* out of core */
+        }
+        
+        item->key = key;
+        gpgme_key_ref (key);
+        item->next = key_cache[hash];
+        key_cache[hash] = item;
+    }
+}
+
+
+GpgmeKey 
+_gpgme_key_cache_get (const char *fpr)
+{
+    struct key_cache_item_s *item;
+    unsigned int hash;
+
+    if (!key_cache_size)
+        return NULL; /* cache not (yet) enabled */
+
+    if (hash_key (fpr, &hash))
+        return NULL;
+
+    hash %= key_cache_size;
+    for (item=key_cache[hash]; item; item = item->next) {
+        struct subkey_s *k;
+
+        for (k=&item->key->keys; k; k = k->next ) {
+            if( k->fingerprint && !strcmp (k->fingerprint, fpr) ) {
+                gpgme_key_ref (item->key);
+                return item->key;
+            }
+        }
+    }
+    return NULL;
+}
+
 
 static const char *
 pkalgo_to_string ( int algo )
@@ -47,8 +240,6 @@ pkalgo_to_string ( int algo )
 }
 
 
-
-
 static GpgmeError
 key_new ( GpgmeKey *r_key, int secret )
 {
index 60244e9..003821a 100644 (file)
@@ -61,6 +61,11 @@ struct gpgme_key_s {
     struct user_id_s *uids;
 };
 
+void _gpgme_key_cache_init (void);
+void _gpgme_key_cache_add (GpgmeKey key);
+GpgmeKey _gpgme_key_cache_get (const char *fpr);
+
+
 struct subkey_s *_gpgme_key_add_subkey (GpgmeKey key);
 struct subkey_s *_gpgme_key_add_secret_subkey (GpgmeKey key);
 GpgmeError _gpgme_key_append_name ( GpgmeKey key, const char *s );
index 9d7824b..11e10cf 100644 (file)
@@ -341,10 +341,12 @@ finish_key ( GpgmeCtx ctx )
 {
     GpgmeKey key = ctx->tmp_key;
     struct key_queue_item_s *q, *q2;
-    
+
     assert (key);
     ctx->tmp_key = NULL;
-    
+
+    _gpgme_key_cache_add (key);
+
     q = xtrymalloc ( sizeof *q );
     if ( !q ) {
         gpgme_key_release (key);
index 6f731e5..708b278 100644 (file)
@@ -1094,7 +1094,6 @@ read_status ( GpgObject gpg )
             if ( *p == '\n' ) {
                 /* (we require that the last line is terminated by a LF) */
                 *p = 0;
-                fflush (stdout); fprintf (stderr, "read_status: `%s'\n", buffer); 
                 if (!strncmp (buffer, "[GNUPG:] ", 9 )
                     && buffer[9] >= 'A' && buffer[9] <= 'Z' ) {
                     struct status_table_s t, *r;
index 0d50b8a..3b2174b 100644 (file)
@@ -28,6 +28,7 @@
 #include "util.h"
 #include "context.h"
 #include "ops.h"
+#include "key.h"
 
 struct verify_result_s {
     struct verify_result_s *next;
@@ -219,7 +220,7 @@ gpgme_op_verify_start ( GpgmeCtx c,  GpgmeData sig, GpgmeData text )
 {
     int rc = 0;
     int i;
-    int pipemode = !!text; /* use pipemode for detached sigs */
+    int pipemode = 0; /*!!text; use pipemode for detached sigs */
 
     fail_on_pending_request( c );
     c->pending = 1;
@@ -414,8 +415,7 @@ GpgmeError
 gpgme_get_sig_key (GpgmeCtx c, int idx, GpgmeKey *r_key)
 {
     VerifyResult res;
-    GpgmeCtx listctx;
-    GpgmeError err;
+    GpgmeError err = 0;
 
     if (!c || !r_key)
         return mk_error (Invalid_Value);
@@ -430,15 +430,19 @@ gpgme_get_sig_key (GpgmeCtx c, int idx, GpgmeKey *r_key)
     if (strlen(res->fpr) < 16) /* we have at least an key ID */
         return mk_error (Invalid_Key);
 
-    /* Fixme: This can me optimized keeping
-     *        an internal context used for such key listings */
-    if ( (err=gpgme_new (&listctx)) )
-        return err;
-    gpgme_set_keylist_mode( listctx, c->keylist_mode );
-    if ( !(err=gpgme_op_keylist_start (listctx, res->fpr, 0 )) )
-        err=gpgme_op_keylist_next ( listctx, r_key );
-    gpgme_release (listctx);
-
+    *r_key = _gpgme_key_cache_get (res->fpr);
+    if (!*r_key) {
+        GpgmeCtx listctx;
+
+        /* Fixme: This can be optimized by keeping
+         *        an internal context used for such key listings */
+        if ( (err=gpgme_new (&listctx)) )
+            return err;
+        gpgme_set_keylist_mode( listctx, c->keylist_mode );
+        if ( !(err=gpgme_op_keylist_start (listctx, res->fpr, 0 )) )
+            err=gpgme_op_keylist_next ( listctx, r_key );
+        gpgme_release (listctx);
+    }
     return err;
 }
 
index 0d8e5a7..74b6576 100644 (file)
@@ -30,7 +30,7 @@
 #include "rungpg.h"
 #include "sema.h"
 #include "util.h"
-
+#include "key.h" /* for key_cache_init */
 
 static int lineno;
 static char *tmp_engine_version;
@@ -46,6 +46,7 @@ do_subsystem_inits (void)
     if (done)
         return;
     _gpgme_sema_subsystem_init ();
+    _gpgme_key_cache_init ();
 }
 
 
@@ -104,7 +105,7 @@ compare_versions ( const char *my_version, const char *req_version )
 
     if ( my_major > rq_major
          || (my_major == rq_major && my_minor > rq_minor)
-         || (my_major == rq_major && my_minor == rq_minor
+         || (my_major == rq_major && my_minor == rq_minor 
              && my_micro > rq_micro)
          || (my_major == rq_major && my_minor == rq_minor
              && my_micro == rq_micro
@@ -173,7 +174,7 @@ gpgme_check_engine ()
     s = strstr (info, "<version>");
     if (s) {
         s += 9;
-        s2 = strchr (s, '>');
+        s2 = strchr (s, '<');
         if (s2) {
             char *ver = xtrymalloc (s2 - s + 1);
             if (!ver)
index b315d1f..524a203 100644 (file)
@@ -132,6 +132,7 @@ main (int argc, char **argv )
     GpgmeData sig, text;
     GpgmeSigStat status;
     char *nota;
+    int n = 0;
 
     err = gpgme_new (&ctx);
     fail_if_err (err);
@@ -166,6 +167,7 @@ main (int argc, char **argv )
     fail_if_err (err);
     gpgme_data_rewind ( sig );
     err = gpgme_op_verify (ctx, sig, text, &status );
+
     print_sig_stat ( ctx, status );
     fail_if_err (err);
     if ( (nota=gpgme_get_notation (ctx)) )
@@ -174,7 +176,7 @@ main (int argc, char **argv )
     gpgme_data_release (sig);
     gpgme_data_release (text);
  
-} while ( argc > 1 && !strcmp( argv[1], "--loop" ) );
+} while ( argc > 1 && !strcmp( argv[1], "--loop" ) && ++n < 20 );
       gpgme_release (ctx);
     
     return 0;