Changeset View
Changeset View
Standalone View
Standalone View
b/fltk/main.cxx
/* | |||||
main.cpp - A Fltk based dialog for PIN entry. | |||||
Copyright (C) 2016 Anatoly madRat L. Berenblit | |||||
Written by Anatoly madRat L. Berenblit <madrat-@users.noreply.github.com>. | |||||
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. | |||||
*/ | |||||
#ifdef HAVE_CONFIG_H | |||||
#include "config.h" | |||||
#endif | |||||
#define PGMNAME (PACKAGE_NAME"-fltk") | |||||
#include <stdio.h> | |||||
#include <stdlib.h> | |||||
#include <unistd.h> | |||||
#include <errno.h> | |||||
#include <getopt.h> | |||||
#include <assert.h> | |||||
#include "memory.h" | |||||
#include <memory> | |||||
#include <pinentry.h> | |||||
#ifdef FALLBACK_CURSES | |||||
#include <pinentry-curses.h> | |||||
#endif | |||||
#include <string> | |||||
#include <string.h> | |||||
#include <stdexcept> | |||||
#include <FL/Fl.H> | |||||
#include <FL/Fl_Window.H> | |||||
#include <FL/fl_ask.H> | |||||
#include "pinwindow.h" | |||||
#include "passwindow.h" | |||||
#include "qualitypasswindow.h" | |||||
#define CONFIRM_STRING "Confirm" | |||||
#define REPEAT_ERROR_STRING "Texts do not match" | |||||
#define OK_STRING "OK" | |||||
#define CANCEL_STRING "Cancel" | |||||
char *application = NULL; | |||||
static std::string escape_accel_utf8(const char *s) | |||||
{ | |||||
std::string result; | |||||
if (NULL != s) | |||||
{ | |||||
result.reserve(strlen(s)); | |||||
for (const char *p = s; *p; ++p) | |||||
{ | |||||
if ('&' == *p) | |||||
result.push_back(*p); | |||||
result.push_back(*p); | |||||
} | |||||
} | |||||
return result; | |||||
} | |||||
class cancel_exception | |||||
{ | |||||
}; | |||||
static int get_quality(const char *passwd, void *ptr) | |||||
{ | |||||
if (NULL == passwd || 0 == *passwd) | |||||
return 0; | |||||
pinentry_t* pe = reinterpret_cast<pinentry_t*>(ptr); | |||||
return pinentry_inq_quality(*pe, passwd, strlen(passwd)); | |||||
} | |||||
bool is_short(const char *str) | |||||
{ | |||||
return fl_utf_nb_char(reinterpret_cast<const unsigned char*>(str), strlen(str)) < 16; | |||||
} | |||||
bool is_empty(const char *str) | |||||
{ | |||||
return (NULL == str) || (0 == *str); | |||||
} | |||||
static int fltk_cmd_handler(pinentry_t pe) | |||||
{ | |||||
int ret = -1; | |||||
try | |||||
{ | |||||
// TODO: Add parent window to pinentry-fltk window | |||||
//if (pe->parent_wid){} | |||||
std::string title = !is_empty(pe->title)?pe->title:PGMNAME; | |||||
std::string ok = escape_accel_utf8(pe->ok?pe->ok:(pe->default_ok?pe->default_ok:OK_STRING)); | |||||
std::string cancel = escape_accel_utf8(pe->cancel?pe->cancel:(pe->default_cancel?pe->default_cancel:CANCEL_STRING)); | |||||
if (!!pe->pin) // password (or confirmation) | |||||
{ | |||||
std::auto_ptr<PinWindow> window; | |||||
bool isSimple = (NULL == pe->quality_bar) && // pinenty.h: If this is not NULL ... | |||||
is_empty(pe->error) && is_empty(pe->description) && | |||||
is_short(pe->prompt); | |||||
if (isSimple) | |||||
{ | |||||
assert(NULL == pe->description); | |||||
window.reset(PinWindow::create()); | |||||
window->prompt(pe->prompt); | |||||
} | |||||
else | |||||
{ | |||||
PassWindow *pass = NULL; | |||||
if (pe->quality_bar) // pinenty.h: If this is not NULL ... | |||||
{ | |||||
QualityPassWindow *p = QualityPassWindow::create(get_quality, &pe); | |||||
window.reset(p); | |||||
pass = p; | |||||
p->quality(pe->quality_bar); | |||||
} | |||||
else | |||||
{ | |||||
pass = PassWindow::create(); | |||||
window.reset(pass); | |||||
} | |||||
if (NULL == pe->description) | |||||
{ | |||||
pass->description(pe->prompt); | |||||
pass->prompt(" "); | |||||
} | |||||
else | |||||
{ | |||||
pass->description(pe->description); | |||||
pass->prompt(escape_accel_utf8(pe->prompt).c_str()); | |||||
} | |||||
pass->description(pe->description); | |||||
pass->prompt(escape_accel_utf8(pe->prompt).c_str()); | |||||
if (NULL != pe->error) | |||||
pass->error(pe->error); | |||||
} | |||||
window->ok(ok.c_str()); | |||||
window->cancel(cancel.c_str()); | |||||
window->title(title.c_str()); | |||||
window->showModal((NULL != application)?1:0, &application); | |||||
if (NULL == window->passwd()) | |||||
throw cancel_exception(); | |||||
const std::string password = window->passwd(); | |||||
window.reset(); | |||||
if (pe->repeat_passphrase) | |||||
{ | |||||
const char *dont_match = NULL; | |||||
do | |||||
{ | |||||
if (NULL == dont_match && is_short(pe->repeat_passphrase)) | |||||
{ | |||||
window.reset(PinWindow::create()); | |||||
window->prompt(escape_accel_utf8(pe->repeat_passphrase).c_str()); | |||||
} | |||||
else | |||||
{ | |||||
PassWindow *pass = PassWindow::create(); | |||||
window.reset(pass); | |||||
pass->description(pe->repeat_passphrase); | |||||
pass->prompt(" "); | |||||
pass->error(dont_match); | |||||
} | |||||
window->ok(ok.c_str()); | |||||
window->cancel(cancel.c_str()); | |||||
window->title(title.c_str()); | |||||
window->showModal(); | |||||
if (NULL == window->passwd()) | |||||
throw cancel_exception(); | |||||
if (password == window->passwd()) | |||||
{ | |||||
pe->repeat_okay = 1; | |||||
ret = 1; | |||||
break; | |||||
} | |||||
else | |||||
{ | |||||
dont_match = (NULL!=pe->repeat_error_string)? pe->repeat_error_string:REPEAT_ERROR_STRING; | |||||
} | |||||
} while (true); | |||||
} | |||||
else | |||||
ret = 1; | |||||
pinentry_setbufferlen(pe, password.size()+1); | |||||
if (pe->pin) | |||||
{ | |||||
memcpy(pe->pin, password.c_str(), password.size()+1); | |||||
pe->result = password.size(); | |||||
ret = password.size(); | |||||
} | |||||
} | |||||
else | |||||
{ | |||||
// Confirmation or Message Dialog title, desc | |||||
Fl_Window dummy(0,0, 1,1); | |||||
dummy.border(0); | |||||
dummy.show((NULL != application)?1:0, &application); | |||||
dummy.hide(); | |||||
fl_message_title(title.c_str()); | |||||
int result = -1; | |||||
const char *message = (NULL != pe->description)?pe->description:CONFIRM_STRING; | |||||
if (pe->one_button) | |||||
{ | |||||
fl_ok = ok.c_str(); | |||||
fl_message(message); | |||||
result = 1; // OK | |||||
} | |||||
else if (pe->notok) | |||||
{ | |||||
switch (fl_choice(message, ok.c_str(), cancel.c_str(), pe->notok)) | |||||
{ | |||||
case 0: result = 1; break; | |||||
case 2: result = 0; break; | |||||
default: | |||||
case 1: result = -1;break; | |||||
} | |||||
} | |||||
else | |||||
{ | |||||
switch (fl_choice(message, ok.c_str(), cancel.c_str(), NULL)) | |||||
{ | |||||
case 0: result = 1; break; | |||||
default: | |||||
case 1: result = -1;break; | |||||
} | |||||
} | |||||
// cancel -> pe->canceled = true, 0 | |||||
// ok/y -> 1 | |||||
// no -> 0 | |||||
if (-1 == result) | |||||
pe->canceled = true; | |||||
ret = (1 == result); | |||||
} | |||||
Fl::check(); | |||||
} | |||||
catch (const cancel_exception&) | |||||
{ | |||||
ret = -1; | |||||
} | |||||
catch (...) | |||||
{ | |||||
ret = -1; | |||||
} | |||||
// do_touch_file(pe); only for NCURSES? | |||||
return ret; | |||||
} | |||||
pinentry_cmd_handler_t pinentry_cmd_handler = fltk_cmd_handler; | |||||
int main(int argc, char *argv[]) | |||||
{ | |||||
application = *argv; | |||||
pinentry_init(PGMNAME); | |||||
#ifdef FALLBACK_CURSES | |||||
if (!pinentry_have_display(argc, argv)) | |||||
pinentry_cmd_handler = curses_cmd_handler; | |||||
else | |||||
#endif | |||||
{ | |||||
//FLTK understood only -D (--display) | |||||
// and should be converted into -di[splay] | |||||
const static struct option long_options[] = | |||||
{ | |||||
{"display", required_argument, 0, 'D' }, | |||||
{NULL, no_argument, 0, 0 } | |||||
}; | |||||
for (int i = 0; i < argc-1; ++i) | |||||
{ | |||||
switch (getopt_long(argc-i, argv+i, "D:", long_options, NULL)) | |||||
{ | |||||
case 'D': | |||||
{ | |||||
char* emul[] = {application, (char*)"-display", optarg}; | |||||
Fl::args(3, emul); | |||||
i = argc; | |||||
break; | |||||
} | |||||
default: | |||||
break; | |||||
} | |||||
} | |||||
} | |||||
pinentry_parse_opts(argc, argv); | |||||
return pinentry_loop() ?EXIT_FAILURE:EXIT_SUCCESS; | |||||
} | |||||
/* | |||||
int get_quality(const char *pass) | |||||
{ | |||||
size_t len = strlen(pass); | |||||
return len>4?(80+len):-len*10; | |||||
} | |||||
int main(int argc, char *argv[]) | |||||
{ | |||||
std::auto_ptr<PassWindow> window; | |||||
window.reset(QualityPassWindow::create(get_quality)); | |||||
// window->message("Lorem ipsum dolor sit amet"); | |||||
// window->message("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus porttitor nisi a fringilla porttitor. Phasellus tempor orci vel metus eleifend ultrices. Curabitur tempor euismod lorem"); | |||||
window->prompt("Lorem ipsum:"); | |||||
window->ok("YES!"); | |||||
window->cancel("OTMEHA"); | |||||
// window->error("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus porttitor nisi a fringilla"); | |||||
// window->error("Some error ellus adipiscing elit portt text dolor sit amet, consectetur adipiscing elit. Phasellus porttitor a porttitor!"); | |||||
window->timeout(100); | |||||
window->title(PGMNAME); | |||||
window->showModal(argc, argv); | |||||
return 0; | |||||
} | |||||
// */ | |||||
/* | |||||
int main(int argc, char *argv[]) | |||||
{ | |||||
Fl::args(argc, argv); | |||||
std::auto_ptr<PinWindow> window; | |||||
window.reset(PinWindow::create()); | |||||
// window->message("PIN:"); | |||||
// window->message("Phasellus adipiscing elit porttitor nisi a fringilla porttitor:"); | |||||
window->ok("YES!"); | |||||
window->cancel("OTMEHA"); | |||||
window->timeout(100); | |||||
window->title(PGMNAME); | |||||
window->showModal(argc, argv); | |||||
return 0; | |||||
} | |||||
// */ | |||||
/* | |||||
int main(int argc, char *argv[]) | |||||
{ | |||||
Fl::args(argc, argv); | |||||
std::auto_ptr<PassWindow> window; | |||||
window.reset(PassWindow::create()); | |||||
// window->message("Descr&iption"); | |||||
// window->message("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus porttitor nisi a fringilla porttitor:"); | |||||
// window->prompt("Prompt sit amet:"); | |||||
window->ok("YES!"); | |||||
window->cancel("OTMEHA"); | |||||
// window->error("Password is empty."); | |||||
// window->error("Some error text dolor sit amet, consectetur adipiscing elit. Phasellus porttitor nisi a fringilla porttitor!"); | |||||
// window->error("Some error ellus adipiscing elit portt text dolor sit amet, consectetur adipiscing elit. Phasellus porttitor nisi a fringilla porttitor!"); | |||||
window->timeout(100); | |||||
window->title(PGMNAME); | |||||
window->showModal(argc, argv); | |||||
return 0; | |||||
} | |||||
// */ |