2008-07-24 Marcus Brinkmann <marcus@g10code.de>
authorMarcus Brinkmann <mb@g10code.com>
Thu, 24 Jul 2008 14:49:21 +0000 (14:49 +0000)
committerMarcus Brinkmann <mb@g10code.com>
Thu, 24 Jul 2008 14:49:21 +0000 (14:49 +0000)
* qt4/pinentrydialog.h, qt4/pinentrydialog.cpp, qt4/main.cpp,
qt4/Makefile.am: New files.
* configure.ac: Add check for Qt4.
(AC_CONFIG_FILES): Add qt4/Makefile.am.
* Makefile.am (pinentry_qt4): New variable.
(SUBDIRS): Add ${pinentry_qt4}.

ChangeLog
Makefile.am
NEWS
configure.ac
qt4/Makefile.am [new file with mode: 0644]
qt4/main.cpp [new file with mode: 0644]
qt4/pinentrydialog.cpp [new file with mode: 0644]
qt4/pinentrydialog.h [new file with mode: 0644]

index 18047d1..3699d7d 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2008-07-24  Marcus Brinkmann  <marcus@g10code.de>
+
+       * qt4/pinentrydialog.h, qt4/pinentrydialog.cpp, qt4/main.cpp,
+       qt4/Makefile.am: New files.
+       * configure.ac: Add check for Qt4.
+       (AC_CONFIG_FILES): Add qt4/Makefile.am.
+       * Makefile.am (pinentry_qt4): New variable.
+       (SUBDIRS): Add ${pinentry_qt4}.
+
 2008-07-23  Werner Koch  <wk@g10code.com>
 
        * secmem/secmem.c (secmem_init): Fix apostrophe in error
index 49ae451..dab6a16 100644 (file)
@@ -47,6 +47,12 @@ else
 pinentry_qt = 
 endif
 
+if BUILD_PINENTRY_QT4
+pinentry_qt4 = qt4
+else
+pinentry_qt4 = 
+endif
+
 if BUILD_PINENTRY_W32
 pinentry_w32 = w32
 else
@@ -54,7 +60,8 @@ pinentry_w32 =
 endif
 
 SUBDIRS = assuan secmem pinentry ${pinentry_curses} \
-       ${pinentry_gtk} ${pinentry_gtk_2} ${pinentry_qt} ${pinentry_w32} doc
+       ${pinentry_gtk} ${pinentry_gtk_2} ${pinentry_qt} ${pinentry_qt4} \
+       ${pinentry_w32} doc
 
 
 install-exec-local:
diff --git a/NEWS b/NEWS
index 9ddf46d..2e1ad68 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,8 @@ Noteworthy changes in version 0.7.6
 
  * Make Gtk+-2 pinentry transient to the root window.
 
+ * Add Qt4 pinentry.
+
 Noteworthy changes in version 0.7.5 (2008-02-15)
 ------------------------------------------------
 
index de4fe67..c2b270c 100644 (file)
@@ -46,7 +46,7 @@ AC_PROG_CC
 AC_PROG_CPP
 AC_PROG_INSTALL
 AC_PROG_RANLIB
-# We need to check for cplusplus here becuase we may not do the test
+# We need to check for cplusplus here because we may not do the test
 # for Qt and autoconf does does not allow that.
 AC_PROG_CXX
 AC_PROG_LN_S
@@ -355,6 +355,56 @@ dnl dnl End of checks for Qt pinentry.
 dnl fi
 
 
