• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

yapet/mainwindow.cc

Go to the documentation of this file.
00001 // $Id: mainwindow.cc 3356 2010-09-18 21:06:17Z rafi $
00002 //
00003 // Copyright (C) 2008-2010  Rafael Ostertag
00004 //
00005 // This file is part of YAPET.
00006 //
00007 // YAPET is free software: you can redistribute it and/or modify it under the
00008 // terms of the GNU General Public License as published by the Free Software
00009 // Foundation, either version 3 of the License, or (at your option) any later
00010 // version.
00011 //
00012 // YAPET is distributed in the hope that it will be useful, but WITHOUT ANY
00013 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00014 // FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
00015 // details.
00016 //
00017 // You should have received a copy of the GNU General Public License along with
00018 // YAPET.  If not, see <http://www.gnu.org/licenses/>.
00019 //
00020 
00021 #ifdef HAVE_CONFIG_H
00022 # include <config.h>
00023 #endif
00024 
00025 #ifdef HAVE_FCNTL_H
00026 # include <fcntl.h>
00027 #endif
00028 
00029 #ifdef HAVE_SYS_TYPES_H
00030 # include <sys/types.h>
00031 #endif
00032 
00033 #ifdef HAVE_SYS_STAT_H
00034 # include <sys/stat.h>
00035 #endif
00036 
00037 #ifdef HAVE_SIGNAL_H
00038 # include <signal.h>
00039 #endif
00040 
00041 #ifdef HAVE_ERRNO_H
00042 # include <errno.h>
00043 #endif
00044 
00045 #ifdef HAVE_STRING_H
00046 # include <string.h>
00047 #endif
00048 
00049 #ifdef TIME_WITH_SYS_TIME
00050 # include <sys/time.h>
00051 # include <time.h>
00052 #else
00053 # ifdef HAVE_SYS_TIME_H
00054 #  include <sys/time.h>
00055 # else
00056 #  include <time.h>
00057 # endif
00058 #endif // TIME_WITH_SYS_TIME
00059 
00060 #include <button.h>
00061 #include <dialogbox.h>
00062 #include <colors.h>
00063 #include <misc.h>
00064 
00065 #include "../intl.h"
00066 #include "mainwindow.h"
00067 #include "fileopen.h"
00068 #include "passworddialog.h"
00069 #include "passwordrecord.h"
00070 #include "searchdialog.h"
00071 #ifdef ENABLE_PWGEN
00072 # include "pwgendialog.h"
00073 #endif
00074 #include "globals.h"
00075 
00082 struct KeyDesc {
00088     int y;
00094     int x;
00100     const char* key;
00106     const char* desc;
00107 };
00108 
00109 /*
00110  * The _ macro is undefined and redefined to a noop, so we can trick the
00111  * xgettext program to read strings to translate. After that, _ is restored to
00112  * its previous state (taken from intl.h).
00113  *
00114  * The actual translation using gettext is done in
00115  * MainWindow::topRightWinContent()
00116  *
00117  * Better approaches welcome.
00118  */
00119 #ifdef _
00120 #undef _
00121 #endif
00122 #define _(String) String
00123 
00128 KeyDesc keys[] = { {3, 2, "S", _ ("Save File") },
00129     {4, 2, "R", _ ("Load File") },
00130     {5, 2, "L", _ ("Lock Screen") },
00131     {6, 2, "A", _ ("Add Entry") },
00132     {7, 2, "D", _ ("Delete Entry") },
00133     {8, 2, "O", _ ("Sort Order") },
00134     {9, 2, "/", _ ("Search") },
00135     {10, 2, "N", _ ("Search Next") },
00136     {11, 2, "C", _ ("Change Password") },
00137     {12, 2, "^L", _ ("Redraw Screen") },
00138     {13, 2, "Q", _ ("Quit") },
00139 #ifdef ENABLE_PWGEN
00140     {14, 2, "G", _ ("Password Generator") },
00141 #endif
00142     {0, 0, NULL, NULL}
00143 };
00144 #undef _
00145 #if ! defined(_) && ENABLE_NLS==0
00146 #define _(String) (String)
00147 #endif
00148 
00149 #if ! defined(_) && ENABLE_NLS==1
00150 #define _(String) gettext(String)
00151 #endif
00152 
00153 
00154 #if defined(HAVE_SIGACTION) && defined(HAVE_SIGNAL_H)
00155 
00161 class Alarm : public YAPET::UI::BaseWindow::AlarmFunction {
00162     private:
00163         MainWindow& ref;
00164     public:
00165         inline Alarm (MainWindow& r) : ref (r) {}
00166         inline void process (int signo) {
00167             ref.handle_signal (signo);
00168         }
00169 };
00170 #endif // defined(HAVE_SIGACTION) && defined(HAVE_SIGNAL_H)
00171 
00172 void
00173 MainWindow::printTitle() throw (YAPET::UI::UIException) {
00174     YAPET::UI::Colors::setcolor (stdscr, YAPET::UI::DEFAULT);
00175     // Clear the previous title
00176     int retval = wmove (stdscr, 0, 0);
00177 
00178     if (retval == ERR)
00179         throw YAPET::UI::UIException (_ ("Error moving cursor") );
00180 
00181     retval = wclrtoeol (stdscr);
00182 
00183     if (retval == ERR)
00184         throw YAPET::UI::UIException (_ ("Error clearing line") );
00185 
00186     // Title
00187     char title[100];
00188     snprintf (title, 100, "..::|| %s ||::..", PACKAGE_STRING);
00189     // Position the title
00190     retval = wmove (stdscr, 0, maxX() / 2 - strlen (title) / 2);
00191 
00192     if (retval == ERR)
00193         throw YAPET::UI::UIException (_ ("Error moving cursor") );
00194 
00195     retval = mywaddstr (stdscr, title);
00196 
00197     if (retval == ERR)
00198         throw YAPET::UI::UIException (_ ("Error printing title") );
00199 
00200     std::string terminal_title;
00201 
00202     if ( file != NULL )
00203         terminal_title = "YAPET (" + file->getFilename() + ")";
00204     else
00205         terminal_title = "YAPET";
00206 
00207     setTerminalTitle (terminal_title);
00208 }
00209 
00210 void
00211 MainWindow::topRightWinContent() throw (YAPET::UI::UIException) {
00212     int max_y, max_x;
00213     getmaxyx (toprightwin, max_y, max_x);
00214     int start_title_x = max_x / 2 - strlen (_ ("K E Y S") ) / 2;
00215     int retval = mymvwaddstr (toprightwin, 1, start_title_x, _ ("K E Y S") );
00216 
00217     if (retval == ERR)
00218         throw YAPET::UI::UIException (_ ("mvwaddstr() blew it") );
00219 
00220     retval = wmove (toprightwin, 2, 1);
00221 
00222     if (retval == ERR)
00223         throw YAPET::UI::UIException (_ ("wmove() blew it") );
00224 
00225 #if defined(_XOPEN_CURSES) && !defined(__NCURSES_H)
00226     retval = whline (toprightwin, '-', max_x - 2);
00227 #else
00228     retval = whline (toprightwin, 0, max_x - 2);
00229 #endif
00230 
00231     if (retval == ERR)
00232         throw YAPET::UI::UIException (_ ("whline() blew it") );
00233 
00234     KeyDesc* ptr = keys;
00235 
00236     while (ptr->key != NULL
00237             && ptr->desc != NULL) {
00238         wattron (toprightwin, A_REVERSE);
00239         retval = mvwprintw (toprightwin, ptr->y, ptr->x, "  %0-2s  ", ptr->key);
00240 
00241         if (retval == ERR)
00242             throw YAPET::UI::UIException (_ ("mvprintw() blew it") );
00243 
00244         wattroff (toprightwin, A_REVERSE);
00245         // The translation of the keys is done here
00246         retval = mymvwaddstr (toprightwin, ptr->y, ptr->x + 8, _ (ptr->desc) );
00247 
00248         if (retval == ERR)
00249             throw YAPET::UI::UIException (_ ("waddstr() blew it") );
00250 
00251         ptr++;
00252     }
00253 }
00254 
00255 void
00256 MainWindow::bottomRightWinContent() throw (YAPET::UI::UIException) {
00257     if (key == NULL || recordlist == NULL) return;
00258 
00259     int retval = 0;
00260 
00261     if (usefsecurity)
00262         retval = mymvwaddstr (bottomrightwin, 1, 2, _ ("File permission check: enabled") );
00263     else
00264         retval = mymvwaddstr (bottomrightwin, 1, 2, _ ("File permission check: disabled") );
00265 
00266     if (retval == ERR)
00267         throw YAPET::UI::UIException (_ ("waddstr() blew it") );
00268 
00269     retval = mvwprintw (bottomrightwin, 2, 2, _ ("Screen lock time-out: %u sec"), locktimeout);
00270 
00271     if (retval == ERR)
00272         throw YAPET::UI::UIException (_ ("mvprintw() blew it") );
00273 
00274     // The %s in the format string is used for indicating whether or not
00275     // records have been altered, added, and or removed.
00276     //
00277     // The empty string containing of spaces is used to erase any previous
00278     // status indications.
00279     //
00280     // (V: %d) displays the version if a file is loaded.
00281     int version = 0;
00282     if (file != NULL && key != NULL) 
00283     version = (int)file->getFileVersion(*key);
00284 
00285     retval = mvwprintw (bottomrightwin, 3, 2, _ ("%d entries %s (V: %d)"), recordlist->size(), (records_changed ? "(+)" : "   "), version );
00286 
00287     if (retval == ERR)
00288         throw YAPET::UI::UIException (_ ("mvprintw() blew it") );
00289 
00290 #if defined(HAVE_ASCTIME) && defined(HAVE_LOCALTIME)
00291 
00292     if (file != NULL) {
00293         try {
00294             time_t t = static_cast<time_t>(file->getMasterPWSet (*key));
00295         retval = mvwprintw (bottomrightwin, 4, 2, _ ("PW set: %s"),
00296                 asctime (localtime (&t) ) );
00297 
00298             if (retval == ERR)
00299                 throw YAPET::UI::UIException (_ ("mvprintw() blew it") );
00300         } catch (YAPET::YAPETException& ex) {
00301             statusbar.putMsg (ex.what() );
00302         }
00303     }
00304 
00305 #endif
00306 }
00307 
00308 void
00309 MainWindow::createWindow() throw (YAPET::UI::UIException) {
00310     if (toprightwin != NULL || bottomrightwin != NULL)
00311         throw YAPET::UI::UIException (_ ("May you consider deleting the window before reallocating") );
00312 
00313     int middleX = maxX() / 2;
00314     int thirdY = maxY() / 3 - 1;
00315     printTitle();
00316     //
00317     // Top right window
00318     //
00319     toprightwin = newwin (maxY() - thirdY - 1 , maxX() - middleX, 1, middleX);
00320 
00321     if (toprightwin == NULL)
00322         throw YAPET::UI::UIException (_ ("newwin() returned NULL") );
00323 
00324     YAPET::UI::Colors::setcolor (toprightwin, YAPET::UI::DEFAULT);
00325     int retval = box (toprightwin, 0, 0);
00326 
00327     if (retval == ERR)
00328         throw YAPET::UI::UIException (_ ("box() blew it") );
00329 
00330     topRightWinContent();
00331     //
00332     // Bottom right window
00333     //
00334     bottomrightwin = newwin (thirdY - 1 , maxX() - middleX, maxY() - thirdY, middleX);
00335 
00336     if (bottomrightwin == NULL)
00337         throw YAPET::UI::UIException (_ ("newwin() returned NULL") );
00338 
00339     YAPET::UI::Colors::setcolor (bottomrightwin, YAPET::UI::DEFAULT);
00340     retval = werase (bottomrightwin);
00341 
00342     if (retval == ERR)
00343         throw YAPET::UI::UIException (_ ("werase() blew it") );
00344 
00345     retval = box (bottomrightwin, 0, 0);
00346 
00347     if (retval == ERR)
00348         throw YAPET::UI::UIException (_ ("box() blew it") );
00349 
00350     //
00351     // List widget on the left
00352     //
00353     if (recordlist == NULL) {
00354         std::list<YAPET::PartDec> emptylist;
00355         recordlist = new YAPET::UI::ListWidget<YAPET::PartDec> (emptylist,
00356                 0,
00357                 1,
00358                 maxX() / 2,
00359                 maxY() - 2);
00360     }
00361 
00362     bottomRightWinContent();
00363 }
00364 
00365 void
00366 MainWindow::resize() throw (YAPET::UI::UIException) {
00367     int retval = delwin (toprightwin);
00368 
00369     if (retval == ERR)
00370         throw YAPET::UI::UIException (_ ("delwin() blew it") );
00371 
00372     retval = delwin (bottomrightwin);
00373 
00374     if (retval == ERR)
00375         throw YAPET::UI::UIException (_ ("delwin() blew it") );
00376 
00377     toprightwin = NULL;
00378     bottomrightwin = NULL;
00379     createWindow();
00380     recordlist->resize (0, 1, maxX() / 2, maxY() - 2);
00381 }
00382 
00383 void
00384 MainWindow::refresh() throw (YAPET::UI::UIException) {
00385     printTitle();
00386     int retval = wrefresh (stdscr);
00387 
00388     if (retval == ERR)
00389         throw YAPET::UI::UIException (_ ("Error refreshing stdscr") );
00390 
00391     topRightWinContent();
00392     bottomRightWinContent();
00393     retval = box (toprightwin, 0, 0);
00394 
00395     if (retval == ERR)
00396         throw YAPET::UI::UIException (_ ("Error setting border") );
00397 
00398     retval = box (bottomrightwin, 0, 0);
00399 
00400     if (retval == ERR)
00401         throw YAPET::UI::UIException (_ ("Error setting border") );
00402 
00403     retval = wrefresh (toprightwin);
00404 
00405     if (retval == ERR)
00406         throw YAPET::UI::UIException (_ ("Error refreshing top right window") );
00407 
00408     retval = wrefresh (bottomrightwin);
00409 
00410     if (retval == ERR)
00411         throw YAPET::UI::UIException (_ ("Error refreshing bottom right window") );
00412 
00413     recordlist->refresh();
00414     statusbar.refresh();
00415 }
00416 
00417 void
00418 MainWindow::createFile (std::string& filename) throw (YAPET::UI::UIException) {
00419     closeFile();
00420     PasswordDialog* pwdia = NULL;
00421 
00422     try {
00423         pwdia = new PasswordDialog (NEW_PW, filename);
00424         pwdia->run();
00425         key = pwdia->getKey();
00426         delete pwdia;
00427     } catch (YAPET::UI::UIException&) {
00428         if (pwdia != NULL)
00429             delete pwdia;
00430 
00431         statusbar.putMsg (_ ("Error while asking for password") );
00432         return;
00433     }
00434 
00435     if (key == NULL) {
00436         statusbar.putMsg (_ ("Creation of file canceled") );
00437         return;
00438     }
00439 
00440     try {
00441         file = new YAPET::File (filename, *key, true, usefsecurity);
00442         statusbar.putMsg (filename + _ (" created") );
00443         records_changed = false;
00444     } catch (YAPET::YAPETException& ex) {
00445         YAPET::UI::MessageBox* msgbox = NULL;
00446 
00447         try {
00448             msgbox = new YAPET::UI::MessageBox (_ ("E R R O R"), ex.what() );
00449             msgbox->run();
00450             delete msgbox;
00451         } catch (YAPET::UI::UIException&) {
00452             if (msgbox != NULL)
00453                 delete msgbox;
00454 
00455             statusbar.putMsg (_ ("Error showing error message") );
00456         }
00457 
00458         closeFile();
00459     }
00460 }
00461 
00462 void
00463 MainWindow::openFile (std::string filename) throw (YAPET::UI::UIException) {
00464     struct stat st;
00465     int retval = stat (filename.c_str(), &st);
00466 
00467     if (retval == -1 && errno == ENOENT) {
00468         // Ask user whether or not he wants to create a new file
00469         YAPET::UI::DialogBox* question =
00470             new YAPET::UI::DialogBox (_ ("Q U E S T I O N"),
00471                                       _ ("The file does not exist. Do you want to create it?") );
00472         question->run();
00473         YAPET::UI::ANSWER a = question->getAnswer();
00474         delete question;
00475 
00476         if ( a == YAPET::UI::ANSWER_OK) {
00477             createFile (filename);
00478             return;
00479         } else {
00480             statusbar.putMsg (_ ("File creation canceled") );
00481             return;
00482         }
00483     } else if (retval == -1) {
00484         // Inform user about other error
00485         YAPET::UI::MessageBox* errmsg = NULL;
00486 
00487         try {
00488             errmsg = new YAPET::UI::MessageBox (_ ("E R R O R"), strerror (errno) );
00489             errmsg->run();
00490             delete errmsg;
00491         } catch (YAPET::UI::UIException&) {
00492             if (errmsg != NULL)
00493                 delete errmsg;
00494         }
00495 
00496         refresh();
00497         return;
00498     }
00499 
00500     // We were able to stat the file, now make sure it is a file and open it
00501     // using the password
00502     if (!S_ISREG (st.st_mode) ) {
00503         YAPET::UI::MessageBox* errmsg = NULL;
00504 
00505         try {
00506             errmsg = new YAPET::UI::MessageBox (_ ("E R R O R"),
00507                                                 _ ("The specified file is not a regular file") );
00508             errmsg->run();
00509             delete errmsg;
00510         } catch (YAPET::UI::UIException&) {
00511             if (errmsg != NULL)
00512                 delete errmsg;
00513         }
00514 
00515         return;
00516     }
00517 
00518     closeFile();
00519     // Ask for password
00520     PasswordDialog* pwdia = NULL;
00521 
00522     try {
00523         pwdia = new PasswordDialog (EXISTING_PW, filename);
00524         pwdia->run();
00525         key = pwdia->getKey();
00526         delete pwdia;
00527     } catch (YAPET::UI::UIException&) {
00528         if (pwdia != NULL)
00529             delete pwdia;
00530 
00531         statusbar.putMsg (_ ("UI error while asking for password") );
00532     }
00533 
00534     // Open file
00535     if (key != NULL) {
00536         try {
00537             file = new YAPET::File (filename, *key, false, usefsecurity);
00538             std::list<YAPET::PartDec> tmp_list = file->read (*key);
00539             recordlist->setList (tmp_list);
00540             statusbar.putMsg (filename + _ (" opened") );
00541             return;
00542         } catch (YAPET::YAPETException& e) {
00543             if (file != NULL)
00544                 delete file;
00545 
00546             YAPET::UI::MessageBox* msgbox = NULL;
00547 
00548             try {
00549                 msgbox = new YAPET::UI::MessageBox (_ ("E R R O R"), e.what() );
00550                 msgbox->run();
00551                 delete msgbox;
00552             } catch (YAPET::UI::UIException&) {
00553                 if (msgbox != NULL)
00554                     delete msgbox;
00555 
00556                 statusbar.putMsg (_ ("Error while trying to show error") );
00557             }
00558 
00559             delete key;
00560             key = NULL;
00561             file = NULL;
00562             statusbar.putMsg (_ ("Error opening file") );
00563             return;
00564         }
00565     } else {
00566         statusbar.putMsg (_ ("Opening of ") + filename + _ (" canceled") );
00567     }
00568 }
00569 
00570 void
00571 MainWindow::saveFile() {
00572     if (key == NULL || file == NULL) return;
00573 
00574     try {
00575         file->save (recordlist->getList() );
00576         records_changed = false;
00577         statusbar.putMsg (file->getFilename() + _ (" saved") );
00578         // This is because the status has to be updated on the right bottom win
00579         // regarding whether or not changes to be saved are pending
00580         bottomRightWinContent();
00581         int retval = wrefresh (bottomrightwin);
00582 
00583         if (retval == ERR)
00584             throw YAPET::UI::UIException (_ ("Error refreshing bottom right window") );
00585     } catch (YAPET::YAPETException& ex) {
00586         YAPET::UI::MessageBox* msgbox = NULL;
00587 
00588         try {
00589             msgbox = new YAPET::UI::MessageBox (_ ("E R R O R"), ex.what() );
00590             msgbox->run();
00591             delete msgbox;
00592         } catch (YAPET::UI::UIException) {
00593             if (msgbox != NULL)
00594                 delete msgbox;
00595 
00596             statusbar.putMsg (_ ("Error showing error message") );
00597         }
00598     }
00599 }
00600 
00601 void
00602 MainWindow::closeFile() {
00603     // Remove key and close file
00604     if (key != NULL) {
00605         delete key;
00606         key = NULL;
00607     }
00608 
00609     if (file != NULL) {
00610         delete file;
00611         file = NULL;
00612     }
00613 
00614     // Clear list
00615     recordlist->getList().clear();
00616     records_changed = false;
00617 }
00618 
00619 void
00620 MainWindow::addNewRecord() {
00621     if (key == NULL || file == NULL) return;
00622 
00623     PasswordRecord* pwentry = NULL;
00624 
00625     try {
00626     // Open the dialog in read-write mode by default
00627         pwentry = new PasswordRecord (*key, NULL, false);
00628         pwentry->run();
00629 
00630         if (pwentry->entryChanged() &&
00631                 pwentry->getEncEntry() != NULL) {
00632             recordlist->getList().push_back (*pwentry->getEncEntry() );
00633             recordlist->setSortOrder();
00634             delete pwentry->getEncEntry();
00635             records_changed = true;
00636             statusbar.putMsg (_ ("New record added") );
00637         } else {
00638             statusbar.putMsg (_ ("Record addition canceled") );
00639         }
00640 
00641         delete pwentry;
00642     } catch (YAPET::UI::UIException& ex) {
00643         if (pwentry != NULL) {
00644             if (pwentry->getEncEntry() != NULL)
00645                 delete pwentry->getEncEntry();
00646 
00647             delete pwentry;
00648         }
00649 
00650         YAPET::UI::MessageBox* msgbox = NULL;
00651 
00652         try {
00653             msgbox = new YAPET::UI::MessageBox (_ ("E R R O R"), _ ("Error adding password entry") );
00654             msgbox->run();
00655             delete msgbox;
00656         } catch (YAPET::UI::UIException&) {
00657             if (msgbox != NULL)
00658                 delete msgbox;
00659 
00660             statusbar.putMsg (_ ("Error showing error message") );
00661         }
00662     }
00663 
00664     ::refresh();
00665     refresh();
00666 }
00667 
00668 void
00669 MainWindow::editSelectedRecord() {
00670     if (key == NULL ||
00671             file == NULL ||
00672             recordlist->size() == 0) return;
00673 
00674     PasswordRecord* pwentry = NULL;
00675 
00676     try {
00677         YAPET::PartDec pd = recordlist->getSelectedItem();
00678     // Open the dialog in read-only mode by default
00679         pwentry = new PasswordRecord (*key, &pd, true);
00680         pwentry->run();
00681 
00682         if (pwentry->entryChanged() &&
00683                 pwentry->getEncEntry() != NULL) {
00684             recordlist->replaceCurrentItem (*pwentry->getEncEntry() );
00685             recordlist->setSortOrder();
00686             records_changed = true;
00687             statusbar.putMsg (_ ("Record edited") );
00688             delete pwentry->getEncEntry();
00689         } else {
00690             statusbar.putMsg (_ ("Record edition canceled") );
00691         }
00692 
00693         delete pwentry;
00694     } catch (YAPET::UI::UIException& ex) {
00695         if (pwentry != NULL) {
00696             if (pwentry->getEncEntry() != NULL)
00697                 delete pwentry->getEncEntry();
00698 
00699             delete pwentry;
00700         }
00701 
00702         YAPET::UI::MessageBox* msgbox = NULL;
00703 
00704         try {
00705             msgbox = new YAPET::UI::MessageBox (_ ("E R R O R"), _ ("Error adding password entry") );
00706             msgbox->run();
00707             delete msgbox;
00708         } catch (YAPET::UI::UIException&) {
00709             if (msgbox != NULL)
00710                 delete msgbox;
00711 
00712             statusbar.putMsg (_ ("Error showing error message") );
00713         }
00714     }
00715 
00716     ::refresh();
00717     refresh();
00718 }
00719 
00720 void
00721 MainWindow::deleteSelectedRecord() throw (YAPET::UI::UIException) {
00722     if (recordlist->size() < 1) return;
00723 
00724     YAPET::UI::DialogBox* dialog = NULL;
00725 
00726     try {
00727         dialog = new YAPET::UI::DialogBox (_ ("Q U E S T I O N"), _ ("Delete selected record?") );
00728         dialog->run();
00729         YAPET::UI::ANSWER a = dialog->getAnswer();
00730 
00731         if (a == YAPET::UI::ANSWER_OK) {
00732             recordlist->deleteSelectedItem();
00733             records_changed = true;
00734             recordlist->refresh();
00735             statusbar.putMsg (_ ("Record deleted") );
00736             records_changed = true;
00737         } else {
00738             statusbar.putMsg ("");
00739         }
00740 
00741         delete dialog;
00742     } catch (YAPET::UI::UIException&) {
00743         if (dialog != NULL)
00744             delete dialog;
00745 
00746         YAPET::UI::MessageBox* msgbox = NULL;
00747 
00748         try {
00749             msgbox = new YAPET::UI::MessageBox (_ ("E R R O R"), _ ("Error showing dialog") );
00750             msgbox->run();
00751             delete msgbox;
00752         } catch (YAPET::UI::UIException&) {
00753             if (msgbox != NULL)
00754                 delete msgbox;
00755 
00756             statusbar.putMsg (_ ("Error showing error message") );
00757         }
00758     }
00759 
00760     refresh();
00761 }
00762 
00763 void
00764 MainWindow::setSortOrder() {
00765     try {
00766         switch (recordlist->getSortOrder() ) {
00767             case (YAPET::UI::ListWidget<YAPET::PartDec>::ASCENDING) :
00768                 recordlist->setSortOrder (YAPET::UI::ListWidget<YAPET::PartDec>::DESCENDING);
00769                 statusbar.putMsg (_ ("Set sort order descending") );
00770                 break;
00771             case (YAPET::UI::ListWidget<YAPET::PartDec>::DESCENDING) :
00772                 recordlist->setSortOrder (YAPET::UI::ListWidget<YAPET::PartDec>::ASCENDING);
00773                 statusbar.putMsg (_ ("Set sort order ascending") );
00774                 break;
00775         };
00776 
00777         recordlist->refresh();
00778     } catch (std::exception& ex) {
00779         YAPET::UI::MessageBox* msgbox = NULL;
00780 
00781         try {
00782             msgbox = new YAPET::UI::MessageBox (_ ("E R R O R"), ex.what() );
00783             msgbox->run();
00784             delete msgbox;
00785         } catch (YAPET::UI::UIException&) {
00786             if (msgbox != NULL)
00787                 delete msgbox;
00788 
00789             statusbar.putMsg (_ ("Error showing error message") );
00790         }
00791     }
00792 }
00793 
00794 void
00795 MainWindow::searchTerm() {
00796     if (key == NULL ||
00797             file == NULL ||
00798             recordlist->size() == 0) return;
00799 
00800     SearchDialog* searchdialog = NULL;
00801 
00802     try {
00803         searchdialog = new SearchDialog();
00804         searchdialog->run();
00805 
00806         if (!searchdialog->isCanceled() ) {
00807             if (recordlist->searchTerm (searchdialog->getSearchTerm() ) ) {
00808                 // simply clear the status bar
00809                 statusbar.putMsg ("");
00810             } else {
00811                 statusbar.putMsg (_ ("Search term not found") );
00812             }
00813         } else {
00814             statusbar.putMsg (_ ("Search canceled") );
00815         }
00816 
00817         delete searchdialog;
00818     } catch (YAPET::UI::UIException& ex) {
00819         if (searchdialog != NULL) {
00820             delete searchdialog;
00821         }
00822 
00823         YAPET::UI::MessageBox* msgbox = NULL;
00824 
00825         try {
00826             msgbox = new YAPET::UI::MessageBox (_ ("E R R O R"), ex.what() );
00827             msgbox->run();
00828             delete msgbox;
00829         } catch (YAPET::UI::UIException&) {
00830             if (msgbox != NULL)
00831                 delete msgbox;
00832 
00833             statusbar.putMsg (_ ("Error showing error message") );
00834         }
00835     }
00836 
00837     ::refresh();
00838     refresh();
00839 }
00840 
00841 void
00842 MainWindow::searchNext() {
00843     if (key == NULL ||
00844             file == NULL ||
00845             recordlist->size() == 0) return;
00846 
00847     if (recordlist->searchNext() ) {
00848         // simply clear the status bar
00849         statusbar.putMsg ("");
00850     } else {
00851         statusbar.putMsg (_ ("Search term not found") );
00852     }
00853 }
00854 
00855 bool
00856 MainWindow::quit() {
00860     if (!records_changed) {
00861         return true;
00862     }
00863 
00864     YAPET::UI::DialogBox* dialogbox = NULL;
00865 
00866     try {
00867         dialogbox = new YAPET::UI::DialogBox (_ ("Q U E S T I O N"), _ ("Save before quitting?") );
00868         dialogbox->run();
00869         YAPET::UI::ANSWER a = dialogbox->getAnswer();
00870         delete dialogbox;
00871 
00872         if (a == YAPET::UI::ANSWER_OK) {
00873             saveFile();
00874             return true;
00875         }
00876 
00877         return true;
00878     } catch (YAPET::UI::UIException&) {
00879         if (dialogbox != NULL)
00880             delete dialogbox;
00881 
00882         statusbar.putMsg (_ ("Error showing error message") );
00883         refresh();
00884         return false;
00885     }
00886 }
00887 
00888 void
00889 MainWindow::lockScreen() const throw (YAPET::UI::UIException) {
00890     if (key == NULL) return;
00891 
00892     int ch;
00893 
00894     while (true) {
00895         WINDOW* lockwin = newwin (0, 0, 0, 0);
00896 
00897         if (lockwin == NULL)
00898             throw YAPET::UI::UIException (_ ("Error creating lock window") );
00899 
00900         int retval = werase (lockwin);
00901 
00902         if (retval == ERR) {
00903             delwin (lockwin);
00904             throw YAPET::UI::UIException (_ ("Error erasing window") );
00905         }
00906 
00907         retval = wrefresh (lockwin);
00908 
00909         if (retval == ERR) {
00910             delwin (lockwin);
00911             throw YAPET::UI::UIException (_ ("Error refreshing window") );
00912         }
00913 
00914         std::string locked_title (_ ("YAPET -- Locked --") );
00915         setTerminalTitle (locked_title);
00916         ch = wgetch (lockwin);
00917 #ifdef HAVE_WRESIZE
00918 
00919         if (ch == KEY_RESIZE) {
00920             delwin (lockwin);
00921             YAPET::UI::BaseWindow::resizeAll();
00922             continue;
00923         }
00924 
00925 #endif
00926         PasswordDialog* pwdia = NULL;
00927         YAPET::Key* testkey = NULL;
00928     bool wants_quit = false;
00929 
00930         try {
00931         // Flush pending input
00932         flushinp();
00933 
00934         bool show_quit = records_changed ? false : true;
00935         // In case the user does not want to show the quit button
00936         show_quit = YAPET::GLOBALS::Globals::getAllowLockQuit() ? show_quit : false;
00937 
00938             pwdia = new PasswordDialog (EXISTING_PW,
00939                     file->getFilename(),
00940                     YAPET::GLOBALS::Globals::getPwInputTimeout(),
00941                     show_quit);
00942             pwdia->run();
00943             testkey = pwdia->getKey();
00944         wants_quit = pwdia->wantsQuit();
00945             delete pwdia;
00946         } catch (YAPET::UI::UIException&) {
00947             if (pwdia != NULL)
00948                 delete pwdia;
00949 
00950             if (testkey != NULL)
00951                 delete testkey;
00952 
00953             delwin (lockwin);
00954             continue;
00955         }
00956 
00957         if (testkey == NULL) {
00958             delwin (lockwin);
00959         // Do we have to quit
00960         if (wants_quit) {
00961         ungetch('q');
00962         return;
00963         }
00964             continue;
00965         }
00966 
00967         if (*testkey != *key) {
00968             YAPET::UI::MessageBox* msgbox = NULL;
00969 
00970             try {
00971                 msgbox = new YAPET::UI::MessageBox (_ ("E R R O R"), _ ("Wrong password") );
00972                 msgbox->run();
00973                 delete msgbox;
00974             } catch (YAPET::UI::UIException&) {
00975                 if (msgbox != NULL)
00976                     delete msgbox;
00977             }
00978         } else {
00979             delete testkey;
00980             delwin (lockwin);
00981             return;
00982         }
00983 
00984         delete testkey;
00985         delwin (lockwin);
00986     }
00987 }
00988 
00989 void
00990 MainWindow::changePassword() throw (YAPET::UI::UIException) {
00991     if (file == NULL || key == NULL) return;
00992 
00993     // Make sure there are no unsaved entries
00994     if (records_changed) {
00995         YAPET::UI::DialogBox* dialogbox = NULL;
00996 
00997         try {
00998             dialogbox = new YAPET::UI::DialogBox (_ ("Q U E S T I O N"), _ ("Save before changing password?") );
00999             dialogbox->run();
01000             YAPET::UI::ANSWER a = dialogbox->getAnswer();
01001             delete dialogbox;
01002 
01003             if (a == YAPET::UI::ANSWER_OK) {
01004                 saveFile();
01005             } else {
01006                 statusbar.putMsg (_ ("Password change aborted") );
01007                 return;
01008             }
01009         } catch (YAPET::UI::UIException&) {
01010             if (dialogbox != NULL)
01011                 delete dialogbox;
01012 
01013             statusbar.putMsg (_ ("Error showing error message") );
01014             refresh();
01015             return;
01016         }
01017     }
01018 
01019     // Prompt for the new password
01020     PasswordDialog* pwdia = NULL;
01021     YAPET::Key* newkey;
01022 
01023     try {
01024         pwdia = new PasswordDialog (NEW_PW, file->getFilename() );
01025         pwdia->run();
01026         newkey = pwdia->getKey();
01027         delete pwdia;
01028     } catch (YAPET::UI::UIException&) {
01029         if (pwdia != NULL)
01030             delete pwdia;
01031 
01032         statusbar.putMsg (_ ("Error while asking for password") );
01033         return;
01034     }
01035 
01036     // Make sure the key has been generated
01037     if (newkey == NULL) {
01038         statusbar.putMsg (_ ("Password change canceled") );
01039         return;
01040     }
01041 
01042     // Change the password
01043     try {
01044         file->setNewKey (*key, *newkey);
01045     } catch (std::exception& ex) {
01046         delete newkey;
01047         YAPET::UI::MessageBox* msgbox = NULL;
01048 
01049         try {
01050             msgbox = new YAPET::UI::MessageBox (_ ("E R R O R"), ex.what() );
01051             msgbox->run();
01052             delete msgbox;
01053         } catch (YAPET::UI::UIException&) {
01054             if (msgbox != NULL)
01055                 delete msgbox;
01056         }
01057 
01058         return;
01059     }
01060 
01061     delete key;
01062     key = newkey;
01063 
01064     // Read records from file
01065     try {
01066         std::list<YAPET::PartDec> tmp_list = file->read (*key);
01067         recordlist->setList (tmp_list);
01068     } catch (YAPET::YAPETException& e) {
01069         if (file != NULL)
01070             delete file;
01071 
01072         YAPET::UI::MessageBox* msgbox = NULL;
01073 
01074         try {
01075             msgbox = new YAPET::UI::MessageBox (_ ("E R R O R"), e.what() );
01076             msgbox->run();
01077             delete msgbox;
01078         } catch (YAPET::UI::UIException&) {
01079             if (msgbox != NULL)
01080                 delete msgbox;
01081 
01082             statusbar.putMsg (_ ("Error while trying to show error") );
01083         }
01084 
01085         delete key;
01086         key = NULL;
01087         file = NULL;
01088         statusbar.putMsg (_ ("Error reading from file") );
01089         return;
01090     }
01091 
01092     statusbar.putMsg (_ ("Password successfully changed") );
01093 }
01094 
01095 MainWindow::MainWindow (unsigned int timeout,
01096                         bool fsecurity) throw (YAPET::UI::UIException) : BaseWindow(),
01097         toprightwin (NULL),
01098         bottomrightwin (NULL),
01099         recordlist (NULL),
01100         statusbar(),
01101         records_changed (false),
01102         key (NULL),
01103         file (NULL),
01104         locktimeout (timeout),
01105         usefsecurity (fsecurity) {
01106     locktimeout = locktimeout < 10 ? 10 : locktimeout;
01107     createWindow();
01108 }
01109 
01110 MainWindow::~MainWindow() {
01111     delete recordlist;
01112     wclear (toprightwin);
01113     wclear (bottomrightwin);
01114     delwin (toprightwin);
01115     delwin (bottomrightwin);
01116 
01117     if (key != NULL)
01118         delete key;
01119 
01120     if (file != NULL)
01121         delete file;
01122 }
01123 
01124 void
01125 MainWindow::run() throw (YAPET::UI::UIException) {
01126     if (file == NULL || key == NULL)
01127         statusbar.putMsg (_ ("No file loaded") );
01128 
01129     if (file != NULL && key != NULL)
01130         statusbar.putMsg (file->getFilename() + _ (" loaded") );
01131 
01132     refresh();
01133     Alarm alrm (*this);
01134     int ch;
01135 
01136     while (true) {
01137         try {
01138 #if defined(HAVE_SIGACTION) && defined(HAVE_SIGNAL_H)
01139             BaseWindow::setTimeout (&alrm, locktimeout);
01140 #endif // defined(HAVE_SIGACTION) && defined(HAVE_SIGNAL_H)
01141 
01142             while ( (ch = recordlist->focus() ) ) {
01143 #if defined(HAVE_SIGACTION) && defined(HAVE_SIGNAL_H)
01144                 YAPET::UI::BaseWindow::suspendTimeout();
01145 #endif // defined(HAVE_SIGACTION) && defined(HAVE_SIGNAL_H)
01146 
01147                 switch (ch) {
01148                     case '\n':
01149                         editSelectedRecord();
01150                         break;
01151                     case 3: // ^C
01152                     case 'Q':
01153                     case 'q':
01154                         if (quit() ) return;
01155 
01156                         break;
01157 #ifdef HAVE_WRESIZE
01158                     case KEY_RESIZE:
01159                         YAPET::UI::BaseWindow::resizeAll();
01160                         break;
01161 #endif // HAVE_WRESIZE
01162                     case KEY_REFRESH:
01163 #ifdef HAVE_WRESIZE
01164                         YAPET::UI::BaseWindow::resizeAll();
01165 #endif // HAVE_WRESIZE
01166                         YAPET::UI::BaseWindow::refreshAll();
01167                         break;
01168                     case 'S':
01169                     case 's':
01170                         saveFile();
01171                         break;
01172                     case 'R':
01173                     case 'r': {
01174             //
01175             // Check if we have unsaved changes
01176             //
01177             if (records_changed) {
01178                 YAPET::UI::DialogBox* dialogbox = NULL;
01179                 
01180                 try {
01181                 dialogbox = new YAPET::UI::DialogBox (_ ("Q U E S T I O N"), _ ("Save before loading other file?") );
01182                 dialogbox->run();
01183                 YAPET::UI::ANSWER a = dialogbox->getAnswer();
01184                 delete dialogbox;
01185                 // Clear the terminal title
01186                 setTerminalTitle ("");
01187                 
01188                 if (a == YAPET::UI::ANSWER_OK) {
01189                     saveFile();
01190                 } else {
01191                     refresh();
01192                     break;
01193                 }
01194                 
01195                 } catch (YAPET::UI::UIException&) {
01196                 if (dialogbox != NULL)
01197                     delete dialogbox;
01198                 
01199                 statusbar.putMsg (_ ("Error showing error message") );
01200                 refresh();
01201                 break;;
01202                 }
01203             }
01204                         FileOpen* tmp = NULL;
01205 
01206                         try {
01207                             tmp = new FileOpen (_ ("O P E N  F I L E") );
01208                             tmp->run();
01209 
01210                             if (!tmp->isCanceled() ) {
01211                                 openFile (tmp->getFilepath() );
01212                             }
01213 
01214                             delete tmp;
01215                         } catch (std::exception& ex2) {
01216                             statusbar.putMsg (ex2.what() );
01217 
01218                             if (file != NULL)
01219                                 delete file;
01220 
01221                             if (key != NULL)
01222                                 delete key;
01223 
01224                             if (tmp != NULL)
01225                                 delete tmp;
01226 
01227                             file = NULL;
01228                             key = NULL;
01229                         }
01230 
01231                         //::refresh();
01232                         YAPET::UI::BaseWindow::refreshAll();
01233                     }
01234                     break;
01235                     case 'L':
01236                     case 'l':
01237                         lockScreen();
01238                         ::refresh();
01239                         YAPET::UI::BaseWindow::refreshAll();
01240                         break;
01241                     case 'A':
01242                     case 'a':
01243                         addNewRecord();
01244                         break;
01245                     case 'D':
01246                     case 'd':
01247                         deleteSelectedRecord();
01248                         break;
01249                     case 'O':
01250                     case 'o':
01251                         setSortOrder();
01252                         break;
01253                     case '/':
01254                         searchTerm();
01255                         break;
01256                     case 'N':
01257                     case 'n':
01258                         searchNext();
01259                         break;
01260                     case 'c':
01261                     case 'C':
01262                         changePassword();
01263                         ::refresh();
01264                         YAPET::UI::BaseWindow::refreshAll();
01265                         break;
01266 #ifdef ENABLE_PWGEN
01267                     case 'G':
01268                     case 'g': {
01269                         PWGenDialog* tmp = NULL;
01270 
01271                         try {
01272                             tmp = new PWGenDialog ();
01273                             tmp->run();
01274                             delete tmp;
01275                         } catch (std::exception& ex2) {
01276                             statusbar.putMsg (ex2.what() );
01277 
01278                             if (tmp != NULL)
01279                                 delete tmp;
01280                         }
01281 
01282                         YAPET::UI::BaseWindow::refreshAll();
01283                         break;
01284                     }
01285 #endif
01286                 }
01287 
01288                 // Hmm, what's this doing here?? Not sure, I'll leave it...
01289 #if defined(HAVE_SIGACTION) && defined(HAVE_SIGNAL_H)
01290                 YAPET::UI::BaseWindow::setTimeout (&alrm, locktimeout);
01291 #endif // defined(HAVE_SIGACTION) && defined(HAVE_SIGNAL_H)
01292             }
01293         } catch (std::exception& ex) {
01294             statusbar.putMsg (ex.what() );
01295         }
01296     }
01297 }
01298 
01299 void
01300 MainWindow::run (std::string fn) {
01301     if (fn.empty() ) {
01302         run();
01303         return;
01304     }
01305 
01306     refresh();
01307 
01308     try {
01309         openFile (fn);
01310     } catch (std::exception& ex2) {
01311         statusbar.putMsg (ex2.what() );
01312 
01313         if (file != NULL)
01314             delete file;
01315 
01316         if (key != NULL)
01317             delete key;
01318 
01319         file = NULL;
01320         key = NULL;
01321     }
01322 
01323     ::refresh();
01324     run();
01325 }
01326 
01327 #if defined(HAVE_SIGACTION) && defined(HAVE_SIGNAL_H)
01328 void
01329 MainWindow::handle_signal (int signo) {
01330     if (signo == SIGALRM) {
01331         lockScreen();
01332         ::refresh();
01333         YAPET::UI::BaseWindow::refreshAll();
01334     }
01335 }
01336 #endif // defined(HAVE_SIGACTION) && defined(HAVE_SIGNAL_H)

Generated on Sun Sep 19 2010 15:37:14 for YAPET by  doxygen 1.7.1