Add progress CB and subkey listing

This commit is contained in:
Werner Koch 2000-12-19 10:07:32 +00:00
parent a92ecd4470
commit 6b4ca13dd4
13 changed files with 229 additions and 76 deletions

1
README
View File

@ -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.

View 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)

View 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;
};

View File

@ -31,8 +31,33 @@
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 );

View 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;
}

View 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 );
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 );
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);

View 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 )

View 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 );

View 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 )

View 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++;
}

View 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;
}
}

View 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

View File

@ -32,6 +32,13 @@
} 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"