+dnl
+dnl Check for Qt4 pinentry program.
+dnl
+AC_ARG_ENABLE(pinentry-qt4,
+            AC_HELP_STRING([--enable-pinentry-qt4], [build Qt4 pinentry]),
+            pinentry_qt4=$enableval, pinentry_qt4=maybe)
+
+
+dnl
+dnl Checks for Qt4 libraries.  Deal correctly with $pinentry_qt4 = maybe.
+dnl
+if test "$pinentry_qt4" != "no"; then
+PKG_CHECK_MODULES(QT4_CORE, QtCore,,
+if test "$pinentry_qt4" = "yes"; then
+    AC_MSG_ERROR([[
+***
+*** Qt4 Core is required.
+***]])
+else
+    pinentry_qt4=no
+fi)
+fi
+
+if test "$pinentry_qt4" != "no"; then
+PKG_CHECK_MODULES(QT4_GUI, QtGui,,
+if test "$pinentry_qt4" = "yes"; then
+    AC_MSG_ERROR([[
+***
+*** Qt4 Gui is required.
+***]])
+else
+    pinentry_qt4=no
+fi)
+fi
+
+dnl If we have come so far, Qt4 pinentry can be build.
+if test "$pinentry_qt4" != "no"; then
+    pinentry_qt4=yes
+fi
+AM_CONDITIONAL(BUILD_PINENTRY_QT4, test "$pinentry_qt4" = "yes")
+if test "$pinentry_qt4" = "yes"; then
+  AC_DEFINE(PINENTRY_QT4, 1, [The Qt4 version of Pinentry is to be build])
+fi
+
+dnl if test "$pinentry_qt4" = "yes"; then
+dnl Additional checks for Qt4 pinentry.
+dnl End of additional checks for Qt4 pinentry.
+dnl fi
+
+
 #
 # Check whether we should build the W32 pinentry.  This is actually
 # the simplest check as we do this only for that platform.
@@ -399,6 +449,7 @@ curses/Makefile
 gtk/Makefile
 gtk+-2/Makefile
 qt/Makefile
+qt4/Makefile
 w32/Makefile
 doc/Makefile
 Makefile
