00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "keyservers.h"
00019
00020 #include <QCursor>
00021 #include <QLabel>
00022
00023 #include <KConfig>
00024 #include <KMessageBox>
00025 #include <KLocale>
00026 #include <KDebug>
00027 #include <KDateTime>
00028
00029 #include "kgpgsettings.h"
00030 #include "detailedconsole.h"
00031 #include "convert.h"
00032 #include "gpgproc.h"
00033
00034
00035 using namespace KgpgCore;
00036
00037 ConnectionDialog::ConnectionDialog(QWidget *parent)
00038 : KProgressDialog(parent, i18n("Keyserver"), i18n("<b>Connecting to the server...</b>"))
00039 {
00040 setModal(true);
00041
00042 progressBar()->setRange(0, 0);
00043 show();
00044 }
00045
00046 KeyServer::KeyServer(QWidget *parent, const bool &modal, const bool &autoclose)
00047 : KDialog(parent)
00048 {
00049 m_searchproc = NULL;
00050
00051 setCaption(i18n("Key Server"));
00052 setButtons(Close);
00053 setModal(modal);
00054
00055 m_autoclose = autoclose;
00056
00057 page = new keyServerWidget();
00058 setMainWidget(page);
00059
00060 QStringList serverlist = getServerList();
00061 page->kCBexportks->addItems(serverlist);
00062 page->kCBimportks->addItems(serverlist);
00063 page->kLEimportid->setFocus();
00064
00065 connect(page->Buttonimport, SIGNAL(clicked()), this, SLOT(slotImport()));
00066 connect(page->Buttonsearch, SIGNAL(clicked()), this, SLOT(slotSearch()));
00067 connect(page->Buttonexport, SIGNAL(clicked()), this, SLOT(slotPreExport()));
00068 connect(this, SIGNAL(okClicked()), this, SLOT(slotOk()));
00069 connect(page->cBproxyI, SIGNAL(toggled(bool)), this, SLOT(slotEnableProxyI(bool)));
00070 connect(page->cBproxyE, SIGNAL(toggled(bool)), this, SLOT(slotEnableProxyE(bool)));
00071 connect(page->kLEimportid, SIGNAL(textChanged(const QString &)), this, SLOT(slotTextChanged(const QString &)));
00072
00073 page->cBproxyI->setChecked(KGpgSettings::useProxy());
00074 page->cBproxyE->setChecked(KGpgSettings::useProxy());
00075
00076 QString httpproxy = qgetenv("http_proxy");
00077 if (!httpproxy.isEmpty())
00078 {
00079 page->cBproxyI->setEnabled(true);
00080 page->cBproxyE->setEnabled(true);
00081 page->kLEproxyI->setText(httpproxy);
00082 page->kLEproxyE->setText(httpproxy);
00083 }
00084
00085 KgpgInterface *interface = new KgpgInterface();
00086 connect (interface, SIGNAL(readPublicKeysFinished(KgpgCore::KgpgKeyList, KgpgInterface*)), this, SLOT(slotReadKeys(KgpgCore::KgpgKeyList, KgpgInterface*)));
00087 interface->readPublicKeys();
00088
00089 page->Buttonimport->setEnabled(!page->kLEimportid->text().isEmpty());
00090 page->Buttonsearch->setEnabled(!page->kLEimportid->text().isEmpty());
00091 setMinimumSize(sizeHint());
00092 }
00093
00094 void KeyServer::slotReadKeys(KgpgKeyList list, KgpgInterface *interface)
00095 {
00096 interface->deleteLater();
00097 for (int i = 0; i < list.size(); ++i)
00098 {
00099 const KgpgKey key = list.at(i);
00100
00101 bool dead = false;
00102 if ((key.trust() == 'i') || (key.trust() == 'd') || (key.trust() == 'r') || (key.trust() == 'e'))
00103 dead = true;
00104
00105 if (!dead)
00106 {
00107 QString line = key.name();
00108 if (!key.comment().isEmpty()) line += " (" + key.comment() + ')';
00109 if (!key.email().isEmpty()) line += " <" + key.email() + '>';
00110 if (line.length() > 37)
00111 {
00112 line.remove(35, line.length());
00113 line += "...";
00114 }
00115
00116 if (!line.isEmpty())
00117 page->kCBexportkey->addItem(key.id() + ": " + line);
00118 }
00119 }
00120 }
00121
00122 void KeyServer::refreshKeys(QStringList keys)
00123 {
00124 QApplication::setOverrideCursor(QCursor(Qt::BusyCursor));
00125
00126 QString keyserv = getServerList().first();
00127
00128 QString proxy;
00129 if (KGpgSettings::useProxy())
00130 proxy = qgetenv("http_proxy");
00131
00132 KgpgInterface *interface = new KgpgInterface();
00133 connect(interface, SIGNAL(downloadKeysFinished(QList<int>, QStringList, bool, QString, KgpgInterface*)), this, SLOT(slotDownloadKeysFinished(QList<int>, QStringList, bool, QString, KgpgInterface*)));
00134 connect(interface, SIGNAL(downloadKeysAborted(KgpgInterface*)), this, SLOT(slotAbort(KgpgInterface*)));
00135
00136 m_importpop = new ConnectionDialog(this);
00137 connect(m_importpop, SIGNAL(cancelClicked()), interface, SLOT(downloadKeysAbort()));
00138
00139 interface->downloadKeys(keys, keyserv, true, proxy);
00140 }
00141
00142 void KeyServer::slotImport()
00143 {
00144 if (page->kCBimportks->currentText().isEmpty())
00145 return;
00146
00147 if (page->kLEimportid->text().isEmpty())
00148 {
00149 KMessageBox::sorry(this, i18n("You must enter a search string."));
00150 return;
00151 }
00152
00153 QApplication::setOverrideCursor(QCursor(Qt::BusyCursor));
00154
00155 KgpgInterface *interface = new KgpgInterface();
00156 connect(interface, SIGNAL(downloadKeysFinished(QList<int>, QStringList, bool, QString, KgpgInterface*)), this, SLOT(slotDownloadKeysFinished(QList<int>, QStringList, bool, QString, KgpgInterface*)));
00157 connect(interface, SIGNAL(downloadKeysAborted(KgpgInterface*)), this, SLOT(slotAbort(KgpgInterface*)));
00158
00159 m_importpop = new ConnectionDialog(this);
00160 connect(m_importpop, SIGNAL(cancelClicked()), interface, SLOT(downloadKeysAbort()));
00161
00162 interface->downloadKeys(page->kLEimportid->text().simplified().split(' '), page->kCBimportks->currentText(), false, page->kLEproxyI->text());
00163 }
00164
00165 void KeyServer::slotDownloadKeysFinished(QList<int> result, QStringList keys, bool imported, QString log, KgpgInterface *interface)
00166 {
00167 delete m_importpop;
00168 m_importpop = 0;
00169 interface->deleteLater();
00170
00171 QApplication::restoreOverrideCursor();
00172
00173 QString resultmessage;
00174 if (imported)
00175 {
00176 if (result[0] != 0) resultmessage += i18np("<qt>%1 key processed.<br/></qt>", "<qt>%1 keys processed.<br/></qt>", result[0]);
00177 if (result[4] != 0) resultmessage += i18np("<qt>%1 key unchanged.<br/></qt>", "<qt>%1 keys unchanged.<br/></qt>", result[4]);
00178 if (result[7] != 0) resultmessage += i18np("<qt>%1 signature imported.<br/></qt>", "<qt>%1 signatures imported.<br/></qt>", result[7]);
00179 if (result[1] != 0) resultmessage += i18np("<qt>%1 key without ID.<br/></qt>", "<qt>%1 keys without ID.<br/></qt>", result[1]);
00180 if (result[3] != 0) resultmessage += i18np("<qt>%1 RSA key imported.<br/></qt>", "<qt>%1 RSA keys imported.<br/></qt>", result[3]);
00181 if (result[5] != 0) resultmessage += i18np("<qt>%1 user ID imported.<br/></qt>", "<qt>%1 user IDs imported.<br/></qt>", result[5]);
00182 if (result[6] != 0) resultmessage += i18np("<qt>%1 subkey imported.<br/></qt>", "<qt>%1 subkeys imported.<br/></qt>", result[6]);
00183 if (result[8] != 0) resultmessage += i18np("<qt>%1 revocation certificate imported.<br/></qt>", "<qt>%1 revocation certificates imported.<br/></qt>", result[8]);
00184 if (result[9] != 0) resultmessage += i18np("<qt>%1 secret key processed.<br/></qt>", "<qt>%1 secret keys processed.<br/></qt>", result[9]);
00185 if (result[10] != 0) resultmessage += i18np("<qt><b>%1 secret key imported.</b><br/></qt>", "<qt><b>%1 secret keys imported.</b><br/></qt>", result[10]);
00186 if (result[11] != 0) resultmessage += i18np("<qt>%1 secret key unchanged.<br/></qt>", "<qt>%1 secret keys unchanged.<br/></qt>", result[11]);
00187 if (result[12] != 0) resultmessage += i18np("<qt>%1 secret key not imported.<br/></qt>", "<qt>%1 secret keys not imported.<br/></qt>", result[12]);
00188 if (result[2] != 0) resultmessage += i18np("<qt><b>%1 key imported:</b><br/></qt>", "<qt><b>%1 keys imported:</b><br/></qt>", result[2]);
00189 }
00190 else
00191 resultmessage = i18n("No key imported... \nCheck detailed log for more infos");
00192
00193 if (!keys.empty())
00194 emit importFinished(keys);
00195
00196 (void) new KgpgDetailedInfo(0, resultmessage, log, keys);
00197 }
00198
00199 void KeyServer::slotAbort(KgpgInterface *interface)
00200 {
00201 delete interface;
00202 QApplication::restoreOverrideCursor();
00203 if (m_autoclose)
00204 close();
00205 }
00206
00207 void KeyServer::slotExport(const QString &keyId)
00208 {
00209 if (page->kCBexportks->currentText().isEmpty())
00210 return;
00211
00212 QApplication::setOverrideCursor(QCursor(Qt::BusyCursor));
00213
00214 KgpgInterface *interface = new KgpgInterface();
00215 connect(interface, SIGNAL(uploadKeysFinished(QString, KgpgInterface*)), this, SLOT(slotUploadKeysFinished(QString, KgpgInterface*)));
00216 connect(interface, SIGNAL(uploadKeysAborted(KgpgInterface*)), this, SLOT(slotAbort(KgpgInterface*)));
00217
00218 m_importpop = new ConnectionDialog(this);
00219 connect(m_importpop, SIGNAL(cancelClicked()), interface, SLOT(uploadKeysAbort()));
00220
00221 interface->uploadKeys(keyId.simplified().split(' '), page->kCBimportks->currentText(), expattr, page->kLEproxyI->text());
00222 }
00223
00224 void KeyServer::slotUploadKeysFinished(QString message, KgpgInterface *interface)
00225 {
00226 delete m_importpop;
00227 m_importpop = 0;
00228 interface->deleteLater();
00229
00230 QApplication::restoreOverrideCursor();
00231
00232 if (message.isEmpty())
00233 message = i18n("Upload to keyserver finished without errors");
00234 KMessageBox::information(this, message);
00235 }
00236
00237 void KeyServer::slotSearch()
00238 {
00239 if (page->kCBimportks->currentText().isEmpty())
00240 return;
00241
00242 if (page->kLEimportid->text().isEmpty())
00243 {
00244 KMessageBox::sorry(this, i18n("You must enter a search string."));
00245 return;
00246 }
00247
00248 page->Buttonsearch->setEnabled(false);
00249 if (m_searchproc)
00250 return;
00251
00252
00253
00254 m_dialogserver = new KDialog(this );
00255 m_dialogserver->setCaption( i18n("Import Key From Keyserver") );
00256 m_dialogserver->setButtons( KDialog::Ok | KDialog::Close );
00257 m_dialogserver->setDefaultButton( KDialog::Ok);
00258 m_dialogserver->setModal( true );
00259
00260 m_dialogserver->setButtonText(KDialog::Ok, i18n("&Import"));
00261 m_dialogserver->enableButtonOk(false);
00262 m_listpop = new searchRes(0);
00263
00264
00265 m_listpop->statusText->setText(i18n("Connecting to the server..."));
00266
00267 connect(m_listpop->kLVsearch, SIGNAL(itemSelectionChanged()), this, SLOT(transferKeyID()));
00268 connect(m_dialogserver, SIGNAL(okClicked()), this, SLOT(slotPreImport()));
00269 connect(m_listpop->kLVsearch, SIGNAL(itemActivated(QTreeWidgetItem *, int)), m_dialogserver, SIGNAL(okClicked()));
00270 connect(m_dialogserver, SIGNAL(closeClicked()), this, SLOT(handleQuit()));
00271 connect(m_listpop, SIGNAL(destroyed()), this, SLOT(slotAbortSearch()));
00272
00273 m_listpop->kLVsearch->setSelectionMode(QAbstractItemView::ExtendedSelection);
00274
00275 m_count = 0;
00276 m_keyid.clear();
00277 m_readmessage.clear();
00278 m_kitem = NULL;
00279
00280 QString keyserv = page->kCBimportks->currentText();
00281
00282 bool useproxy = page->cBproxyI->isChecked();
00283 QString proxy = page->kLEproxyI->text();
00284
00285 m_searchproc = new GPGProc(this);
00286
00287 if (useproxy) {
00288 m_searchproc->setEnvironment(QStringList("http_proxy=" + proxy));
00289 *m_searchproc << "--keyserver-options" << "honor-http-proxy";
00290 } else
00291 *m_searchproc << "--keyserver-options" << "no-honor-http-proxy";
00292 *m_searchproc << "--keyserver" << keyserv << "--status-fd=1" << "--command-fd=0";
00293 *m_searchproc << "--with-colons"<< "--search-keys" << page->kLEimportid->text().simplified().toLocal8Bit();
00294
00295 m_keynumbers = 0;
00296 connect(m_searchproc, SIGNAL(processExited(GPGProc *)), this, SLOT(slotSearchResult(GPGProc *)));
00297 connect(m_searchproc, SIGNAL(readReady(GPGProc *)), this, SLOT(slotSearchRead(GPGProc *)));
00298 m_searchproc->start();
00299
00300 QApplication::setOverrideCursor(QCursor(Qt::BusyCursor));
00301 m_dialogserver->setMainWidget(m_listpop);
00302 m_listpop->setMinimumSize(m_listpop->sizeHint());
00303 m_dialogserver->exec();
00304 }
00305
00306 void KeyServer::slotAbortSearch()
00307 {
00308 if (m_searchproc != NULL) {
00309 if (m_searchproc->state() == QProcess::Running) {
00310 QApplication::restoreOverrideCursor();
00311 disconnect(m_searchproc, 0, 0, 0);
00312 m_searchproc->kill();
00313 }
00314 delete m_searchproc;
00315 m_searchproc = NULL;
00316 }
00317 page->Buttonsearch->setEnabled(true);
00318
00319 if (m_dialogserver)
00320 {
00321 delete m_dialogserver;
00322 m_dialogserver = 0L;
00323 }
00324 }
00325
00326 void KeyServer::slotSearchRead(GPGProc *p)
00327 {
00328 QString required;
00329
00330 while (p->readln(required, true) >= 0) {
00331 if (required.contains("keysearch.prompt")) {
00332 if (m_count < 4)
00333 p->write("N\n");
00334 else
00335 p->write("Q\n");
00336 } else if (required.contains("GOT_IT")) {
00337 m_count++;
00338 required.clear();
00339 } else if (required.startsWith("pub")) {
00340 if (m_keyid.length() > 0)
00341 CreateUidEntry();
00342 m_keyid = required;
00343 m_kitem = NULL;
00344 } else if (required.startsWith("uid")) {
00345 QString kid = required.section(':', 1, 1);
00346
00347 if (m_kitem != NULL) {
00348 QTreeWidgetItem *k = new QTreeWidgetItem(m_kitem);
00349 k->setText(0, kid);
00350 } else {
00351 m_kitem = new QTreeWidgetItem(m_listpop->kLVsearch);
00352 m_kitem->setText(0, kid);
00353 m_keynumbers++;
00354 }
00355 m_count = 0;
00356 }
00357 }
00358 }
00359
00360 void KeyServer::slotSearchResult(GPGProc *p)
00361 {
00362
00363 if (m_kitem != NULL)
00364 CreateUidEntry();
00365
00366 m_searchproc->deleteLater();
00367 m_searchproc = NULL;
00368 page->Buttonsearch->setEnabled(true);
00369 QString nb;
00370 m_dialogserver->enableButtonOk(true);
00371 QApplication::restoreOverrideCursor();
00372 nb = nb.setNum(m_keynumbers);
00373
00374 m_listpop->statusText->setText(i18n("Found %1 matching keys", nb));
00375
00376 if (m_listpop->kLVsearch->topLevelItemCount() > 0)
00377 {
00378 m_listpop->kLVsearch->setCurrentItem(m_listpop->kLVsearch->topLevelItem(0));
00379 transferKeyID();
00380 }
00381 }
00382
00383 void KeyServer::slotSetText(const QString &text)
00384 {
00385 page->kLEimportid->setText(text);
00386 }
00387
00388 void KeyServer::slotTextChanged(const QString &text)
00389 {
00390 page->Buttonimport->setEnabled(!text.isEmpty());
00391 page->Buttonsearch->setEnabled(!text.isEmpty() && (m_searchproc == NULL));
00392 }
00393
00394 void KeyServer::slotSetExportAttribute(const QString *state)
00395 {
00396 if (state != 0)
00397 expattr = QString(*state);
00398 else
00399 expattr.clear();
00400 }
00401
00402 void KeyServer::slotEnableProxyI(const bool &on)
00403 {
00404 page->kLEproxyI->setEnabled(on);
00405 }
00406
00407 void KeyServer::slotEnableProxyE(const bool &on)
00408 {
00409 page->kLEproxyE->setEnabled(on);
00410 }
00411
00412 void KeyServer::transferKeyID()
00413 {
00414 if (m_listpop->kLVsearch->topLevelItemCount() == 0)
00415 return;
00416
00417 QStringList keysToSearch;
00418 m_listpop->kLEID->clear();
00419 const QList<QTreeWidgetItem*> &searchList = m_listpop->kLVsearch->selectedItems();
00420
00421 foreach (QTreeWidgetItem *searchItem, searchList)
00422 {
00423 if (searchItem)
00424 {
00425 QTreeWidgetItem *item = searchItem->parent();
00426
00427 if (item == NULL)
00428 item = searchItem;
00429
00430 QString id = item->data(0, Qt::UserRole).toString();
00431 if (!keysToSearch.contains(id))
00432 keysToSearch << id;
00433 }
00434 }
00435
00436
00437 m_listpop->kLEID->setText(keysToSearch.join(" "));
00438 }
00439
00440 void KeyServer::slotPreImport()
00441 {
00442 transferKeyID();
00443 if (m_listpop->kLEID->text().isEmpty())
00444 {
00445 KMessageBox::sorry(this, i18n("You must choose a key."));
00446 return;
00447 }
00448 page->kLEimportid->setText(m_listpop->kLEID->text());
00449 m_dialogserver->close();
00450 slotImport();
00451 }
00452
00453 void KeyServer::slotPreExport()
00454 {
00455 slotExport(page->kCBexportkey->currentText().section(':', 0, 0));
00456 }
00457
00458 void KeyServer::slotOk()
00459 {
00460 accept();
00461 }
00462
00463 QStringList KeyServer::getServerList()
00464 {
00465 KConfig config("kgpgrc", KConfig::SimpleConfig);
00466 KConfigGroup group = config.group("Servers");
00467
00468 QStringList serverlist;
00469 serverlist << KgpgInterface::getGpgSetting("keyserver", KGpgSettings::gpgConfigPath());
00470 serverlist << group.readEntry("Server_List").split(',', QString::SkipEmptyParts);
00471
00472 return serverlist;
00473 }
00474
00475 void KeyServer::handleQuit()
00476 {
00477 if (m_searchproc != NULL) {
00478 if (m_searchproc->state() == QProcess::Running) {
00479 QApplication::restoreOverrideCursor();
00480 disconnect(m_searchproc, 0, 0, 0);
00481 m_searchproc->kill();
00482 }
00483 delete m_searchproc;
00484 m_searchproc = NULL;
00485 }
00486 m_dialogserver->close();
00487 page->Buttonsearch->setEnabled(true);
00488 }
00489
00490 void KeyServer::slotSetKeyserver(const QString &server)
00491 {
00492 page->kCBimportks->setCurrentIndex(page->kCBimportks->findText(server));
00493 }
00494
00495 void KeyServer::CreateUidEntry(void)
00496 {
00497 Q_ASSERT(m_keyid.section(':', 1, 1).length() > 0);
00498
00499 QString id = m_keyid.section(':', 1, 1).right(16);
00500 KDateTime kd;
00501 kd.setTime_t(m_keyid.section(':', 4, 4).toULongLong());
00502
00503 QTreeWidgetItem *k = new QTreeWidgetItem(m_kitem);
00504 if (m_keyid.section(':', 6, 6) == "r")
00505 {
00506 k->setText(0, i18n("ID %1, %2 bit %3 key, created %4 revoked", id, m_keyid.section(':', 3, 3),
00507 Convert::toString(Convert::toAlgo(m_keyid.section(':', 2, 2))),
00508 kd.toString(KDateTime::LocalDate)));
00509 }
00510 else
00511 {
00512 k->setText(0, i18n("ID %1, %2 bit %3 key, created %4", id, m_keyid.section(':', 3, 3),
00513 Convert::toString(Convert::toAlgo(m_keyid.section(':', 2, 2))),
00514 kd.toString(KDateTime::LocalDate)));
00515 }
00516 m_kitem->setData(0, Qt::UserRole, id);
00517 }
00518
00519 #include "keyservers.moc"