2002-04-06 Marcus Brinkmann <marcus@g10code.de>
[pinentry.git] / qt / pinentrycontroller.cpp
1 /* pinentrycontroller.cpp - A secure KDE dialog for PIN entry.
2    Copyright (C) 2002 Klarälvdalens Datakonsult AB
3    Written by Steffen Hansen <steffen@klaralvdalens-datakonsult.se>.
4    
5    This program is free software; you can redistribute it and/or
6    modify it under the terms of the GNU General Public License as
7    published by the Free Software Foundation; either version 2 of the
8    License, or (at your option) any later version.
9  
10    This program is distributed in the hope that it will be useful, but
11    WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    General Public License for more details.
14  
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
18    02111-1307, USA  */
19
20 #include "pinentrycontroller.h"
21 #include "pinentrydialog.h"
22 extern "C"
23 {
24 #include "memory.h"
25 }
26 #ifdef USE_KDE
27 # include <kmessagebox.h>
28 #else
29 # include <qmessagebox.h>
30 #endif
31
32 PinEntryController::PinEntryController() : _pinentry( 0 )
33 {
34   int fds[2];
35   fds[0] = 0;
36   fds[1] = 1;
37   
38   assuan_set_malloc_hooks( secmem_malloc, secmem_realloc, secmem_free );
39   int rc = assuan_init_pipe_server( &_ctx, fds );
40   if( rc ) {
41     qDebug(assuan_strerror( static_cast<AssuanError>(rc) ));
42     exit(-1);
43   }
44   rc = registerCommands();
45
46   assuan_set_pointer( _ctx, this );
47 }
48
49 PinEntryController::~PinEntryController()
50 {
51   assuan_deinit_server( _ctx );
52 }
53
54 void PinEntryController::exec()
55 {
56   while( true ) {
57     int rc = assuan_accept( _ctx );
58     if( rc == -1 ) {
59       qDebug("Assuan terminated");
60       break;
61     } else if( rc ) {
62       qDebug("Assuan accept problem: %s", assuan_strerror( static_cast<AssuanError>(rc) ) );
63       break;
64     }
65     rc = assuan_process( _ctx );
66     if( rc ) {
67       qDebug("Assuan processing failed: %s", assuan_strerror( static_cast<AssuanError>(rc) ) );
68       continue;
69     }
70   }
71 }
72
73 int PinEntryController::registerCommands()
74 {
75   static struct {
76     const char *name;
77     int cmd_id;
78     int (*handler)(ASSUAN_CONTEXT, char *line);
79   } table[] = {
80     { "SETDESC",      0,  PinEntryController::assuanDesc },
81     { "SETPROMPT",    0,  PinEntryController::assuanPrompt },
82     { "SETERROR",     0,  PinEntryController::assuanError },
83     { "GETPIN",       0,  PinEntryController::assuanGetpin },
84     { "CONFIRM",      0,  PinEntryController::assuanConfirm },
85     { 0,0,0 }
86   };
87   int i, j, rc;
88   
89   for (i=j=0; table[i].name; i++) {
90     rc = assuan_register_command (_ctx,
91                                   table[i].cmd_id? table[i].cmd_id
92                                   : (ASSUAN_CMD_USER + j++),
93                                   table[i].name, table[i].handler);
94     if (rc) return rc;
95   }
96   return 0;
97 }
98
99 int PinEntryController::assuanDesc( ASSUAN_CONTEXT ctx, char* line )
100 {
101   //qDebug("PinEntryController::assuanDesc( %s )", line );
102   PinEntryController* that =   static_cast<PinEntryController*>(assuan_get_pointer(ctx));
103   that->_desc = QString::fromUtf8(line);
104   that->_error = QString::null;
105   return 0;
106 }
107
108 int PinEntryController::assuanPrompt( ASSUAN_CONTEXT ctx, char* line )
109 {
110   //qDebug("PinEntryController::assuanPrompt( %s )", line );
111   PinEntryController* that =   static_cast<PinEntryController*>(assuan_get_pointer(ctx));
112   that->_prompt = QString::fromUtf8(line);
113   that->_error = QString::null;
114   return 0;
115 }
116
117 int PinEntryController::assuanError( ASSUAN_CONTEXT ctx, char* line )
118 {
119   //qDebug("PinEntryController::assuanError( %s )", line );
120   PinEntryController* that =   static_cast<PinEntryController*>(assuan_get_pointer(ctx));
121   that->_error = QString::fromUtf8(line);
122   return 0;
123 }
124
125 int PinEntryController::assuanGetpin( ASSUAN_CONTEXT ctx, char* line )
126 {
127   //qDebug("PinEntryController::assuanGetpin( %s )", line );  
128   PinEntryController* that =   static_cast<PinEntryController*>(assuan_get_pointer(ctx));
129   return that->getPin( line );
130 }
131
132 int PinEntryController::getPin( char* line ) {
133   if( _pinentry == 0 ) {
134     _pinentry = new PinEntryDialog(0,0,true);
135   }
136   _pinentry->setPrompt( _prompt );
137   _pinentry->setDescription( _desc );
138   if( !_error.isNull() ) _pinentry->setError( _error );
139   connect( _pinentry, SIGNAL( accepted() ),
140            this, SLOT( slotAccepted() ) );
141   connect( _pinentry, SIGNAL( rejected() ),
142            this, SLOT( slotRejected() ) );
143   bool ret = _pinentry->exec();  
144   FILE* fp = assuan_get_data_fp( _ctx );
145   if( ret ) {
146     fputs( static_cast<const char*>(_pinentry->text().utf8()), fp );
147     return 0;
148   } else {
149     assuan_set_error( _ctx, ASSUAN_Canceled, "Dialog cancelled by user" );
150     return ASSUAN_Canceled;
151   }
152 }
153
154 int PinEntryController::assuanConfirm( ASSUAN_CONTEXT ctx, char* line )
155 {
156   //qDebug("PinEntryController::assuanConfirm( %s )", line );  
157   PinEntryController* that =   static_cast<PinEntryController*>(assuan_get_pointer(ctx));
158   return that->confirm( line );  
159 }
160
161 int PinEntryController::confirm( char* line )
162 {
163   int ret;
164 #ifdef USE_KDE
165   if( !_error.isNull() ) {
166     ret = KMessageBox::questionYesNo( 0, _error );
167   } else {
168     ret = KMessageBox::questionYesNo( 0, _desc );    
169   }
170   FILE* fp = assuan_get_data_fp( _ctx );
171   if( ret == KMessageBox::Yes ) {
172 #else
173   if( !_error.isNull() ) {
174     ret = QMessageBox::critical( 0, "", _error, QMessageBox::Yes, QMessageBox::No );
175   } else {
176     ret = QMessageBox::information( 0, "", _desc, QMessageBox::Yes, QMessageBox::No );
177   }    
178   FILE* fp = assuan_get_data_fp( _ctx );
179   if( ret == 0 ) {
180 #endif // USE_KDE
181     fputs( "YES", fp );    
182   } else {
183     fputs( "NO", fp );
184   }
185   return 0;
186 }
187
188 void PinEntryController::slotAccepted()
189 {
190   //qDebug("PinEntryController::slotAccepted() NYI");
191   _pinentry->accept();
192 }
193
194 void PinEntryController::slotRejected()
195 {
196   //qDebug("PinEntryController::slotRejected() NYI");
197   _pinentry->reject();
198 }