mirror of
git://git.gnupg.org/gnupg.git
synced 2025-02-01 16:33:02 +01:00
* keyserver-internal.h, keyserver.c (print_keyrec, parse_keyrec,
show_prompt, keyserver_search_prompt, keyserver_spawn): Go to version 1 of the keyserver protocol. This is a better design, similar to --with-colons, that allows for keys with multiple user IDs rather than using multiple keys. It also matches the machine readable pksd format. Also use a prettier --search-keys listing format that can fill different size windows (currently set at 24 lines).
This commit is contained in:
parent
a94053810c
commit
da1c9e820c
@ -1,3 +1,14 @@
|
||||
2002-10-14 David Shaw <dshaw@jabberwocky.com>
|
||||
|
||||
* keyserver-internal.h, keyserver.c (print_keyrec, parse_keyrec,
|
||||
show_prompt, keyserver_search_prompt, keyserver_spawn): Go to
|
||||
version 1 of the keyserver protocol. This is a better design,
|
||||
similar to --with-colons, that allows for keys with multiple user
|
||||
IDs rather than using multiple keys. It also matches the machine
|
||||
readable pksd format. Also use a prettier --search-keys listing
|
||||
format that can fill different size windows (currently set at 24
|
||||
lines).
|
||||
|
||||
2002-10-12 Werner Koch <wk@gnupg.org>
|
||||
|
||||
* keygen.c (print_status_key_created): New.
|
||||
|
@ -17,6 +17,5 @@ int keyserver_import_fprint(const byte *fprint,size_t fprint_len);
|
||||
int keyserver_import_keyid(u32 *keyid);
|
||||
int keyserver_refresh(STRLIST users);
|
||||
int keyserver_search(STRLIST tokens);
|
||||
void keyserver_search_prompt(IOBUF buffer,int count,const char *searchstr);
|
||||
|
||||
#endif /* !_KEYSERVER_INTERNAL_H_ */
|
||||
|
630
g10/keyserver.c
630
g10/keyserver.c
@ -32,17 +32,26 @@
|
||||
#include "i18n.h"
|
||||
#include "iobuf.h"
|
||||
#include "memory.h"
|
||||
#include "ttyio.h"
|
||||
#include "options.h"
|
||||
#include "packet.h"
|
||||
#include "keyserver-internal.h"
|
||||
#include "util.h"
|
||||
|
||||
#define KEYSERVER_PROTO_VERSION 0
|
||||
|
||||
#define GET 0
|
||||
#define SEND 1
|
||||
#define SEARCH 2
|
||||
|
||||
struct keyrec
|
||||
{
|
||||
KEYDB_SEARCH_DESC desc;
|
||||
time_t createtime,expiretime;
|
||||
int size,flags;
|
||||
byte type;
|
||||
IOBUF uidbuf;
|
||||
int lines;
|
||||
};
|
||||
|
||||
struct kopts
|
||||
{
|
||||
char *name;
|
||||
@ -61,6 +70,9 @@ struct kopts
|
||||
{NULL}
|
||||
};
|
||||
|
||||
static int keyserver_work(int action,STRLIST list,
|
||||
KEYDB_SEARCH_DESC *desc,int count);
|
||||
|
||||
void
|
||||
parse_keyserver_options(char *options)
|
||||
{
|
||||
@ -218,119 +230,412 @@ parse_keyserver_uri(char *uri,const char *configname,unsigned int configlineno)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Unquote only the delimiter character and backslashes (\x5C) */
|
||||
static void
|
||||
printunquoted(char *string,char delim)
|
||||
static void
|
||||
print_keyrec(int number,struct keyrec *keyrec)
|
||||
{
|
||||
char *ch=string;
|
||||
int i;
|
||||
|
||||
while(*ch)
|
||||
iobuf_writebyte(keyrec->uidbuf,0);
|
||||
iobuf_flush_temp(keyrec->uidbuf);
|
||||
printf("(%d)\t%s ",number,iobuf_get_temp_buffer(keyrec->uidbuf));
|
||||
|
||||
if(keyrec->size>0)
|
||||
printf("%d bit ",keyrec->size);
|
||||
|
||||
if(keyrec->type)
|
||||
{
|
||||
if(*ch=='\\')
|
||||
{
|
||||
int c;
|
||||
const char *str=pubkey_algo_to_string(keyrec->type);
|
||||
|
||||
sscanf(ch,"\\x%02x",&c);
|
||||
if(c==delim)
|
||||
{
|
||||
printf("%c",c);
|
||||
ch+=3;
|
||||
}
|
||||
else if(c=='\\')
|
||||
{
|
||||
fputc('\\',stdout);
|
||||
ch+=3;
|
||||
}
|
||||
else
|
||||
fputc(*ch,stdout);
|
||||
}
|
||||
if(str)
|
||||
printf("%s ",str);
|
||||
else
|
||||
fputc(*ch,stdout);
|
||||
|
||||
ch++;
|
||||
printf("unknown ");
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
print_keyinfo(int count,char *keystring,KEYDB_SEARCH_DESC *desc)
|
||||
{
|
||||
char *certid,*userid,*keytype,*tok;
|
||||
int flags,keysize=0;
|
||||
time_t createtime=0,expiretime=0,modifytime=0;
|
||||
switch(keyrec->desc.mode)
|
||||
{
|
||||
case KEYDB_SEARCH_MODE_SHORT_KID:
|
||||
printf("key %08lX",(ulong)keyrec->desc.u.kid[1]);
|
||||
break;
|
||||
|
||||
if((certid=strsep(&keystring,":"))==NULL)
|
||||
return -1;
|
||||
case KEYDB_SEARCH_MODE_LONG_KID:
|
||||
printf("key %08lX%08lX",(ulong)keyrec->desc.u.kid[0],
|
||||
(ulong)keyrec->desc.u.kid[1]);
|
||||
break;
|
||||
|
||||
classify_user_id (certid, desc);
|
||||
if(desc->mode!=KEYDB_SEARCH_MODE_SHORT_KID &&
|
||||
desc->mode!=KEYDB_SEARCH_MODE_LONG_KID &&
|
||||
desc->mode!=KEYDB_SEARCH_MODE_FPR16 &&
|
||||
desc->mode!=KEYDB_SEARCH_MODE_FPR20)
|
||||
return -1;
|
||||
case KEYDB_SEARCH_MODE_FPR16:
|
||||
printf("key ");
|
||||
for(i=0;i<16;i++)
|
||||
printf("%02X",(unsigned char)keyrec->desc.u.fpr[i]);
|
||||
break;
|
||||
|
||||
if((tok=strsep(&keystring,":"))==NULL)
|
||||
return -1;
|
||||
case KEYDB_SEARCH_MODE_FPR20:
|
||||
printf("key ");
|
||||
for(i=0;i<20;i++)
|
||||
printf("%02X",(unsigned char)keyrec->desc.u.fpr[i]);
|
||||
break;
|
||||
|
||||
userid=utf8_to_native(tok,strlen(tok),0);
|
||||
default:
|
||||
BUG();
|
||||
break;
|
||||
}
|
||||
|
||||
if((tok=strsep(&keystring,":"))==NULL)
|
||||
goto fail;
|
||||
if(keyrec->createtime>0)
|
||||
printf(", created %s",strtimestamp(keyrec->createtime));
|
||||
|
||||
flags=atoi(tok);
|
||||
if(keyrec->expiretime>0)
|
||||
printf(", expires %s",strtimestamp(keyrec->expiretime));
|
||||
|
||||
if((tok=strsep(&keystring,":"))==NULL)
|
||||
goto fail;
|
||||
|
||||
createtime=atoi(tok);
|
||||
|
||||
if((tok=strsep(&keystring,":"))==NULL)
|
||||
goto fail;
|
||||
|
||||
expiretime=atoi(tok);
|
||||
|
||||
if((tok=strsep(&keystring,":"))==NULL)
|
||||
goto fail;
|
||||
|
||||
modifytime=atoi(tok);
|
||||
|
||||
if((keytype=strsep(&keystring,":"))==NULL)
|
||||
goto fail;
|
||||
|
||||
/* The last one */
|
||||
if(keystring!=NULL)
|
||||
keysize=atoi(keystring);
|
||||
|
||||
printf("(%d)\t",count);
|
||||
|
||||
/* No need to check for control characters, as utf8_to_native does
|
||||
this for us. */
|
||||
printunquoted(userid,':');
|
||||
|
||||
if(flags&1)
|
||||
printf(" (revoked)");
|
||||
if(flags&2)
|
||||
printf(" (disabled)");
|
||||
|
||||
printf("\n\t ");
|
||||
|
||||
if(keysize>0)
|
||||
printf("%d bit ",keysize);
|
||||
|
||||
if(keytype[0])
|
||||
printf("%s ",keytype);
|
||||
|
||||
printf("key %s, created %s",certid,strtimestamp(createtime));
|
||||
|
||||
if(expiretime>0)
|
||||
printf(", expires %s",strtimestamp(expiretime));
|
||||
if(keyrec->flags&1)
|
||||
printf(" (%s)",("revoked"));
|
||||
if(keyrec->flags&2)
|
||||
printf(" (%s)",("disabled"));
|
||||
if(keyrec->flags&4)
|
||||
printf(" (%s)",("expired"));
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
/* Returns a keyrec (which must be freed) once a key is complete, and
|
||||
NULL otherwise. Call with a NULL keystring once key parsing is
|
||||
complete to return any unfinished keys. */
|
||||
static struct keyrec *
|
||||
parse_keyrec(char *keystring)
|
||||
{
|
||||
static struct keyrec *work=NULL;
|
||||
struct keyrec *ret=NULL;
|
||||
char *record,*tok;
|
||||
int i;
|
||||
|
||||
if(keystring==NULL)
|
||||
{
|
||||
if(work==NULL)
|
||||
return NULL;
|
||||
else if(work->desc.mode==KEYDB_SEARCH_MODE_NONE)
|
||||
{
|
||||
m_free(work);
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret=work;
|
||||
work=NULL;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if(work==NULL)
|
||||
{
|
||||
work=m_alloc_clear(sizeof(struct keyrec));
|
||||
work->uidbuf=iobuf_temp();
|
||||
}
|
||||
|
||||
/* Remove trailing whitespace */
|
||||
for(i=strlen(keystring);i>0;i--)
|
||||
if(isspace(keystring[i-1]))
|
||||
keystring[i-1]='\0';
|
||||
else
|
||||
break;
|
||||
|
||||
if((record=strsep(&keystring,":"))==NULL)
|
||||
return ret;
|
||||
|
||||
if(ascii_strcasecmp("pub",record)==0)
|
||||
{
|
||||
if(work->desc.mode)
|
||||
{
|
||||
ret=work;
|
||||
work=m_alloc_clear(sizeof(struct keyrec));
|
||||
work->uidbuf=iobuf_temp();
|
||||
}
|
||||
|
||||
if((tok=strsep(&keystring,":"))==NULL)
|
||||
return ret;
|
||||
|
||||
classify_user_id(tok,&work->desc);
|
||||
if(work->desc.mode!=KEYDB_SEARCH_MODE_SHORT_KID
|
||||
&& work->desc.mode!=KEYDB_SEARCH_MODE_LONG_KID
|
||||
&& work->desc.mode!=KEYDB_SEARCH_MODE_FPR16
|
||||
&& work->desc.mode!=KEYDB_SEARCH_MODE_FPR20)
|
||||
{
|
||||
work->desc.mode=KEYDB_SEARCH_MODE_NONE;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Note all items after this are optional. This allows us to
|
||||
have a pub line as simple as pub:keyid and nothing else. */
|
||||
|
||||
work->lines++;
|
||||
|
||||
if((tok=strsep(&keystring,":"))==NULL)
|
||||
return ret;
|
||||
|
||||
work->type=atoi(tok);
|
||||
|
||||
if((tok=strsep(&keystring,":"))==NULL)
|
||||
return ret;
|
||||
|
||||
work->size=atoi(tok);
|
||||
|
||||
if((tok=strsep(&keystring,":"))==NULL)
|
||||
return ret;
|
||||
|
||||
work->createtime=atoi(tok);
|
||||
|
||||
if((tok=strsep(&keystring,":"))==NULL)
|
||||
return ret;
|
||||
|
||||
work->expiretime=atoi(tok);
|
||||
|
||||
if((tok=strsep(&keystring,":"))==NULL)
|
||||
return ret;
|
||||
|
||||
while(*tok)
|
||||
switch(*tok++)
|
||||
{
|
||||
case 'r':
|
||||
case 'R':
|
||||
work->flags|=1;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
case 'D':
|
||||
work->flags|=2;
|
||||
break;
|
||||
|
||||
case 'e':
|
||||
case 'E':
|
||||
work->flags|=4;
|
||||
break;
|
||||
}
|
||||
|
||||
if(work->expiretime && work->expiretime<=make_timestamp())
|
||||
work->flags|=4;
|
||||
}
|
||||
else if(ascii_strcasecmp("uid",record)==0 && work->desc.mode)
|
||||
{
|
||||
char *userid,*tok,*decoded;
|
||||
int i=0;
|
||||
|
||||
if((tok=strsep(&keystring,":"))==NULL)
|
||||
return ret;
|
||||
|
||||
if(strlen(tok)==0)
|
||||
return ret;
|
||||
|
||||
userid=tok;
|
||||
|
||||
/* By definition, de-%-encoding is always smaller than the
|
||||
original string so we can decode in place. */
|
||||
|
||||
while(*tok)
|
||||
if(tok[0]=='%' && tok[1] && tok[2])
|
||||
{
|
||||
if((userid[i]=hextobyte(&tok[1]))==-1)
|
||||
userid[i]='?';
|
||||
|
||||
i++;
|
||||
tok+=3;
|
||||
}
|
||||
else
|
||||
userid[i++]=*tok++;
|
||||
|
||||
/* We don't care about the other info provided in the uid: line
|
||||
since no keyserver supports marking userids with timestamps
|
||||
or revoked/expired/disabled yet. */
|
||||
|
||||
/* No need to check for control characters, as utf8_to_native
|
||||
does this for us. */
|
||||
|
||||
decoded=utf8_to_native(userid,i,0);
|
||||
iobuf_writestr(work->uidbuf,decoded);
|
||||
m_free(decoded);
|
||||
iobuf_writestr(work->uidbuf,"\n\t");
|
||||
work->lines++;
|
||||
}
|
||||
|
||||
/* Ignore any records other than "pri" and "uid" for easy future
|
||||
growth. */
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* TODO: do this as a list sent to keyserver_work rather than calling
|
||||
it once for each key to get the correct counts after the import
|
||||
(cosmetics, really) and to better take advantage of the keyservers
|
||||
that can do multiple fetches in one go (LDAP). */
|
||||
static int
|
||||
show_prompt(KEYDB_SEARCH_DESC *desc,int numdesc,int count,const char *search)
|
||||
{
|
||||
char *answer;
|
||||
|
||||
if(count)
|
||||
{
|
||||
static int from=1;
|
||||
tty_printf("Keys %d-%d of %d for \"%s\". ",from,numdesc,count,search);
|
||||
from=numdesc+1;
|
||||
}
|
||||
|
||||
answer=cpr_get_no_help("keysearch.prompt",
|
||||
_("Enter number(s), N)ext, or Q)uit > "));
|
||||
/* control-d */
|
||||
if(answer[0]=='\x04')
|
||||
{
|
||||
printf("Q\n");
|
||||
answer[0]='q';
|
||||
}
|
||||
|
||||
if(answer[0]=='q' || answer[0]=='Q')
|
||||
{
|
||||
m_free(answer);
|
||||
return 1;
|
||||
}
|
||||
else if(atoi(answer)>=1 && atoi(answer)<=numdesc)
|
||||
{
|
||||
char *split=answer,*num;
|
||||
|
||||
while((num=strsep(&split," ,"))!=NULL)
|
||||
if(atoi(num)>=1 && atoi(num)<=numdesc)
|
||||
keyserver_work(GET,NULL,&desc[atoi(num)-1],1);
|
||||
|
||||
m_free(answer);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
fail:
|
||||
m_free (userid);
|
||||
return -1;
|
||||
/* Count and searchstr are just for cosmetics. If the count is too
|
||||
small, it will grow safely. If negative it disables the "Key x-y
|
||||
of z" messages. */
|
||||
static void
|
||||
keyserver_search_prompt(IOBUF buffer,const char *searchstr)
|
||||
{
|
||||
int i=0,validcount=0,started=0,count=1;
|
||||
unsigned int maxlen,buflen;
|
||||
KEYDB_SEARCH_DESC *desc;
|
||||
byte *line=NULL;
|
||||
/* TODO: Something other than 23? That's 24-1 (the prompt). */
|
||||
int maxlines=23,numlines=0;
|
||||
|
||||
desc=m_alloc(count*sizeof(KEYDB_SEARCH_DESC));
|
||||
|
||||
for(;;)
|
||||
{
|
||||
struct keyrec *keyrec;
|
||||
int rl;
|
||||
|
||||
maxlen=1024;
|
||||
rl=iobuf_read_line(buffer,&line,&buflen,&maxlen);
|
||||
|
||||
/* Look for an info: line. The only current info: values
|
||||
defined are the version and key count. */
|
||||
if(!started && rl>0 && ascii_strncasecmp("info:",line,5)==0)
|
||||
{
|
||||
char *tok,*str=&line[5];
|
||||
|
||||
if((tok=strsep(&str,":"))!=NULL)
|
||||
{
|
||||
int version;
|
||||
|
||||
if(sscanf(tok,"%d",&version)!=1)
|
||||
version=1;
|
||||
|
||||
if(version!=1)
|
||||
{
|
||||
log_error(_("invalid keyserver protocol "
|
||||
"(us %d!=handler %d)\n"),1,version);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if((tok=strsep(&str,":"))!=NULL && sscanf(tok,"%d",&count)==1)
|
||||
{
|
||||
if(count==0)
|
||||
goto notfound;
|
||||
else if(count<0)
|
||||
count=10;
|
||||
else
|
||||
validcount=1;
|
||||
|
||||
desc=m_realloc(desc,count*sizeof(KEYDB_SEARCH_DESC));
|
||||
}
|
||||
|
||||
started=1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(rl==0)
|
||||
{
|
||||
keyrec=parse_keyrec(NULL);
|
||||
|
||||
if(keyrec==NULL)
|
||||
{
|
||||
if(i==0)
|
||||
{
|
||||
count=0;
|
||||
break;
|
||||
}
|
||||
|
||||
if(i!=count)
|
||||
validcount=0;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
if(show_prompt(desc,i,validcount?count:0,searchstr))
|
||||
break;
|
||||
validcount=0;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
keyrec=parse_keyrec(line);
|
||||
|
||||
if(i==count)
|
||||
{
|
||||
/* keyserver helper sent more keys than they claimed in the
|
||||
info: line. */
|
||||
count+=10;
|
||||
desc=m_realloc(desc,count*sizeof(KEYDB_SEARCH_DESC));
|
||||
validcount=0;
|
||||
}
|
||||
|
||||
if(keyrec)
|
||||
{
|
||||
desc[i]=keyrec->desc;
|
||||
|
||||
if(numlines+keyrec->lines>maxlines)
|
||||
{
|
||||
if(show_prompt(desc,i,validcount?count:0,searchstr))
|
||||
break;
|
||||
else
|
||||
numlines=0;
|
||||
}
|
||||
|
||||
print_keyrec(i+1,keyrec);
|
||||
numlines+=keyrec->lines;
|
||||
iobuf_close(keyrec->uidbuf);
|
||||
m_free(keyrec);
|
||||
|
||||
started=1;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
m_free(desc);
|
||||
m_free(line);
|
||||
|
||||
notfound:
|
||||
if(count==0)
|
||||
{
|
||||
if(searchstr)
|
||||
log_info(_("key \"%s\" not found on keyserver\n"),searchstr);
|
||||
else
|
||||
log_info(_("key not found on keyserver\n"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#define KEYSERVER_ARGS_KEEP " -o \"%O\" \"%I\""
|
||||
@ -549,8 +854,8 @@ keyserver_spawn(int action,STRLIST list,
|
||||
|
||||
for(;;)
|
||||
{
|
||||
char *ptr;
|
||||
int plen;
|
||||
char *ptr;
|
||||
|
||||
maxlen=1024;
|
||||
if(iobuf_read_line(spawn->fromchild,&line,&buflen,&maxlen)==0)
|
||||
@ -628,19 +933,7 @@ keyserver_spawn(int action,STRLIST list,
|
||||
|
||||
case SEARCH:
|
||||
{
|
||||
/* Look for the COUNT line */
|
||||
do
|
||||
{
|
||||
maxlen=1024;
|
||||
if(iobuf_read_line(spawn->fromchild,&line,&buflen,&maxlen)==0)
|
||||
{
|
||||
ret=G10ERR_READ_FILE;
|
||||
goto fail; /* i.e. EOF */
|
||||
}
|
||||
}
|
||||
while(sscanf(line,"COUNT %d\n",&i)!=1);
|
||||
|
||||
keyserver_search_prompt(spawn->fromchild,i,searchstr);
|
||||
keyserver_search_prompt(spawn->fromchild,searchstr);
|
||||
|
||||
break;
|
||||
}
|
||||
@ -693,6 +986,12 @@ keyserver_work(int action,STRLIST list,KEYDB_SEARCH_DESC *desc,int count)
|
||||
action==GET?"get":action==SEND?"send":
|
||||
action==SEARCH?"search":"unknown",
|
||||
opt.keyserver_scheme);
|
||||
break;
|
||||
|
||||
case KEYSERVER_VERSION_ERROR:
|
||||
log_error(_("gpgkeys_%s does not support handler version %d\n"),
|
||||
opt.keyserver_scheme,KEYSERVER_PROTO_VERSION);
|
||||
break;
|
||||
|
||||
case KEYSERVER_INTERNAL_ERROR:
|
||||
default:
|
||||
@ -963,114 +1262,3 @@ keyserver_search(STRLIST tokens)
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Count and searchstr are just for cosmetics. If the count is too
|
||||
small, it will grow safely. If negative it disables the "Key x-y
|
||||
of z" messages. */
|
||||
|
||||
/* TODO: do this as a list sent to keyserver_work rather than calling
|
||||
it once for each key to get the correct counts after the import
|
||||
(cosmetics, really) and to better take advantage of the keyservers
|
||||
that can do multiple fetches in one go (LDAP). */
|
||||
void
|
||||
keyserver_search_prompt(IOBUF buffer,int count,const char *searchstr)
|
||||
{
|
||||
int i=0,validcount=1;
|
||||
unsigned int maxlen,buflen;
|
||||
KEYDB_SEARCH_DESC *desc;
|
||||
byte *line=NULL;
|
||||
char *answer;
|
||||
|
||||
if(count==0)
|
||||
goto notfound;
|
||||
|
||||
if(count<0)
|
||||
{
|
||||
validcount=0;
|
||||
count=10;
|
||||
}
|
||||
|
||||
desc=m_alloc(count*sizeof(KEYDB_SEARCH_DESC));
|
||||
|
||||
/* Read each line and show it to the user */
|
||||
|
||||
for(;;)
|
||||
{
|
||||
int rl;
|
||||
|
||||
if(validcount && i%10==0)
|
||||
{
|
||||
printf("Keys %d-%d of %d",i+1,(i+10<count)?i+10:count,count);
|
||||
if(searchstr)
|
||||
printf(" for \"%s\"",searchstr);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
maxlen=1024;
|
||||
rl=iobuf_read_line(buffer,&line,&buflen,&maxlen);
|
||||
if(rl>0)
|
||||
{
|
||||
if(print_keyinfo(i+1,line,&desc[i])==0)
|
||||
{
|
||||
i++;
|
||||
|
||||
if(i==count)
|
||||
{
|
||||
count+=10;
|
||||
desc=m_realloc(desc,count*sizeof(KEYDB_SEARCH_DESC));
|
||||
validcount=0;
|
||||
}
|
||||
}
|
||||
else
|
||||
continue;
|
||||
}
|
||||
|
||||
if(rl==0 && i==0)
|
||||
{
|
||||
count=0;
|
||||
break;
|
||||
}
|
||||
|
||||
if(i%10==0 || rl==0)
|
||||
{
|
||||
answer=cpr_get_no_help("keysearch.prompt",
|
||||
_("Enter number(s), N)ext, or Q)uit > "));
|
||||
/* control-d */
|
||||
if(answer[0]=='\x04')
|
||||
{
|
||||
printf("Q\n");
|
||||
answer[0]='q';
|
||||
}
|
||||
|
||||
if(answer[0]=='q' || answer[0]=='Q')
|
||||
{
|
||||
m_free(answer);
|
||||
break;
|
||||
}
|
||||
else if(atoi(answer)>=1 && atoi(answer)<=i)
|
||||
{
|
||||
char *split=answer,*num;
|
||||
|
||||
while((num=strsep(&split," ,"))!=NULL)
|
||||
if(atoi(num)>=1 && atoi(num)<=i)
|
||||
keyserver_work(GET,NULL,&desc[atoi(num)-1],1);
|
||||
|
||||
m_free(answer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_free(desc);
|
||||
m_free(line);
|
||||
|
||||
notfound:
|
||||
if(count==0)
|
||||
{
|
||||
if(searchstr)
|
||||
log_info(_("key \"%s\" not found on keyserver\n"),searchstr);
|
||||
else
|
||||
log_info(_("key not found on keyserver\n"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user