diff options
| -rw-r--r-- | gpgme/ChangeLog | 25 | ||||
| -rw-r--r-- | gpgme/decrypt.c | 4 | ||||
| -rw-r--r-- | gpgme/encrypt.c | 1 | ||||
| -rw-r--r-- | gpgme/key.c | 195 | ||||
| -rw-r--r-- | gpgme/key.h | 5 | ||||
| -rw-r--r-- | gpgme/keylist.c | 6 | ||||
| -rw-r--r-- | gpgme/rungpg.c | 1 | ||||
| -rw-r--r-- | gpgme/verify.c | 28 | ||||
| -rw-r--r-- | gpgme/version.c | 7 | ||||
| -rw-r--r-- | tests/t-verify.c | 4 | 
10 files changed, 251 insertions, 25 deletions
| diff --git a/gpgme/ChangeLog b/gpgme/ChangeLog index 017ab28b..a8242e5b 100644 --- a/gpgme/ChangeLog +++ b/gpgme/ChangeLog @@ -1,3 +1,26 @@ +2001-05-28  Werner Koch  <[email protected]> + +	* 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 <[email protected]> + +	* 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  <[email protected]> + +	* 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  <[email protected]>  	* keylist.c (parse_timestamp): Adjusted for the changed @@ -208,4 +231,4 @@   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 +	 diff --git a/gpgme/decrypt.c b/gpgme/decrypt.c index 526a8156..5982301b 100644 --- a/gpgme/decrypt.c +++ b/gpgme/decrypt.c @@ -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; diff --git a/gpgme/encrypt.c b/gpgme/encrypt.c index 5234cc8b..3fe60a62 100644 --- a/gpgme/encrypt.c +++ b/gpgme/encrypt.c @@ -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); diff --git a/gpgme/key.c b/gpgme/key.c index f61d2c1c..966675e3 100644 --- a/gpgme/key.c +++ b/gpgme/key.c @@ -31,6 +31,199 @@  #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 )  { diff --git a/gpgme/key.h b/gpgme/key.h index 60244e97..003821a5 100644 --- a/gpgme/key.h +++ b/gpgme/key.h @@ -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 ); diff --git a/gpgme/keylist.c b/gpgme/keylist.c index 9d7824bb..11e10cf2 100644 --- a/gpgme/keylist.c +++ b/gpgme/keylist.c @@ -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); diff --git a/gpgme/rungpg.c b/gpgme/rungpg.c index 6f731e51..708b2781 100644 --- a/gpgme/rungpg.c +++ b/gpgme/rungpg.c @@ -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; diff --git a/gpgme/verify.c b/gpgme/verify.c index 0d50b8a9..3b2174b6 100644 --- a/gpgme/verify.c +++ b/gpgme/verify.c @@ -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;  } diff --git a/gpgme/version.c b/gpgme/version.c index 0d8e5a7c..74b6576d 100644 --- a/gpgme/version.c +++ b/gpgme/version.c @@ -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) diff --git a/tests/t-verify.c b/tests/t-verify.c index b315d1f1..524a203e 100644 --- a/tests/t-verify.c +++ b/tests/t-verify.c @@ -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; | 
