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