Version: (using KDE KDE 3.1.93) Installed from: Compiled From Sources Compiler: gcc3.2 OS: FreeBSD KDE Version: 3.1.93 (kde3.2 beta) Kgpg Version: 1.0.99 Problem Description: Generating key pair does not show up in key list Reproduce: Start with empty key list. Generate a key pair, go through normal motions of generating a key. When the key is generated, it does not show up in the list.
Subject: Re: generated key not in key list Hello ! I cannot reproduce the bug. Could you update your cvs and see if it still happens ? Does it only happen if there is no key in the list ? regards
I'm running kde 3.2 beta 2. If i do a 'gpg --list-keys' i get a list of a few keys, but when i start kgpg, zero keys show up. I mentioned an empty keylist above because that's all that i have seen so far, but i don't think that's a factor. So i guess a better description of the bug is that 'gpg --list-keys' does not populate kgpg's display. I'm using gpg (GnuPG) 1.2.2 if that makes any difference. Is there a verbose flag i can execute kgpg with to see what it is trying to do?
Subject: Re: generated key not in key list > If i do a 'gpg --list-keys' i get a list of a few keys, but when i start > kgpg, zero keys show up. I mentioned an empty keylist above because that's > all that i have seen so far, but i don't think that's a factor. So i guess > a better description of the bug is that 'gpg --list-keys' does not populate > kgpg's display. Could you please send me the output the following command: gpg --with-colon --list-keys You can also try to start KGpg from a console, it may give you some output in the console view. Are you sure the gpg binary is in your path (executable from your home directory ?) Nobody ever reported such a problem. Thanks to give me all informations, It would be really nice to find & fix the problem before the final release. regards
More specs on my system FreeBSD 5.1. After talking with the developer it seems that the problem is with the fgets() function calls in listkeys.cpp in the function KeyView::refreshkeylist(). Here is some output with added debugging code (the intersting output is the last three lines). FreeBSD| brad@lou > ./kgpg --nofork QSettings::sync: filename is null/empty kgpg: New instance kgpg: Starting KGpg kdecore (KConfigSkeleton): Creating KConfigSkeleton (0x8238c00) kdecore (KConfigSkeleton): KConfigSkeleton::readConfig() kdecore (KAccel): WARNING: KKeySequence::init( seq ): key[0] is null. kdecore (KAccel): WARNING: KKeySequence::init( seq ): key[0] is null. QMetaObject::findSignal:KeyView: Conflict with QListView::doubleClicked(QListViewItem*,const QPoint&,int) kgpg: Fgets error no is : 35 kgpg: Error is : Resource temporarily unavailable kgpg: Last line read is : p??0
Using popen() with gpg is nasty; the pty stuff hard to understand (I have a great example showing resource unavailable bugs, BTW). kgpg would need KProcess if it weren't in much bigger need of a complete rewrite using gpgme and the rest of the improved crypto stuff Mutz is working on.
Again, misunderstood.
can't reproduce this bug with kde 3.4.2
This may be the result of an bug of the settings. KGPG do not find the gpg configuration file. On Linux / Unix per default ~/.gnupg/gpg.conf. If you open the setup dialog and change the "GnuPG" settings (to show the hidden .gnupg directory the right mouse buttom have to be used over the listing!!!!!!) so that the gnupg configuration is shown, you get your secret keys displayed.
I think the much greater problem is that kgpg is not using gpgme but rather it's using the gpg command line interface directly through system calls such as popen(), for example, kgpg/listkeys.cpp:249 fp = popen("gpg --no-tty --with-colon --list-secret-keys", "r"); The behavior of these calls is not portable at all. The think the use gpgme will greatly improve the portability of kgpg.
SVN commit 708873 by dakon: Clean up scanning for possible default keys in KGpg wizard If the wizard comes up it does it's own scanning for secret keys. It uses the popen() function reported as unportable. In fact it's not really needed at all as the actions performed here are already implemented in the KgpgInterface class. CCBUG:68470 M +22 -34 kgpg.cpp --- trunk/KDE/kdeutils/kgpg/kgpg.cpp #708872:708873 @@ -767,46 +767,34 @@ wiz->kURLRequester2->setURL(KGlobalSettings::desktopPath()); wiz->kURLRequester2->setMode(2);*/ - FILE *fp,*fp2; - QString tst; - QString tst2; - QString name; - QString trustedvals = "idre-"; QString firstKey = QString(); - char line[300]; - bool counter = false; - fp = popen("gpg --no-tty --with-colon --list-secret-keys", "r"); - while (fgets(line, sizeof(line), fp)) - { - tst = line; - if (tst.startsWith("sec")) - { - name = KgpgInterface::checkForUtf8(tst.section(':', 9, 9)); - if (!name.isEmpty()) - { - fp2 = popen("gpg --no-tty --with-colon --list-keys " + QFile::encodeName(tst.section(':',4,4)), "r"); - while (fgets( line, sizeof(line), fp2)) - { - tst2 = line; - if (tst2.startsWith("pub") && !trustedvals.contains(tst2.section(':',1,1))) - { - counter = true; - wiz->CBdefault->addItem(tst.section(':', 4, 4).right(8) + ": " + name); - if (firstKey.isEmpty()) - firstKey=tst.section(':',4,4).right(8)+": "+name; - break; - } - } - pclose(fp2); - } + KgpgInterface *interface = new KgpgInterface(); + KgpgKeyList secretlist = interface->readSecretKeys(); + + QStringList issec; + int i; + for (i = 0; i < secretlist.size(); ++i) + issec << secretlist.at(i).fullId(); + + KgpgKeyList publiclist = interface->readPublicKeys(true, issec); + delete interface; + + for (i = 0; i < publiclist.size(); ++i) + if (publiclist.at(i).trust() >= TRUST_FULL) { + KgpgKey k = publiclist.at(i); + + QString s = k.fullId().right(8) + ": " + k.name() + " <" + k.email() + '>'; + + wiz->CBdefault->addItem(s); + if (firstKey.isEmpty()) + firstKey = s; } - } - pclose(fp); + wiz->CBdefault->setCurrentItem(firstKey); //connect(wiz->pushButton4,SIGNAL(clicked()),this,SLOT(slotGenKey())); - if (!counter) + if (!firstKey.isEmpty()) connect(wiz->finishButton(),SIGNAL(clicked()),this,SLOT(slotGenKey())); else {
SVN commit 709135 by dakon: Remove another instance of the unportable popen() The newly introduced function can work with more than one signature at once. Currently this is not supported by the rest of the program but I don't see any benefit in introducing a new function with another limitation. Deletion of multiple signatures at once will come when the feature freeze is lifted. CCBUG:68470 M +30 -21 kgpginterface.cpp M +5 -0 kgpginterface.h --- trunk/KDE/kdeutils/kgpg/kgpginterface.cpp #709134:709135 @@ -2959,33 +2959,21 @@ // delete signature void KgpgInterface::KgpgDelSignature(const QString &keyID, const QString &uid, QString signKeyID) { - message = signKeyID.remove(0, 2); deleteSuccess = false; step = 0; - FILE *fp; QString encResult; - char buffer[200]; signb = 0; sigsearch = 0; - int curuid = 1; - int tgtuid = uid.toInt(); + QList<int> signoff; - QString gpgcmd = "gpg --no-tty --no-secmem-warning --with-colon --list-sigs " + keyID; - fp = popen(QFile::encodeName(gpgcmd), "r"); - while (fgets( buffer, sizeof(buffer), fp)) - { - encResult = buffer; - if (encResult.startsWith("uid")) - curuid++; - else if (encResult.startsWith("sig") && (curuid == tgtuid)) { - if (encResult.contains(message)) - break; - signb++; - } else if (encResult.startsWith("rev")) - signb++; - } - pclose(fp); + findSigns(keyID, QStringList(signKeyID), uid, &signoff); + + if (signoff.count() == 0) + return; + + signb = signoff.at(0); + K3ProcIO *conprocess = gpgProc(2, 0); *conprocess << "--edit-key" << keyID << "uid" << uid << "delsig"; connect(conprocess,SIGNAL(readReady(K3ProcIO *)),this,SLOT(delsigprocess(K3ProcIO *))); @@ -2993,7 +2981,6 @@ conprocess->start(K3Process::NotifyOnExit,true); } - void KgpgInterface::delsigprocess(K3ProcIO *p)//ess *p,char *buf, int buflen) { @@ -3130,4 +3117,26 @@ return process; } +void KgpgInterface::findSigns(const QString &keyID, const QStringList &ids, const QString &uid, QList<int> *res) +{ + K3ProcIO* listproc = gpgProc(1); + *listproc << "--with-colons" << "--list-sigs" << keyID; + listproc->start(K3Process::Block, false); + + QString line; + int curuid = 1; + int signs = 0; + int tgtuid = uid.toInt(); + + while (listproc->readln(line, true) != -1) { + if (line.startsWith("sig:") && (tgtuid == curuid)) { + if (ids.contains(line.section(':', 4, 4), Qt::CaseInsensitive)) + *res << signs; + signs++; + } else if (line.startsWith("uid:")) { + curuid++; + } + } +} + #include "kgpginterface.moc" --- trunk/KDE/kdeutils/kgpg/kgpginterface.h #709134:709135 @@ -698,6 +698,11 @@ void delsignover(K3Process *p); /** + * Finds the offset of the given signatures to a uid + */ + void findSigns(const QString &keyID, const QStringList &ids, const QString &uid, QList<int> *res); + + /** * Checks output of the import process */ void importURLover(K3Process *p);
SVN commit 711028 by dakon: Remove another instance of popen() Again KgpgInterface already has was we need. CCBUG:68470 M +16 -17 kgpg.cpp --- trunk/KDE/kdeutils/kgpg/kgpg.cpp #711027:711028 @@ -784,7 +784,7 @@ if (publiclist.at(i).trust() >= TRUST_FULL) { KgpgKey k = publiclist.at(i); - QString s = k.fullId().right(8) + ": " + k.name() + " <" + k.email() + '>'; + QString s = k.id() + ": " + k.name() + " <" + k.email() + '>'; wiz->CBdefault->addItem(s); if (firstKey.isEmpty()) @@ -813,26 +813,25 @@ void MyView::slotWizardChange() { - QString tst,name; - char line[300]; - FILE *fp; - if (wiz->indexOf(wiz->currentPage()) == 2) { - QString defaultID = KgpgInterface::getGpgSetting("default-key", wiz->kURLRequester1->url().path()); - if (defaultID.isEmpty()) + QString tst,name; + KgpgInterface *iface = new KgpgInterface(); + QString defaultID = iface->getGpgSetting("default-key", wiz->kURLRequester1->url().path()); + + if (defaultID.isEmpty()) { + delete iface; return; - fp = popen("gpg --no-tty --with-colon --list-secret-keys " + QFile::encodeName(defaultID), "r"); - while (fgets( line, sizeof(line), fp)) - { - tst = line; - if (tst.startsWith("sec")) - { - name = KgpgInterface::checkForUtf8(tst.section(':', 9, 9)); - wiz->CBdefault->setCurrentItem(tst.section(':', 4, 4).right(8) + ": " + name); - } } - pclose(fp); + KgpgKeyList secl = iface->readSecretKeys(QStringList(defaultID)); + delete iface; + + if (secl.isEmpty()) + return; + + KgpgKey k = secl.at(0); + + wiz->CBdefault->setCurrentItem(k.id() + ": " + k.name() + " <" + k.email() + '>'); } }
Seems to work. There is only one instance of popen() left, used for the seldom needed operation of public key regeneration. Once I find a better way this will also go away.