diff --git a/lib/db_base.cpp b/lib/db_base.cpp index a5e36d4e..1f98857b 100644 --- a/lib/db_base.cpp +++ b/lib/db_base.cpp @@ -585,19 +585,18 @@ bool db_base::setData(const QModelIndex &index, const QVariant &value, int role) void db_base::load_default(load_base &load) { + QString s; QStringList slist = QFileDialog::getOpenFileNames(mainwin, load.caption, mainwin->getPath(), load.filter); if (!slist.count()) return; - QString fn = QDir::convertSeparators(slist[0]); - mainwin->setPath(fn.mid(0, fn.lastIndexOf(QRegExp("[/\\\\]")) )); + QString fn = slist[0]; + mainwin->setPath(fn.mid(0, fn.lastIndexOf("/"))); ImportMulti *dlgi = new ImportMulti(mainwin); - for (QStringList::Iterator it = slist.begin(); it != slist.end(); ++it) { - QString s = *it; - s = QDir::convertSeparators(s); + foreach(s, slist) { pki_base *item = NULL; try { item = load.loadItem(s); diff --git a/lib/func.cpp b/lib/func.cpp index 5c482793..e72a070b 100644 --- a/lib/func.cpp +++ b/lib/func.cpp @@ -54,6 +54,19 @@ QString getDefaultPkcs11Lib() #endif } +QStringList getLibExtensions() +{ + QStringList l; +#if defined(_WIN32) || defined(USE_CYGWIN) + l << QString("*.dll") << QString("*.DLL"); +#elif defined(Q_WS_MAC) + l << QString("*.dylib") << QString("*.so"); +#else + l << QString("*.so"); +#endif + return l; +} + /* returns e.g. /usr/local/share/xca for unix systems * or HKEY_LOCAL_MACHINE->Software->xca for WIN32 * (e.g. c:\Program Files\xca ) @@ -209,28 +222,21 @@ QString filename2QString(const char *fname) #endif } -QString compressFilename(QString filename) +QString compressFilename(QString filename, int maxlen) { - /* quick and dirty demo for compacting filename */ - /* there are i compactable path components, but keep the filename */ - int i = filename.count(QDir::separator()) - 1; + if (filename.length() < maxlen) + return filename; - /* we want to keep the first component, - * so don't count the starting slash */ - if(filename.startsWith(QDir::separator())) - i--; + int len, lastslash = filename.lastIndexOf("/"); + QString base = filename.mid(lastslash); + len = base.length(); + len = maxlen - len -3; + if (len < 0) + return QString("...") + base.right(maxlen -3); + filename = filename.left(len); + lastslash = filename.lastIndexOf("/"); -#define MAX_DISPLAY_LEN 50 - // start most-right - int from, to = filename.lastIndexOf(QDir::separator()); - - for (; i > 0 && filename.length() > MAX_DISPLAY_LEN; i--) { - from = filename.lastIndexOf(QDir::separator(), to - 1); - filename.replace(from + 1 , to-from - 1, "..."); - to = from; - } - - return filename; + return filename.left(lastslash+1) + "..." + base; } diff --git a/lib/func.h b/lib/func.h index 7a3a3b41..03ff7465 100644 --- a/lib/func.h +++ b/lib/func.h @@ -23,10 +23,11 @@ QString getDocDir(); QString getUserSettingsDir(); QString getDefaultPkcs11Lib(); QString getFullFilename(const QString &filename, const QString &selectedFilter); +QStringList getLibExtensions(); QByteArray filename2bytearray(const QString &fname); QString filename2QString(const char *fname); -QString compressFilename(QString filename); +QString compressFilename(QString filename, int maxlen = 50); QString asn1ToQString(const ASN1_STRING *str, bool quote = false); ASN1_STRING *QStringToAsn1(QString s, int nid); diff --git a/lib/pki_base.cpp b/lib/pki_base.cpp index b1bc5243..1b642fb8 100644 --- a/lib/pki_base.cpp +++ b/lib/pki_base.cpp @@ -105,13 +105,7 @@ QString pki_base::rmslashdot(const QString &s) { QByteArray a = s.toAscii(); int r = a.lastIndexOf('.'); -#ifdef WIN32 - int l = a.lastIndexOf('\\'); -#else int l = a.lastIndexOf('/'); -#endif - //printf("r=%d, l=%d, s='%s', mid='%s'\n",r,l,(const char*)a, - // CCHAR(s.mid(l+1,r-l-1))); return s.mid(l+1,r-l-1); } diff --git a/ui/Makefile b/ui/Makefile index c54af197..d876f2bb 100644 --- a/ui/Makefile +++ b/ui/Makefile @@ -8,7 +8,7 @@ UI_H = ui_About.h ui_CaProperties.h ui_CertDetail.h ui_CertExtend.h \ ui_CrlDetail.h ui_ExportDialog.h ui_ExportKey.h ui_Help.h \ ui_ImportMulti.h ui_KeyDetail.h ui_MainWindow.h ui_NewCrl.h \ ui_NewKey.h ui_NewX509.h ui_Options.h ui_PwDialog.h ui_Revoke.h \ - ui_SelectToken.h ui_TrustState.h ui_v3ext.h + ui_SelectToken.h ui_TrustState.h ui_v3ext.h ui_SearchPkcs11.h include $(TOPDIR)/Rules.mak diff --git a/ui/Options.ui b/ui/Options.ui index ed290ceb..c1ba9140 100644 --- a/ui/Options.ui +++ b/ui/Options.ui @@ -7,7 +7,7 @@ 0 0 494 - 495 + 529 @@ -172,6 +172,13 @@ + + + + Search + + + @@ -179,8 +186,8 @@ - 20 - 40 + 77 + 17 diff --git a/ui/SearchPkcs11.ui b/ui/SearchPkcs11.ui new file mode 100644 index 00000000..e12416af --- /dev/null +++ b/ui/SearchPkcs11.ui @@ -0,0 +1,152 @@ + + + SearchPkcs11 + + + + 0 + 0 + 480 + 378 + + + + Dialog + + + + + + + 0 + 0 + + + + QFrame::Box + + + QFrame::Sunken + + + + + + + 0 + 0 + + + + Directory + + + + + + + + + + + 0 + 0 + + + + ... + + + + + + + include sub directorys + + + + + + + Search + + + + + + + + + + + + + Qt::PlainText + + + false + + + + + + + QAbstractItemView::NoEditTriggers + + + false + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok|QDialogButtonBox::Open + + + + + + + + + buttonBox + clicked(QAbstractButton*) + SearchPkcs11 + buttonPress(QAbstractButton*) + + + 229 + 362 + + + 368 + 104 + + + + + liblist + itemDoubleClicked(QListWidgetItem*) + SearchPkcs11 + loadItem(QListWidgetItem*) + + + 339 + 279 + + + 368 + 225 + + + + + + buttonPress(QAbstractButton*) + loadItem(QListWidgetItem*) + + diff --git a/widgets/Makefile b/widgets/Makefile index 618740c3..a8a18ce1 100644 --- a/widgets/Makefile +++ b/widgets/Makefile @@ -6,7 +6,8 @@ endif MOC_NAMES=MainWindow KeyDetail clicklabel XcaTreeView ExportKey NewX509 \ validity v3ext distname CertDetail CertExtend PwDialog \ - ImportMulti CrlDetail ExportDialog hashBox Options NewKey kvView NewCrl + ImportMulti CrlDetail ExportDialog hashBox Options NewKey kvView \ + NewCrl SearchPkcs11 NAMES=$(MOC_NAMES) NewX509_ext MW_menu MW_help MW_database OBJS=$(patsubst %,moc_%.o,$(MOC_NAMES)) $(patsubst %,%.o,$(NAMES)) diff --git a/widgets/Options.cpp b/widgets/Options.cpp index 2f0f9b0e..1b1eb86e 100644 --- a/widgets/Options.cpp +++ b/widgets/Options.cpp @@ -7,9 +7,11 @@ #include "lib/func.h" #include "Options.h" +#include "SearchPkcs11.h" #include "lib/pki_scard.h" #include #include +#include Options::Options(MainWindow *parent) :QDialog(parent) @@ -40,6 +42,13 @@ Options::Options(MainWindow *parent) << tr("UTF8 strings only (RFC2459)") << tr("All strings"); mbstring->addItems(s); + searchP11 = NULL; +} + +Options::~Options() +{ + if (searchP11) + delete searchP11; } void Options::on_extDNadd_clicked() @@ -78,12 +87,21 @@ QString Options::getStringOpt() void Options::on_addButton_clicked(void) { load_pkcs11 l; - pkcs11_lib *lib; - QString fname, status; + QString fname; fname = QFileDialog::getOpenFileName(this, l.caption, getLibDir(), l.filter); + addLib(fname); +} + +void Options::addLib(QString fname) +{ + pkcs11_lib *lib; + QString status; + + fname = QFileInfo(fname).canonicalFilePath(); + if (fname.isEmpty() || pkcs11::get_lib(fname)) return; try { @@ -94,11 +112,15 @@ void Options::on_addButton_clicked(void) lib = NULL; status = ex.getString(); } + status = status.trimmed(); QListWidgetItem *item = new QListWidgetItem(fname); item->setToolTip(status); if (lib) item->setIcon(*MainWindow::doneIco); pkcs11List->addItem(item); + if (searchP11) + QToolTip::showText(searchP11->mapToGlobal( + QPoint(0,0)), status); } void Options::on_removeButton_clicked(void) @@ -113,6 +135,16 @@ void Options::on_removeButton_clicked(void) } } +void Options::on_searchPkcs11_clicked(void) +{ + if (!searchP11) { + searchP11 = new SearchPkcs11(this, QString()); + connect(searchP11, SIGNAL(addLib(QString)), + this, SLOT(addLib(QString))); + } + searchP11->show(); +} + void Options::setupPkcs11Provider(QString list) { pkcs11_lib_list libs = pkcs11::get_libs(); diff --git a/widgets/Options.h b/widgets/Options.h index d695a624..cdd7b395 100644 --- a/widgets/Options.h +++ b/widgets/Options.h @@ -11,16 +11,19 @@ #include "ui_Options.h" #include #include "lib/base.h" -#include "widgets/MainWindow.h" +#include "SearchPkcs11.h" +#include "MainWindow.h" class Options: public QDialog, public Ui::Options { Q_OBJECT private: + SearchPkcs11 *searchP11; QStringList string_opts; MainWindow *mw; public: Options(MainWindow *parent); + ~Options(); void setupPkcs11Provider(QString list); void setStringOpt(const QString string_opt); QString getDnString(); @@ -32,6 +35,8 @@ class Options: public QDialog, public Ui::Options void on_extDNdel_clicked(); void on_addButton_clicked(void); void on_removeButton_clicked(void); + void on_searchPkcs11_clicked(void); + void addLib(QString); }; #endif diff --git a/widgets/SearchPkcs11.cpp b/widgets/SearchPkcs11.cpp new file mode 100644 index 00000000..58d1f616 --- /dev/null +++ b/widgets/SearchPkcs11.cpp @@ -0,0 +1,192 @@ +/* vi: set sw=4 ts=4: + * + * Copyright (C) 2010 Christian Hohnstaedt. + * + * All rights reserved. + */ + + +#include "SearchPkcs11.h" +#include "lib/base.h" +#include "lib/func.h" +#include "lib/pkcs11_lib.h" + +#include +#include +#include +#include +#include +#include +#include + +SearchPkcs11::SearchPkcs11(QWidget *parent, QString fname) + :QDialog(parent) +{ + setupUi(this); + filename->setText(fname); + setWindowTitle(XCA_TITLE); + + filename->setText(getLibDir()); + searching = NULL; +} + +SearchPkcs11::~SearchPkcs11() +{ + if (searching) + search->click(); +} + +void SearchPkcs11::on_fileBut_clicked() +{ + QString s = QFileDialog::getExistingDirectory(this, QString(XCA_TITLE), + filename->text()); + + if (!s.isEmpty()) { + QDir::convertSeparators(s); + filename->setText(s); + } +} + +void SearchPkcs11::on_search_clicked() +{ + if (searching) { + return; + } + searching = new searchThread(filename->text(), + getLibExtensions(), + subdirs->isChecked()); + + liblist->clear(); + connect(searching, SIGNAL(updateLibs(QString)), + this, SLOT(updateLibs(QString))); + connect(searching, SIGNAL(updateCurrFile(QString)), + this, SLOT(updateCurrFile(QString))); + connect(searching, SIGNAL(finished()), + this, SLOT(finishSearch())); + + connect(search, SIGNAL(clicked()), + searching, SLOT(cancelSearch())); + + search->setText("Cancel"); + searching->start(); +} + +void SearchPkcs11::finishSearch() +{ + search->setText("Start"); + currFile->setText(tr("The following files are possible PKCS#11 libraries")); + if (!searching) + return; + searching->wait(1000); + delete searching; + searching = NULL; +} + +void SearchPkcs11::buttonPress(QAbstractButton *but) +{ + QList libitems; + QListWidgetItem *lib; + + switch (buttonBox->standardButton(but)) { + case QDialogButtonBox::Ok: + accept(); + break; + default: + case QDialogButtonBox::Cancel: + reject(); + break; + case QDialogButtonBox::Open: + libitems = liblist->selectedItems(); + foreach(lib, libitems) + loadItem(lib); + break; + } +} + +void SearchPkcs11::loadItem(QListWidgetItem *lib) +{ + emit addLib(lib->text()); + delete lib; +} + +void SearchPkcs11::updateCurrFile(QString f) +{ + int len = f.length(); + QString reduced = f; + QFontMetrics fm(currFile->font()); + + currFile->setToolTip(f); + while ((currFile->width() < (fm.width(reduced) -10)) && (len > 0)) { + len -= 10; + reduced = compressFilename(f, len); + } + currFile->setText(reduced); + currFile->update(); +} + +void SearchPkcs11::updateLibs(QString f) +{ + liblist->addItem(new QListWidgetItem(f)); + liblist->update(); +} + +searchThread::searchThread(QString _dir, QStringList _ext, bool _recursive) +{ + dirname = _dir; + ext = _ext; + recursive = _recursive; + keepOnRunning = true; +} + +void searchThread::cancelSearch() +{ + keepOnRunning = false; +} + +bool searchThread::checkLib(QString file) +{ + qint64 siz; + int r = -1; + + QFile qf(file); + siz = qf.size(); + if (qf.open(QIODevice::ReadOnly)) { + uchar *p = qf.map(0, siz); + r = QByteArray::fromRawData((char*)p, siz) + .indexOf("C_GetFunctionList"); + qf.unmap(p); + qf.close(); + } + return r != -1; +} + +void searchThread::search(QString mydir) +{ + QDir dir = QDir(mydir); + QStringList files = dir.entryList( + QStringList(ext), + QDir::Files | QDir::Readable); + + while (!files.isEmpty() && keepOnRunning) { + QString file = files.takeFirst(); + if (file.isEmpty()) + continue; + file = mydir + QDir::separator() + file; + emit updateCurrFile(file); + if (checkLib(file)) + emit updateLibs(file); + } + if (recursive && keepOnRunning) { + QString d; + QStringList dirs = dir.entryList(QStringList(), + QDir::AllDirs | QDir::NoDotAndDotDot); + + foreach(d, dirs) { + if (!keepOnRunning) + break; + QString s = mydir +QDir::separator() +d; + emit updateCurrFile(s); + search(s); + } + } +} diff --git a/widgets/SearchPkcs11.h b/widgets/SearchPkcs11.h new file mode 100644 index 00000000..2a75ebd0 --- /dev/null +++ b/widgets/SearchPkcs11.h @@ -0,0 +1,68 @@ +/* vi: set sw=4 ts=4: + * + * Copyright (C) 2010 Christian Hohnstaedt. + * + * All rights reserved. + */ + +#ifndef __SEARCHPKCS11DIALOG_H +#define __SEARCHPKCS11DIALOG_H + +#include +#include "ui_SearchPkcs11.h" + +class SearchPkcs11; +class searchThread: public QThread +{ + Q_OBJECT + + protected: + QString dirname; + QStringList ext; + bool recursive; + bool keepOnRunning; + + bool checkLib(QString file); + + public: + searchThread(QString _dir, QStringList _ext, bool _recursive); + void search(QString mydir); + void run() + { + search(dirname); + } + + public slots: + void cancelSearch(); + + signals: + void updateCurrFile(QString f); + void updateLibs(QString f); +}; + +class SearchPkcs11: public QDialog, public Ui::SearchPkcs11 +{ + Q_OBJECT + + protected: + void searchDir(QString dirname, bool subdirs); + searchThread *searching; + + public: + SearchPkcs11(QWidget *parent, QString fname); + ~SearchPkcs11(); + + public slots: + void on_search_clicked(); + void on_fileBut_clicked(); + void buttonPress(QAbstractButton *but); + void loadItem(QListWidgetItem *lib); + void updateLibs(QString f); + void updateCurrFile(QString f); + void finishSearch(); + + signals: + void addLib(QString); +}; + +#endif