@@ -413,6 +464,7 @@ AC_MSG_NOTICE([
        GTK+ Pinentry: $pinentry_gtk
        GTK+-2 Pinentry: $pinentry_gtk_2
        Qt Pinentry: $pinentry_qt
+       Qt4 Pinentry: $pinentry_qt4
         W32 Pinentry: $pinentry_w32
 
        Fallback to Curses: $fallback_curses
diff --git a/qt4/Makefile.am b/qt4/Makefile.am
new file mode 100644 (file)
index 0000000..1a772c5
--- /dev/null
@@ -0,0 +1,48 @@
+# Makefile.am
+# Copyright (C) 2002 g10 Code GmbH, Klarälvdalens Datakonsult AB
+# Copyright (C) 2008 g10 Code GmbH
+#
+# This file is part of PINENTRY.
+#
+# PINENTRY is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# PINENTRY is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+
+## Process this file with automake to produce Makefile.in
+
+bin_PROGRAMS = pinentry-qt4
+
+if FALLBACK_CURSES
+ncurses_include = $(NCURSES_INCLUDE)
+libcurses = ../pinentry/libpinentry-curses.a $(LIBCURSES) $(LIBICONV)
+else
+ncurses_include =
+libcurses =
+endif
+
+
+AM_CPPFLAGS = -I$(top_srcdir)/assuan -I$(top_srcdir)/secmem \
+       $(ncurses_include) -I$(top_srcdir)/pinentry
+AM_CXXFLAGS = $(QT4_CORE_CFLAGS) $(QT4_GUI_CFLAGS)
+pinentry_qt4_LDADD = $(QT4_CORE_LIBS) $(QT4_GUI_LIBS) $(libcurses) \
+       ../pinentry/libpinentry.a $(top_builddir)/assuan/libassuan.a \
+       $(top_builddir)/secmem/libsecmem.a $(LIBCAP)
+
+pinentry_qt4_SOURCES = pinentrydialog.h pinentrydialog.cpp \
+       main.cpp 
+nodist_pinentry_qt4_SOURCES = pinentrydialog.moc
+
+DISTCLEANFILES = $(nodist_pinentry_qt4_SOURCES)
+
+%.moc: $(srcdir)/%.h
+       $(MOC) $< -o $@
diff --git a/qt4/main.cpp b/qt4/main.cpp
new file mode 100644 (file)
index 0000000..3d298ec
--- /dev/null
@@ -0,0 +1,191 @@
+/* 
+   main.cpp - A (not yet) secure Qt 4 dialog for PIN entry.
+
+   Copyright (C) 2002 Klarälvdalens Datakonsult AB
+   Copyright (C) 2003 g10 Code GmbH
+   Copyright 2007 Ingo Klöcker
+
+   Written by Steffen Hansen <steffen@klaralvdalens-datakonsult.se>.
+   Modified by Marcus Brinkmann <marcus@g10code.de>.
+   
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+
+#include <stdlib.h>
+#include <errno.h>
+
+#include <qapplication.h>
+#include <QString>
+#include <qwidget.h>
+#include <qmessagebox.h>
+// #include "secqstring.h"
+
+#include "pinentrydialog.h"
+
+#include "pinentry.h"
+
+extern "C"
+{
+#include "memory.h"
+}
+
+#include <stdio.h>
+
+#ifdef FALLBACK_CURSES
+#include <pinentry-curses.h>
+#endif
+
+/* Hack for creating a QWidget with a "foreign" window ID */
+class ForeignWidget : public QWidget
+{
+public:
+  ForeignWidget( WId wid ) : QWidget( 0 )
+  {
+    QWidget::destroy();
+    create( wid, false, false );
+  }
+  ~ForeignWidget()
+  {
+    destroy( false, false );
+  }
+};
+
+static int
+qt_cmd_handler (pinentry_t pe)
+{
+  QWidget *parent = 0;
+
+  int want_pass = !!pe->pin;
+
+  if (want_pass)
+    {
+      /* FIXME: Add parent window ID to pinentry and GTK.  */
+      if (pe->parent_wid)
+       parent = new ForeignWidget (pe->parent_wid);
+
+      PinEntryDialog pinentry (parent, 0, true);
+
+      pinentry.setPrompt (QString::fromUtf8 (pe->prompt));
+      pinentry.setDescription (QString::fromUtf8 (pe->description));
+      /* If we reuse the same dialog window.  */
+#if 0
+      pinentry.setText (SecQString::null);
+#endif
+
+      if (pe->ok)
+       pinentry.setOkText (QString::fromUtf8 (pe->ok));
+      if (pe->cancel)
+       pinentry.setCancelText (QString::fromUtf8 (pe->cancel));
+      if (pe->error)
+       pinentry.setError (QString::fromUtf8 (pe->error));
+
+      bool ret = pinentry.exec ();
+      if (!ret)
+       return -1;
+
+      QByteArray pinUtf8 = pinentry.text().toUtf8();
+      char *pin = pinUtf8.data();
+      if (!pin)
+       return -1;
+
+      int len = strlen (pin);
+      if (len >= 0)
+       {
+         pinentry_setbufferlen (pe, len + 1);
+         if (pe->pin)
+           {
+             strcpy (pe->pin, pin);
+             // ::secmem_free (pin);
+             return len;
+           }
+       }
+      // ::secmem_free (pin);
+      return -1;
+    }
+  else
+    {
+      bool ret = QMessageBox::information (parent, "", pe->description,
+                                          pe->ok ? pe->ok : "OK",
+                                          pe->cancel ? pe->cancel : "Cancel");
+      return !ret;
+    }
+}
+
+pinentry_cmd_handler_t pinentry_cmd_handler = qt_cmd_handler;
+
+int 
+main (int argc, char *argv[])
+{
+  pinentry_init ("pinentry-qt4");
+
+#ifdef FALLBACK_CURSES
+  if (!pinentry_have_display (argc, argv))
+    pinentry_cmd_handler = curses_cmd_handler;
+  else
+#endif
+    {
+      /* Qt does only understand -display but not --display; thus we
+         are fixing that here.  The code is pretty simply and may get
+         confused if an argument is called "--display". */
+      char **new_argv, *p;
+      size_t n;
+      int i, done;
+
+      for (n=0,i=0; i < argc; i++)
+        n += strlen (argv[i])+1;
+      n++;
+      new_argv = (char**)calloc (argc+1, sizeof *new_argv);
+      if (new_argv)
+        *new_argv = (char*)malloc (n);
+      if (!new_argv || !*new_argv)
+        {
+          fprintf (stderr, "pinentry-qt4: can't fixup argument list: %s\n",
+                   strerror (errno));
+          exit (EXIT_FAILURE);
+          
+        }
+      for (done=0,p=*new_argv,i=0; i < argc; i++)
+        if (!done && !strcmp (argv[i], "--display"))
+          {
+            new_argv[i] = "-display";
+            done = 1;
+          }
+        else
+          {
+            new_argv[i] = strcpy (p, argv[i]);
+            p += strlen (argv[i]) + 1;
+          }
+
+      /* We use a modal dialog window, so we don't need the application
+         window anymore.  */
+      i = argc;
+      new QApplication (i, new_argv);
+    }
+  
+
+  /* Consumes all arguments.  */
+  if (pinentry_parse_opts (argc, argv))
+    {
+      printf ("pinentry-qt4 (pinentry) " /* VERSION */ "\n");
+      exit (EXIT_SUCCESS);
+    }
+
+  if (pinentry_loop ())
+    return 1;
+
+  return 0;
+}
diff --git a/qt4/pinentrydialog.cpp b/qt4/pinentrydialog.cpp
new file mode 100644 (file)
index 0000000..c1b6a17
--- /dev/null
@@ -0,0 +1,178 @@
+/* 
+   pinentrydialog.cpp - A (not yet) secure Qt 4 dialog for PIN entry.
+
+   Copyright (C) 2002 Klarälvdalens Datakonsult AB
+   Copyright 2007 Ingo Klöcker
+
+   Written by Steffen Hansen <steffen@klaralvdalens-datakonsult.se>.
+   
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#include <QVBoxLayout>
+#include <QHBoxLayout>
+#include <QPushButton>
+#include <QKeyEvent>
+#include <QLabel>
+#include <QMessageBox>
+
+#ifdef WITH_SECURE_QSTRING
+#include "secqlineedit.h"
+#else
+#include <QLineEdit>
+#endif
+
+#include "pinentrydialog.h"
+
+PinEntryDialog::PinEntryDialog( QWidget* parent, const char* name, bool modal )
+  : QDialog( parent ), _grabbed( false )
+{
+  if ( modal ) {
+    setWindowModality( Qt::ApplicationModal );
+  }
+
+  QBoxLayout* top = new QVBoxLayout( this );
+  top->setMargin( 6 );
+  QBoxLayout* upperLayout = new QHBoxLayout();
+  top->addLayout( upperLayout );
+
+  _icon = new QLabel( this );
+  _icon->setPixmap( QMessageBox::standardIcon( QMessageBox::Information ) );
+  upperLayout->addWidget( _icon );
+
+  QBoxLayout* labelLayout = new QVBoxLayout();
+  upperLayout->addLayout( labelLayout );
+
+  _error = new QLabel( this );
+  labelLayout->addWidget( _error );
+
+  _desc = new QLabel( this );
+  labelLayout->addWidget( _desc );
+
+  QBoxLayout* l = new QHBoxLayout();
+  top->addLayout( l );
+  _prompt = new QLabel( this );
+  l->addWidget( _prompt );
+  _edit = new SecQLineEdit( this );
+  _edit->setMaxLength( 256 );
+  _edit->setEchoMode( SecQLineEdit::Password );
+  l->addWidget( _edit );
+
+  l = new QHBoxLayout();
+  top->addLayout( l );  
+
+  _ok = new QPushButton( tr("OK"), this );
+  _cancel = new QPushButton( tr("Cancel"), this );
+
+  l->addWidget( _ok );
+  l->addStretch();
+  l->addWidget( _cancel );
+
+  _ok->setDefault(true);
+
+  connect( _ok, SIGNAL( clicked() ),
+          this, SIGNAL( accepted() ) );
+  connect( _cancel, SIGNAL( clicked() ),
+          this, SIGNAL( rejected() ) );
+
+  connect (this, SIGNAL (accepted ()),
+          this, SLOT (accept ()));
+  connect (this, SIGNAL (rejected ()),
+          this, SLOT (reject ()));
+
+  _edit->setFocus();
+}
+
+void PinEntryDialog::paintEvent( QPaintEvent* ev )
+{
+  // Grab keyboard when widget is mapped to screen
+  // It might be a little weird to do it here, but it works!
+  if( !_grabbed ) {
+    _edit->grabKeyboard();
+    _grabbed = true;
+  }
+  QDialog::paintEvent( ev );
+}
+
+void PinEntryDialog::hideEvent( QHideEvent* ev )
+{
+  _edit->releaseKeyboard();
+  _grabbed = false;
+  QDialog::hideEvent( ev );
+}
+
+void PinEntryDialog::keyPressEvent( QKeyEvent* e ) 
+{
+  if ( e->modifiers() == Qt::NoModifier && e->key() == Qt::Key_Escape ) {
+    emit rejected();
+    return;
+  }
+  QDialog::keyPressEvent( e );
+}
+
+void PinEntryDialog::setDescription( const QString& txt ) 
+{
+  _desc->setText( txt );
+  _icon->setPixmap( QMessageBox::standardIcon( QMessageBox::Information ) );
+  setError( QString::null );
+}
+
+QString PinEntryDialog::description() const 
+{
+  return _desc->text();
+}
+
+void PinEntryDialog::setError( const QString& txt ) 
+{
+  if( !txt.isNull() )_icon->setPixmap( QMessageBox::standardIcon( QMessageBox::Critical ) );
+  _error->setText( txt );
+}
+
+QString PinEntryDialog::error() const 
+{
+  return _error->text();
+}
+
+void PinEntryDialog::setText( const SecQString& txt ) 
+{
+  _edit->setText( txt );
+}
+
+SecQString PinEntryDialog::text() const 
+{
+  return _edit->text();
+}
+
+void PinEntryDialog::setPrompt( const QString& txt ) 
+{
+  _prompt->setText( txt );
+}
+
+QString PinEntryDialog::prompt() const 
+{
+  return _prompt->text();
+}
+
+void PinEntryDialog::setOkText( const QString& txt )
+{
+  _ok->setText( txt );
+}
+
+void PinEntryDialog::setCancelText( const QString& txt )
+{
+  _cancel->setText( txt );
+}
+
+#include "pinentrydialog.moc"
diff --git a/qt4/pinentrydialog.h b/qt4/pinentrydialog.h
new file mode 100644 (file)
index 0000000..f6a9792
--- /dev/null
@@ -0,0 +1,87 @@
+/* 
+   pinentrydialog.h - A (not yet) secure Qt 4 dialog for PIN entry.
+
+   Copyright (C) 2002 Klarälvdalens Datakonsult AB
+   Copyright 2007 Ingo Klöcker
+
+   Written by Steffen Hansen <steffen@klaralvdalens-datakonsult.se>.
+   
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __PINENTRYDIALOG_H__
+#define __PINENTRYDIALOG_H__
+
+#include <QDialog>
+
+class QLabel;
+class QPushButton;
+#ifdef WITH_SECURE_QSTRING
+class SecQLineEdit;
+class SecQString;
+#else
+class QLineEdit;
+class QString;
+#define SecQLineEdit QLineEdit
+#define SecQString QString
+#endif
+
+class PinEntryDialog : public QDialog {
+  Q_OBJECT
+
+  Q_PROPERTY( QString description READ description WRITE setDescription )
+  Q_PROPERTY( QString error READ error WRITE setError )
+    //  Q_PROPERTY( SecQString text READ text WRITE setText )
+  Q_PROPERTY( QString prompt READ prompt WRITE setPrompt )
+public:
+  friend class PinEntryController; // TODO: remove when assuan lets me use Qt eventloop.
+  PinEntryDialog( QWidget* parent = 0, const char* name = 0, bool modal = false );
+
+  void setDescription( const QString& );
+  QString description() const;
+
+  void setError( const QString& );
+  QString error() const;
+
+  void setText( const SecQString& );
+  SecQString text() const;
+
+  void setPrompt( const QString& );
+  QString prompt() const;
+  
+  void setOkText( const QString& );
+  void setCancelText( const QString& );
+
+signals:
+  void accepted();
+  void rejected();
+
+protected:
+  virtual void keyPressEvent( QKeyEvent *e );
+  virtual void hideEvent( QHideEvent* );
+  virtual void paintEvent( QPaintEvent* );
+
+private:
+  QLabel*    _icon;
+  QLabel*    _desc;
+  QLabel*    _error;
+  QLabel*    _prompt;
+  SecQLineEdit* _edit;
+  QPushButton* _ok;
+  QPushButton* _cancel;  
+  bool       _grabbed;
+};
+
+#endif // __PINENTRYDIALOG_H__