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; | |||||
| } | |||||
| // */ | |||||