author | ulf69 <ulf69> | 2004-09-21 19:44:23 (UTC) |
---|---|---|
committer | ulf69 <ulf69> | 2004-09-21 19:44:23 (UTC) |
commit | a6a6544fc57542752fecc3763e0d35e6a38040ac (patch) (side-by-side diff) | |
tree | 3324285a4aaee1db873e0c83d0c8e911cbe1aefb | |
parent | 6a40d65ddd6657e34c69d839da458810a8d8ff98 (diff) | |
download | kdepimpi-a6a6544fc57542752fecc3763e0d35e6a38040ac.zip kdepimpi-a6a6544fc57542752fecc3763e0d35e6a38040ac.tar.gz kdepimpi-a6a6544fc57542752fecc3763e0d35e6a38040ac.tar.bz2 |
*** empty log message ***
-rw-r--r-- | pwmanager/pwmanager/configwnd.cpp | 11 | ||||
-rw-r--r-- | pwmanager/pwmanager/pwm.cpp | 35 | ||||
-rw-r--r-- | pwmanager/pwmanager/pwmanagerE.pro | 27 | ||||
-rw-r--r-- | pwmanager/pwmanager/pwmdoc.cpp | 2 | ||||
-rw-r--r-- | pwmanager/pwmanager/pwmdoc.h | 2 | ||||
-rw-r--r-- | pwmanager/pwmanager/pwmdocui.cpp | 1 | ||||
-rw-r--r-- | pwmanager/pwmanager/pwminit.cpp | 19 | ||||
-rw-r--r-- | pwmanager/pwmanager/pwmtray.cpp | 4 | ||||
-rw-r--r-- | pwmanager/pwmanager/pwmview.cpp | 4 | ||||
-rw-r--r-- | pwmanager/pwmanager/serializer.cpp | 1 |
10 files changed, 83 insertions, 23 deletions
diff --git a/pwmanager/pwmanager/configwnd.cpp b/pwmanager/pwmanager/configwnd.cpp index 230ca1b..108c40f 100644 --- a/pwmanager/pwmanager/configwnd.cpp +++ b/pwmanager/pwmanager/configwnd.cpp @@ -1,264 +1,265 @@ /**************************************************************************** ** Form implementation generated from reading ui file 'configwnd.ui' ** ** Created: Tue Sep 14 15:20:58 2004 ** by: The User Interface Compiler ($Id$) ** ** WARNING! All changes made in this file will be lost! ****************************************************************************/ #include "configwnd.h" #include <qvariant.h> #include <qpushbutton.h> #include <qtabwidget.h> #include <qwidget.h> #include <qcombobox.h> #include <qlabel.h> #include <qlineedit.h> #include <qcheckbox.h> #include <qspinbox.h> #include <qlayout.h> #include <qtooltip.h> #include <qwhatsthis.h> /* * Constructs a configWnd as a child of 'parent', with the * name 'name' and widget flags set to 'f'. * * The dialog will by default be modeless, unless you set 'modal' to * TRUE to construct a modal dialog. */ configWnd::configWnd( QWidget* parent, const char* name, bool modal, WFlags fl ) : QDialog( parent, name, modal, fl ) { if ( !name ) setName( "configWnd" ); okButton = new QPushButton( this, "okButton" ); okButton->setGeometry( QRect( 10, 280, 107, 27 ) ); cancelButton = new QPushButton( this, "cancelButton" ); cancelButton->setGeometry( QRect( 370, 280, 107, 27 ) ); tabWidget2 = new QTabWidget( this, "tabWidget2" ); tabWidget2->setGeometry( QRect( 10, 10, 470, 260 ) ); + ////////////////////////////// tab = new QWidget( tabWidget2, "tab" ); windowStyleComboBox = new QComboBox( FALSE, tab, "windowStyleComboBox" ); windowStyleComboBox->setGeometry( QRect( 220, 180, 210, 28 ) ); textLabel1_5 = new QLabel( tab, "textLabel1_5" ); textLabel1_5->setGeometry( QRect( 30, 180, 180, 20 ) ); textLabel1_5->setAlignment( int( QLabel::AlignVCenter | QLabel::AlignRight ) ); textLabel1_4 = new QLabel( tab, "textLabel1_4" ); textLabel1_4->setGeometry( QRect( 30, 40, 400, 20 ) ); selEntrFontButton = new QPushButton( tab, "selEntrFontButton" ); selEntrFontButton->setGeometry( QRect( 30, 90, 160, 27 ) ); currEntrFont = new QLabel( tab, "currEntrFont" ); currEntrFont->setGeometry( QRect( 30, 70, 230, 20 ) ); tabWidget2->insertTab( tab, QString("") ); - + ////////////////////////////////////// TabPage = new QWidget( tabWidget2, "TabPage" ); compressionComboBox = new QComboBox( FALSE, TabPage, "compressionComboBox" ); compressionComboBox->setGeometry( QRect( 290, 50, 150, 28 ) ); textLabel1_6 = new QLabel( TabPage, "textLabel1_6" ); textLabel1_6->setGeometry( QRect( 10, 50, 270, 20 ) ); textLabel1_6->setAlignment( int( QLabel::AlignVCenter | QLabel::AlignRight ) ); textLabel1_8 = new QLabel( TabPage, "textLabel1_8" ); textLabel1_8->setGeometry( QRect( 10, 90, 270, 20 ) ); textLabel1_8->setAlignment( int( QLabel::AlignVCenter | QLabel::AlignRight ) ); permissionLineEdit = new QLineEdit( TabPage, "permissionLineEdit" ); permissionLineEdit->setGeometry( QRect( 290, 90, 142, 27 ) ); permissionLineEdit->setMaxLength( 3 ); fileBackupCheckBox = new QCheckBox( TabPage, "fileBackupCheckBox" ); fileBackupCheckBox->setGeometry( QRect( 80, 140, 360, 23 ) ); tabWidget2->insertTab( TabPage, QString("") ); - + ////////////////////////////////////// tab_2 = new QWidget( tabWidget2, "tab_2" ); pwTimeoutSpinBox = new QSpinBox( tab_2, "pwTimeoutSpinBox" ); pwTimeoutSpinBox->setGeometry( QRect( 390, 50, 55, 23 ) ); textLabel1 = new QLabel( tab_2, "textLabel1" ); textLabel1->setGeometry( QRect( 10, 20, 370, 80 ) ); textLabel1->setAlignment( int( QLabel::WordBreak | QLabel::AlignVCenter ) ); textLabel1_7 = new QLabel( tab_2, "textLabel1_7" ); textLabel1_7->setGeometry( QRect( 10, 110, 370, 80 ) ); textLabel1_7->setAlignment( int( QLabel::WordBreak | QLabel::AlignVCenter ) ); lockTimeoutSpinBox = new QSpinBox( tab_2, "lockTimeoutSpinBox" ); lockTimeoutSpinBox->setGeometry( QRect( 390, 140, 55, 23 ) ); autoDeepLockCheckBox = new QCheckBox( tab_2, "autoDeepLockCheckBox" ); autoDeepLockCheckBox->setGeometry( QRect( 60, 180, 380, 25 ) ); tabWidget2->insertTab( tab_2, QString("") ); - + /////////////////////////////////////////// tab_3 = new QWidget( tabWidget2, "tab_3" ); textLabel1_3 = new QLabel( tab_3, "textLabel1_3" ); textLabel1_3->setGeometry( QRect( 30, 30, 400, 20 ) ); autoStartLineEdit = new QLineEdit( tab_3, "autoStartLineEdit" ); autoStartLineEdit->setGeometry( QRect( 30, 50, 360, 20 ) ); browseAutoStButton = new QPushButton( tab_3, "browseAutoStButton" ); browseAutoStButton->setGeometry( QRect( 400, 50, 30, 20 ) ); autostartDeeplockedCheckBox = new QCheckBox( tab_3, "autostartDeeplockedCheckBox" ); autostartDeeplockedCheckBox->setGeometry( QRect( 40, 80, 390, 25 ) ); tabWidget2->insertTab( tab_3, QString("") ); - + //////////////////////////////////////////// tab_4 = new QWidget( tabWidget2, "tab_4" ); textLabel2 = new QLabel( tab_4, "textLabel2" ); textLabel2->setGeometry( QRect( 20, 40, 280, 20 ) ); textLabel2->setAlignment( int( QLabel::AlignVCenter | QLabel::AlignRight ) ); browserLineEdit = new QLineEdit( tab_4, "browserLineEdit" ); browserLineEdit->setGeometry( QRect( 310, 40, 130, 27 ) ); xtermLineEdit = new QLineEdit( tab_4, "xtermLineEdit" ); xtermLineEdit->setGeometry( QRect( 310, 100, 130, 27 ) ); textLabel3 = new QLabel( tab_4, "textLabel3" ); textLabel3->setGeometry( QRect( 20, 100, 280, 20 ) ); textLabel3->setAlignment( int( QLabel::AlignVCenter | QLabel::AlignRight ) ); tabWidget2->insertTab( tab_4, QString("") ); - + /////////////////////////////////////////////// tab_5 = new QWidget( tabWidget2, "tab_5" ); trayCheckBox = new QCheckBox( tab_5, "trayCheckBox" ); trayCheckBox->setGeometry( QRect( 30, 30, 400, 20 ) ); openUnlockedCheckBox = new QCheckBox( tab_5, "openUnlockedCheckBox" ); openUnlockedCheckBox->setGeometry( QRect( 30, 80, 400, 20 ) ); autoMinimizeCheckBox = new QCheckBox( tab_5, "autoMinimizeCheckBox" ); autoMinimizeCheckBox->setEnabled( FALSE ); autoMinimizeCheckBox->setGeometry( QRect( 50, 50, 380, 25 ) ); minimizeLockComboBox = new QComboBox( FALSE, tab_5, "minimizeLockComboBox" ); minimizeLockComboBox->setGeometry( QRect( 310, 170, 120, 27 ) ); textLabel1_9 = new QLabel( tab_5, "textLabel1_9" ); textLabel1_9->setGeometry( QRect( 30, 180, 270, 20 ) ); textLabel1_9->setAlignment( int( QLabel::AlignVCenter | QLabel::AlignRight ) ); kwalletEmuCheckBox = new QCheckBox( tab_5, "kwalletEmuCheckBox" ); kwalletEmuCheckBox->setGeometry( QRect( 30, 110, 400, 25 ) ); wndCloseCheckBox = new QCheckBox( tab_5, "wndCloseCheckBox" ); wndCloseCheckBox->setGeometry( QRect( 30, 140, 430, 24 ) ); tabWidget2->insertTab( tab_5, QString("") ); languageChange(); resize( QSize(490, 318).expandedTo(minimumSizeHint()) ); clearWState( WState_Polished ); // signals and slots connections connect( okButton, SIGNAL( clicked() ), this, SLOT( okButton_slot() ) ); connect( cancelButton, SIGNAL( clicked() ), this, SLOT( cancelButton_slot() ) ); connect( browseAutoStButton, SIGNAL( clicked() ), this, SLOT( browseAutoStButton_slot() ) ); connect( selEntrFontButton, SIGNAL( clicked() ), this, SLOT( selEntrFontButton_slot() ) ); connect( trayCheckBox, SIGNAL( toggled(bool) ), autoMinimizeCheckBox, SLOT( setEnabled(bool) ) ); // tab order setTabOrder( pwTimeoutSpinBox, trayCheckBox ); setTabOrder( trayCheckBox, okButton ); setTabOrder( okButton, cancelButton ); } /* * Destroys the object and frees any allocated resources */ configWnd::~configWnd() { // no need to delete child widgets, Qt does it all for us } /* * Sets the strings of the subwidgets using the current * language. */ void configWnd::languageChange() { setCaption( tr( "PwManager Configuration" ) ); okButton->setText( tr( "&OK" ) ); //US ENH okButton->setAccel( QKeySequence( tr( "Alt+O" ) ) ); cancelButton->setText( tr( "&Cancel" ) ); //US ENH cancelButton->setAccel( QKeySequence( tr( "Alt+C" ) ) ); windowStyleComboBox->clear(); windowStyleComboBox->insertItem( tr( "Category on top" ) ); windowStyleComboBox->insertItem( tr( "Category-list left" ) ); textLabel1_5->setText( tr( "Window-style:" ) ); textLabel1_4->setText( tr( "Font for the password entries:" ) ); selEntrFontButton->setText( tr( "select Font" ) ); currEntrFont->setText( QString::null ); tabWidget2->changeTab( tab, tr( "Look && feel" ) ); compressionComboBox->clear(); compressionComboBox->insertItem( tr( "none" ) ); compressionComboBox->insertItem( tr( "gzip" ) ); compressionComboBox->insertItem( tr( "bzip2" ) ); textLabel1_6->setText( tr( "*.pwm file compression:" ) ); textLabel1_8->setText( tr( "permissions:" ) ); fileBackupCheckBox->setText( tr( "Make file backup before saving" ) ); tabWidget2->changeTab( TabPage, tr( "File" ) ); textLabel1->setText( tr( "Password timeout (timeout to hold password in memory, so you don't have to re-enter it, if you already have entered it) [set to 0 to disable]:" ) ); textLabel1_7->setText( tr( "Auto-lock timeout (auto lock document after this amount of seconds) [set to 0 to disable]:" ) ); autoDeepLockCheckBox->setText( tr( "deep-lock on autolock" ) ); tabWidget2->changeTab( tab_2, tr( "Timeout" ) ); textLabel1_3->setText( tr( "Open this file automatically on startup:" ) ); browseAutoStButton->setText( tr( "..." ) ); autostartDeeplockedCheckBox->setText( tr( "open deeplocked" ) ); tabWidget2->changeTab( tab_3, tr( "Autostart" ) ); textLabel2->setText( tr( "Favourite browser:" ) ); textLabel3->setText( tr( "Favourite X-terminal:" ) ); tabWidget2->changeTab( tab_4, tr( "External apps" ) ); trayCheckBox->setText( tr( "Show icon in system-tray" ) ); openUnlockedCheckBox->setText( tr( "Open document with passwords unlocked" ) ); autoMinimizeCheckBox->setText( tr( "auto-minimize to tray on startup" ) ); minimizeLockComboBox->clear(); minimizeLockComboBox->insertItem( tr( "don't lock" ) ); minimizeLockComboBox->insertItem( tr( "normal lock" ) ); minimizeLockComboBox->insertItem( tr( "deep-lock" ) ); textLabel1_9->setText( tr( "auto-lock on minimize:" ) ); kwalletEmuCheckBox->setText( tr( "KWallet emulation" ) ); wndCloseCheckBox->setText( tr( "Do not minimize windows into tray. (Close the window)" ) ); tabWidget2->changeTab( tab_5, tr( "Miscellaneous" ) ); } void configWnd::okButton_slot() { qWarning( "configWnd::okButton_slot(): Not implemented yet" ); } void configWnd::cancelButton_slot() { qWarning( "configWnd::cancelButton_slot(): Not implemented yet" ); } void configWnd::browseBgButton_slot() { qWarning( "configWnd::browseBgButton_slot(): Not implemented yet" ); } void configWnd::browseAutoStButton_slot() { qWarning( "configWnd::browseAutoStButton_slot(): Not implemented yet" ); } void configWnd::selEntrFontButton_slot() { qWarning( "configWnd::selEntrFontButton_slot(): Not implemented yet" ); } diff --git a/pwmanager/pwmanager/pwm.cpp b/pwmanager/pwmanager/pwm.cpp index e5579f8..08fcb25 100644 --- a/pwmanager/pwmanager/pwm.cpp +++ b/pwmanager/pwmanager/pwm.cpp @@ -1,1283 +1,1304 @@ /*************************************************************************** * * * copyright (C) 2003, 2004 by Michael Buesch * * email: mbuesch@freenet.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License version 2 * * as published by the Free Software Foundation. * * * ***************************************************************************/ /*************************************************************************** * copyright (C) 2004 by Ulf Schenk * This file is originaly based on version 1.0.1 of pwmanager * and was modified to run on embedded devices that run microkde * * $Id$ **************************************************************************/ #include <klocale.h> #include <klistview.h> #include <ktoolbar.h> #include <kfiledialog.h> #include <kiconloader.h> #include <kmessagebox.h> #ifndef PWM_EMBEDDED #include <kmenubar.h> #include <kstatusbar.h> #include <dcopclient.h> +#include "configwndimpl.h" +#include "configuration.h" #else #include <qmenubar.h> #include <qmessagebox.h> +#include <pwmprefs.h> +#include <kpimglobalprefs.h> +#include <kcmconfigs/kcmpwmconfig.h> +#include <kcmconfigs/kcmkdepimconfig.h> +#include <kcmultidialog.h> #endif #include <qpixmap.h> #include <qcheckbox.h> #include <qspinbox.h> #include <qlineedit.h> #include <qfileinfo.h> #include <qclipboard.h> #include <stdio.h> #include "pwm.h" #include "pwminit.h" -#include "configwndimpl.h" #include "pwmprint.h" #include "addentrywndimpl.h" #include "globalstuff.h" #include "findwndimpl.h" -#include "configuration.h" #ifdef CONFIG_KWALLETIF # include "kwalletif.h" # include "kwalletemu.h" #endif #ifdef CONFIG_KEYCARD # include "pwmkeycard.h" #endif #define DEFAULT_SIZE (QSize(700, 400)) // Button IDs for "file" popup menu enum { BUTTON_POPUP_FILE_NEW = 0, BUTTON_POPUP_FILE_OPEN, BUTTON_POPUP_FILE_CLOSE, BUTTON_POPUP_FILE_SAVE, BUTTON_POPUP_FILE_SAVEAS, BUTTON_POPUP_FILE_EXPORT, BUTTON_POPUP_FILE_IMPORT, BUTTON_POPUP_FILE_PRINT, BUTTON_POPUP_FILE_QUIT }; // Button IDs for "manage" popup menu enum { BUTTON_POPUP_MANAGE_ADD = 0, BUTTON_POPUP_MANAGE_EDIT, BUTTON_POPUP_MANAGE_DEL, BUTTON_POPUP_MANAGE_CHANGEMP }; // Button IDs for chipcard popup menu enum { #ifdef CONFIG_KEYCARD BUTTON_POPUP_CHIPCARD_GENNEW = 0, BUTTON_POPUP_CHIPCARD_DEL, BUTTON_POPUP_CHIPCARD_READID, BUTTON_POPUP_CHIPCARD_SAVEBACKUP, BUTTON_POPUP_CHIPCARD_REPLAYBACKUP #else // CONFIG_KEYCARD BUTTON_POPUP_CHIPCARD_NO = 0 #endif // CONFIG_KEYCARD }; // Button IDs for "view" popup menu enum { BUTTON_POPUP_VIEW_FIND = 0, BUTTON_POPUP_VIEW_LOCK, BUTTON_POPUP_VIEW_DEEPLOCK, BUTTON_POPUP_VIEW_UNLOCK }; // Button IDs for "options" popup menu enum { BUTTON_POPUP_OPTIONS_CONFIG = 0 }; // Button IDs for "export" popup menu (in "file" popup menu) enum { BUTTON_POPUP_EXPORT_TEXT = 0, BUTTON_POPUP_EXPORT_GPASMAN #ifdef CONFIG_KWALLETIF ,BUTTON_POPUP_EXPORT_KWALLET #endif }; // Button IDs for "import" popup menu (in "file" popup menu) enum { BUTTON_POPUP_IMPORT_TEXT = 0, BUTTON_POPUP_IMPORT_GPASMAN #ifdef CONFIG_KWALLETIF ,BUTTON_POPUP_IMPORT_KWALLET #endif }; #ifdef PWM_EMBEDDED // Button IDs for "help" popup menu enum { BUTTON_POPUP_HELP_LICENSE = 0, BUTTON_POPUP_HELP_FAQ, BUTTON_POPUP_HELP_ABOUT }; #endif // Button IDs for toolbar enum { BUTTON_TOOL_NEW = 0, BUTTON_TOOL_OPEN, BUTTON_TOOL_SAVE, BUTTON_TOOL_SAVEAS, BUTTON_TOOL_PRINT, BUTTON_TOOL_ADD, BUTTON_TOOL_EDIT, BUTTON_TOOL_DEL, BUTTON_TOOL_FIND, BUTTON_TOOL_LOCK, BUTTON_TOOL_DEEPLOCK, BUTTON_TOOL_UNLOCK }; PwM::PwM(PwMInit *_init, PwMDoc *doc, bool virginity, QWidget *parent, const char *name) : KMainWindow(parent, name) , forceQuit (false) , forceMinimizeToTray (false) { init = _init; connect(doc, SIGNAL(docClosed(PwMDoc *)), this, SLOT(docClosed(PwMDoc *))); initMenubar(); initToolbar(); initMetrics(); setVirgin(virginity); setFocusPolicy(QWidget::WheelFocus); #ifndef PWM_EMBEDDED statusBar()->show(); #endif view = makeNewListView(doc); setCentralWidget(view); updateCaption(); showStatMsg(i18n("Ready.")); } PwM::~PwM() { disconnect(curDoc(), SIGNAL(docClosed(PwMDoc *)), this, SLOT(docClosed(PwMDoc *))); conf()->confWndMainWndSize(size()); emit closed(this); delete view; } void PwM::initMenubar() { KIconLoader* picons; #ifndef PWM_EMBEDDED KIconLoader icons; picons = &icons; #else picons = KGlobal::iconLoader(); #endif filePopup = new KPopupMenu(this); importPopup = new KPopupMenu(filePopup); exportPopup = new KPopupMenu(filePopup); managePopup = new KPopupMenu(this); #ifdef CONFIG_KEYCARD chipcardPopup = new KPopupMenu(this); #endif // CONFIG_KEYCARD viewPopup = new KPopupMenu(this); optionsPopup = new KPopupMenu(this); // "file" popup menu filePopup->insertItem(QIconSet(picons->loadIcon("filenew", KIcon::Small)), i18n("&New"), this, SLOT(new_slot()), 0, BUTTON_POPUP_FILE_NEW); filePopup->insertItem(QIconSet(picons->loadIcon("fileopen", KIcon::Small)), i18n("&Open"), this, SLOT(open_slot()), 0, BUTTON_POPUP_FILE_OPEN); filePopup->insertItem(QIconSet(picons->loadIcon("fileclose", KIcon::Small)), i18n("&Close"), this, SLOT(close_slot()), 0, BUTTON_POPUP_FILE_CLOSE); filePopup->insertSeparator(); filePopup->insertItem(QIconSet(picons->loadIcon("filesave", KIcon::Small)), i18n("&Save"), this, SLOT(save_slot()), 0, BUTTON_POPUP_FILE_SAVE); filePopup->insertItem(QIconSet(picons->loadIcon("filesaveas", KIcon::Small)), i18n("Save &as..."), this, SLOT(saveAs_slot()), 0, BUTTON_POPUP_FILE_SAVEAS); filePopup->insertSeparator(); // "file/export" popup menu exportPopup->insertItem(i18n("&Text-file..."), this, SLOT(exportToText()), 0, BUTTON_POPUP_EXPORT_TEXT); exportPopup->insertItem(i18n("&Gpasman / Kpasman ..."), this, SLOT(exportToGpasman()), 0, BUTTON_POPUP_EXPORT_GPASMAN); #ifdef CONFIG_KWALLETIF exportPopup->insertItem(i18n("&KWallet..."), this, SLOT(exportToKWallet()), 0, BUTTON_POPUP_EXPORT_KWALLET); #endif filePopup->insertItem(QIconSet(picons->loadIcon("fileexport", KIcon::Small)), i18n("E&xport"), exportPopup, BUTTON_POPUP_FILE_EXPORT); // "file/import" popup menu importPopup->insertItem(i18n("&Text-file..."), this, SLOT(importFromText()), 0, BUTTON_POPUP_IMPORT_TEXT); importPopup->insertItem(i18n("&Gpasman / Kpasman ..."), this, SLOT(importFromGpasman()), 0, BUTTON_POPUP_IMPORT_GPASMAN); #ifdef CONFIG_KWALLETIF importPopup->insertItem(i18n("&KWallet..."), this, SLOT(importKWallet()), 0, BUTTON_POPUP_IMPORT_KWALLET); #endif filePopup->insertItem(QIconSet(picons->loadIcon("fileimport", KIcon::Small)), i18n("I&mport"), importPopup, BUTTON_POPUP_FILE_IMPORT); filePopup->insertSeparator(); filePopup->insertItem(QIconSet(picons->loadIcon("fileprint", KIcon::Small)), i18n("&Print..."), this, SLOT(print_slot()), 0, BUTTON_POPUP_FILE_PRINT); filePopup->insertSeparator(); filePopup->insertItem(QIconSet(picons->loadIcon("exit", KIcon::Small)), i18n("&Quit"), this, SLOT(quitButton_slot()), 0, BUTTON_POPUP_FILE_QUIT); menuBar()->insertItem(i18n("&File"), filePopup); // "manage" popup menu managePopup->insertItem(QIconSet(picons->loadIcon("pencil", KIcon::Small)), i18n("&Add password"), this, SLOT(addPwd_slot()), 0, BUTTON_POPUP_MANAGE_ADD); managePopup->insertItem(QIconSet(picons->loadIcon("edit", KIcon::Small)), i18n("&Edit"), this, SLOT(editPwd_slot()), 0, BUTTON_POPUP_MANAGE_EDIT); managePopup->insertItem(QIconSet(picons->loadIcon("editdelete", KIcon::Small)), i18n("&Delete"), this, SLOT(deletePwd_slot()), 0, BUTTON_POPUP_MANAGE_DEL); managePopup->insertSeparator(); managePopup->insertItem(QIconSet(picons->loadIcon("rotate", KIcon::Small)), i18n("Change &Master Password"), this, SLOT(changeMasterPwd_slot()), 0, BUTTON_POPUP_MANAGE_CHANGEMP); menuBar()->insertItem(i18n("&Manage"), managePopup); // "chipcard" popup menu #ifdef CONFIG_KEYCARD chipcardPopup->insertItem(QIconSet(picons->loadIcon("filenew", KIcon::Small)), i18n("&Generate new key-card"), this, SLOT(genNewCard_slot()), 0, BUTTON_POPUP_CHIPCARD_GENNEW); chipcardPopup->insertItem(QIconSet(picons->loadIcon("editdelete", KIcon::Small)), i18n("&Erase key-card"), this, SLOT(eraseCard_slot()), 0, BUTTON_POPUP_CHIPCARD_DEL); chipcardPopup->insertItem(QIconSet(picons->loadIcon("", KIcon::Small)), i18n("Read card-&ID"), this, SLOT(readCardId_slot()), 0, BUTTON_POPUP_CHIPCARD_READID); chipcardPopup->insertSeparator(); chipcardPopup->insertItem(QIconSet(picons->loadIcon("2rightarrow", KIcon::Small)), i18n("&Make card backup-image"), this, SLOT(makeCardBackup_slot()), 0, BUTTON_POPUP_CHIPCARD_SAVEBACKUP); chipcardPopup->insertItem(QIconSet(picons->loadIcon("2leftarrow", KIcon::Small)), i18n("&Replay card backup-image"), this, SLOT(replayCardBackup_slot()), 0, BUTTON_POPUP_CHIPCARD_REPLAYBACKUP); menuBar()->insertItem(i18n("&Chipcard manager"), chipcardPopup); #endif // CONFIG_KEYCARD // "view" popup menu viewPopup->insertItem(QIconSet(picons->loadIcon("find", KIcon::Small)), i18n("&Find"), this, SLOT(find_slot()), 0, BUTTON_POPUP_VIEW_FIND); viewPopup->insertSeparator(); viewPopup->insertItem(QIconSet(picons->loadIcon("halfencrypted", KIcon::Small)), i18n("&Lock all entries"), this, SLOT(lockWnd_slot()), 0, BUTTON_POPUP_VIEW_LOCK); viewPopup->insertItem(QIconSet(picons->loadIcon("encrypted", KIcon::Small)), i18n("&Deep-lock all entries"), this, SLOT(deepLockWnd_slot()), 0, BUTTON_POPUP_VIEW_DEEPLOCK); viewPopup->insertItem(QIconSet(picons->loadIcon("decrypted", KIcon::Small)), i18n("&Unlock all entries"), this, SLOT(unlockWnd_slot()), 0, BUTTON_POPUP_VIEW_UNLOCK); menuBar()->insertItem(i18n("&View"), viewPopup); // "options" popup menu optionsPopup->insertItem(QIconSet(picons->loadIcon("configure", KIcon::Small)), i18n("&Configure..."), this, SLOT(config_slot()), BUTTON_POPUP_OPTIONS_CONFIG); menuBar()->insertItem(i18n("&Options"), optionsPopup); // "help" popup menu #ifndef PWM_EMBEDDED helpPopup = helpMenu(QString::null, false); #else helpPopup = new KPopupMenu(this); helpPopup->insertItem(i18n("&License"), this, SLOT(showLicense_slot()), 0, BUTTON_POPUP_HELP_LICENSE); helpPopup->insertItem(i18n("&Faq"), this, SLOT(faq_slot()), 0, BUTTON_POPUP_HELP_FAQ); helpPopup->insertItem(i18n("&About PwManager"), this, SLOT(createAboutData_slot()), 0, BUTTON_POPUP_HELP_ABOUT); #endif menuBar()->insertItem(i18n("&Help"), helpPopup); } void PwM::initToolbar() { KIconLoader* picons; #ifndef PWM_EMBEDDED KIconLoader icons; picons = &icons; #else picons = KGlobal::iconLoader(); #endif toolBar()->insertButton(picons->loadIcon("filenew", KIcon::Toolbar), BUTTON_TOOL_NEW, SIGNAL(clicked(int)), this, SLOT(new_slot()), true, i18n("New")); toolBar()->insertButton(picons->loadIcon("fileopen", KIcon::Toolbar), BUTTON_TOOL_OPEN, SIGNAL(clicked(int)), this, SLOT(open_slot()), true, i18n("Open")); toolBar()->insertSeparator(); toolBar()->insertButton(picons->loadIcon("filesave", KIcon::Toolbar), BUTTON_TOOL_SAVE, SIGNAL(clicked(int)), this, SLOT(save_slot()), true, i18n("Save")); toolBar()->insertButton(picons->loadIcon("filesaveas", KIcon::Toolbar), BUTTON_TOOL_SAVEAS, SIGNAL(clicked(int)), this, SLOT(saveAs_slot()), true, i18n("Save as")); toolBar()->insertButton(picons->loadIcon("fileprint", KIcon::Toolbar), BUTTON_TOOL_PRINT, SIGNAL(clicked(int)), this, SLOT(print_slot()), true, i18n("Print...")); toolBar()->insertSeparator(); toolBar()->insertButton(picons->loadIcon("pencil", KIcon::Toolbar), BUTTON_TOOL_ADD, SIGNAL(clicked(int)), this, SLOT(addPwd_slot()), true, i18n("Add password")); toolBar()->insertButton(picons->loadIcon("edit", KIcon::Toolbar), BUTTON_TOOL_EDIT, SIGNAL(clicked(int)), this, SLOT(editPwd_slot()), true, i18n("Edit password")); toolBar()->insertButton(picons->loadIcon("editdelete", KIcon::Toolbar), BUTTON_TOOL_DEL, SIGNAL(clicked(int)), this, SLOT(deletePwd_slot()), true, i18n("Delete password")); toolBar()->insertSeparator(); toolBar()->insertButton(picons->loadIcon("find", KIcon::Toolbar), BUTTON_TOOL_FIND, SIGNAL(clicked(int)), this, SLOT(find_slot()), true, i18n("Find entry")); toolBar()->insertSeparator(); toolBar()->insertButton(picons->loadIcon("halfencrypted", KIcon::Toolbar), BUTTON_TOOL_LOCK, SIGNAL(clicked(int)), this, SLOT(lockWnd_slot()), true, i18n("Lock all entries")); toolBar()->insertButton(picons->loadIcon("encrypted", KIcon::Toolbar), BUTTON_TOOL_DEEPLOCK, SIGNAL(clicked(int)), this, SLOT(deepLockWnd_slot()), true, i18n("Deep-Lock all entries")); toolBar()->insertButton(picons->loadIcon("decrypted", KIcon::Toolbar), BUTTON_TOOL_UNLOCK, SIGNAL(clicked(int)), this, SLOT(unlockWnd_slot()), true, i18n("Unlock all entries")); } void PwM::initMetrics() { QSize s = conf()->confWndMainWndSize(); if (s.isValid()) resize(s); else resize(DEFAULT_SIZE); } void PwM::updateCaption() { setPlainCaption(curDoc()->getTitle() + " - " PROG_NAME " " PACKAGE_VER); } void PwM::hideEvent(QHideEvent *) { if (isMinimized()) { if (init->tray()) { forceMinimizeToTray = true; close(); } int mmlock = conf()->confGlobMinimizeLock(); switch (mmlock) { case 0: // don't lock anything break; case 1: { // normal lock curDoc()->lockAll(true); break; } case 2: { // deep-lock curDoc()->deepLock(); break; } default: WARN(); } } } void PwM::setVirgin(bool v) { if (virgin == v) return; virgin = v; filePopup->setItemEnabled(BUTTON_POPUP_FILE_SAVE, !v); filePopup->setItemEnabled(BUTTON_POPUP_FILE_SAVEAS, !v); filePopup->setItemEnabled(BUTTON_POPUP_FILE_EXPORT, !v); filePopup->setItemEnabled(BUTTON_POPUP_FILE_PRINT, !v); managePopup->setItemEnabled(BUTTON_POPUP_MANAGE_EDIT, !v); managePopup->setItemEnabled(BUTTON_POPUP_MANAGE_DEL, !v); managePopup->setItemEnabled(BUTTON_POPUP_MANAGE_CHANGEMP, !v); viewPopup->setItemEnabled(BUTTON_POPUP_VIEW_LOCK, !v); viewPopup->setItemEnabled(BUTTON_POPUP_VIEW_DEEPLOCK, !v); viewPopup->setItemEnabled(BUTTON_POPUP_VIEW_UNLOCK, !v); viewPopup->setItemEnabled(BUTTON_POPUP_VIEW_FIND, !v); toolBar()->setItemEnabled(BUTTON_TOOL_SAVE, !v); toolBar()->setItemEnabled(BUTTON_TOOL_SAVEAS, !v); toolBar()->setItemEnabled(BUTTON_TOOL_PRINT, !v); toolBar()->setItemEnabled(BUTTON_TOOL_EDIT, !v); toolBar()->setItemEnabled(BUTTON_TOOL_DEL, !v); toolBar()->setItemEnabled(BUTTON_TOOL_LOCK, !v); toolBar()->setItemEnabled(BUTTON_TOOL_DEEPLOCK, !v); toolBar()->setItemEnabled(BUTTON_TOOL_UNLOCK, !v); toolBar()->setItemEnabled(BUTTON_TOOL_FIND, !v); } void PwM::new_slot() { init->createMainWnd(); } //US ENH void PwM::open_slot() { open_slot(""); } void PwM::open_slot(QString fn) { openDoc(fn); } PwMDoc * PwM::openDoc(QString filename, bool openDeepLocked) { if (!isVirgin()) { // open the document in a new window. PwM *newInstance = init->createMainWnd(); PwMDoc *newDoc = newInstance->openDoc(filename, openDeepLocked); if (!newDoc) { newInstance->setForceQuit(true); delete_and_null(newInstance); } return newDoc; } if (!curDoc()->openDocUi(curDoc(), filename, openDeepLocked)) return 0; showStatMsg(i18n("Successfully opened file.")); updateCaption(); setVirgin(false); return curDoc(); } PwMView * PwM::makeNewListView(PwMDoc *doc) { PwMView *ret = new PwMView(this, this, doc); ret->setFont(conf()->confGlobEntryFont()); ret->show(); return ret; } void PwM::close_slot() { close(); } void PwM::quitButton_slot() { init->shutdownApp(0); } void PwM::save_slot() { save(); } bool PwM::save() { if (!curDoc()->saveDocUi(curDoc())) return false; showStatMsg(i18n("Successfully saved data.")); updateCaption(); return true; } void PwM::saveAs_slot() { saveAs(); } bool PwM::saveAs() { if (!curDoc()->saveAsDocUi(curDoc())) return false; showStatMsg(i18n("Successfully saved data.")); updateCaption(); return true; } //US ENH : changed code to run with older MOC void PwM::addPwd_slot() { addPwd_slot(0, 0); } void PwM::addPwd_slot(QString *pw, PwMDoc *_doc) { PwMDoc *doc; if (_doc) { doc = _doc; } else { doc = curDoc(); } PWM_ASSERT(doc); doc->timer()->getLock(DocTimer::id_autoLockTimer); AddEntryWndImpl w; vector<string> catList; doc->getCategoryList(&catList); unsigned i, size = catList.size(); for (i = 0; i < size; ++i) { w.addCategory(catList[i].c_str()); } w.setCurrCategory(view->getCurrentCategory()); if (pw) w.pwLineEdit->setText(*pw); tryAgain: if (w.exec() == 1) { PwMDataItem d; d.desc = w.getDescription().latin1(); d.name = w.getUsername().latin1(); d.pw = w.getPassword().latin1(); d.comment = w.getComment().latin1(); d.url = w.getUrl().latin1(); d.launcher = w.getLauncher().latin1(); PwMerror ret = doc->addEntry(w.getCategory(), &d); if (ret == e_entryExists) { KMessageBox::error(this, i18n ("An entry with this \"Description\", " "does already exist.\n" "Please select another description."), i18n("entry already exists.")); goto tryAgain; } else if (ret == e_maxAllowedEntr) { KMessageBox::error(this, i18n("The maximum possible number of entries " "has been reached. You can't add more entries."), i18n("maximum number of entries")); doc->timer()->putLock(DocTimer::id_autoLockTimer); return; } } setVirgin(false); doc->timer()->putLock(DocTimer::id_autoLockTimer); } //US ENH : changed code to run with older MOC void PwM::editPwd_slot() { editPwd_slot(0,0,0); } void PwM::editPwd_slot(const QString *category) { editPwd_slot(category, 0, 0); } void PwM::editPwd_slot(const QString *category, const int *index, PwMDoc *_doc) { PwMDoc *doc; if (_doc) { doc = _doc; } else { doc = curDoc(); } PWM_ASSERT(doc); if (doc->isDocEmpty()) return; if (doc->isDeepLocked()) return; doc->timer()->getLock(DocTimer::id_autoLockTimer); unsigned int curEntryIndex; if (index) { curEntryIndex = *index; } else { if (!(view->getCurEntryIndex(&curEntryIndex))) { printDebug("couldn't get index. Maybe we have a binary entry here."); doc->timer()->putLock(DocTimer::id_autoLockTimer); return; } } QString curCategory; if (category) { curCategory = *category; } else { curCategory = view->getCurrentCategory(); } PwMDataItem currItem; if (!doc->getEntry(curCategory, curEntryIndex, &currItem, true)) { doc->timer()->putLock(DocTimer::id_autoLockTimer); return; } BUG_ON(currItem.binary); AddEntryWndImpl w; vector<string> catList; doc->getCategoryList(&catList); unsigned i, size = catList.size(); for (i = 0; i < size; ++i) { w.addCategory(catList[i].c_str()); } w.setCurrCategory(curCategory); w.setDescription(currItem.desc.c_str()); w.setUsername(currItem.name.c_str()); w.setPassword(currItem.pw.c_str()); w.setUrl(currItem.url.c_str()); w.setLauncher(currItem.launcher.c_str()); w.setComment(currItem.comment.c_str()); if (w.exec() == 1) { currItem.desc = w.getDescription().latin1(); currItem.name = w.getUsername().latin1(); currItem.pw = w.getPassword().latin1(); currItem.comment = w.getComment().latin1(); currItem.url = w.getUrl().latin1(); currItem.launcher = w.getLauncher().latin1(); if (!doc->editEntry(curCategory, w.getCategory(), curEntryIndex, &currItem)) { KMessageBox::error(this, i18n("Couldn't edit the entry.\n" "Maybe you changed the category and " "this entry is already present in the new " "category?"), i18n("couldn't edit entry.")); doc->timer()->putLock(DocTimer::id_autoLockTimer); return; } } doc->timer()->putLock(DocTimer::id_autoLockTimer); } void PwM::deletePwd_slot() { PWM_ASSERT(curDoc()); if (curDoc()->isDocEmpty()) return; if (curDoc()->isDeepLocked()) return; curDoc()->timer()->getLock(DocTimer::id_autoLockTimer); unsigned int curEntryIndex = 0; if (!(view->getCurEntryIndex(&curEntryIndex))) { printDebug("couldn't get index"); curDoc()->timer()->putLock(DocTimer::id_autoLockTimer); return; } PwMDataItem currItem; QString curCategory = view->getCurrentCategory(); if (!curDoc()->getEntry(curCategory, curEntryIndex, &currItem)) { printDebug("couldn't get entry"); curDoc()->timer()->putLock(DocTimer::id_autoLockTimer); return; } if (KMessageBox:: questionYesNo(this, i18n ("Do you really want to delete the selected entry") + " \"" + QString(currItem.desc.c_str()) + "\" ?", i18n("delete?")) == KMessageBox::Yes) { curDoc()->delEntry(curCategory, curEntryIndex); } curDoc()->timer()->putLock(DocTimer::id_autoLockTimer); } void PwM::changeMasterPwd_slot() { PWM_ASSERT(curDoc()); curDoc()->changeCurrentPw(); } void PwM::lockWnd_slot() { PWM_ASSERT(curDoc()); curDoc()->lockAll(true); } void PwM::deepLockWnd_slot() { PWM_ASSERT(curDoc()); curDoc()->deepLock(); } void PwM::unlockWnd_slot() { PWM_ASSERT(curDoc()); curDoc()->lockAll(false); } void PwM::config_slot() { - Configuration *conf = Configuration::obj(); - int oldStyle = conf->confWndMainViewStyle(); + int oldStyle = conf()->confWndMainViewStyle(); +#ifdef PWM_EMBEDDED + KCMultiDialog* ConfigureDialog = new KCMultiDialog( "PIM", this ,"pwmconfigdialog", true ); + KCMPwmConfig* pwmcfg = new KCMPwmConfig( ConfigureDialog->getNewVBoxPage(i18n( "PwManager")) , "KCMPwmConfig" ); + ConfigureDialog->addModule(pwmcfg ); + + KCMKdePimConfig* kdelibcfg = new KCMKdePimConfig( ConfigureDialog->getNewVBoxPage(i18n( "Global")) , "KCMKdeLibConfig" ); + ConfigureDialog->addModule(kdelibcfg ); + +#ifndef DESKTOP_VERSION + ConfigureDialog->showMaximized(); +#endif + if ( ConfigureDialog->exec() ) + KMessageBox::information( this, i18n("Some changes are only\neffective after a restart!\n") ); + delete ConfigureDialog; + +#else //PWM_EMBEDDED // display the configuration window (modal mode) - if (!conf->showConfWnd(this)) + if (!conf()->showConfWnd(this)) return; +#endif - int newStyle = conf->confWndMainViewStyle(); + int newStyle = conf()->confWndMainViewStyle(); // reinitialize tray init->initTray(); // reinitialize KWallet emulation init->initKWalletEmu(); PwMDocList *_dl = PwMDoc::getOpenDocList(); const vector<PwMDocList::listItem> *dl = _dl->getList(); vector<PwMDocList::listItem>::const_iterator i = dl->begin(), end = dl->end(); PwMDoc *doc; while (i != end) { doc = (*i).doc; // unlock-without-mpw timeout doc->timer()->start(DocTimer::id_mpwTimer); // auto-lock timeout doc->timer()->start(DocTimer::id_autoLockTimer); ++i; } const QValueList<PwM *> *ml = init->mainWndList(); #ifndef PWM_EMBEDDED QValueList<PwM *>::const_iterator i2 = ml->begin(), end2 = ml->end(); #else QValueList<PwM *>::ConstIterator i2 = ml->begin(), end2 = ml->end(); #endif PwM *pwm; while (i2 != end2) { pwm = *i2; // reinitialize the window style. if (oldStyle != newStyle) pwm->curView()->initStyle(newStyle); // set the new font - pwm->curView()->setFont(conf->confGlobEntryFont()); + pwm->curView()->setFont(conf()->confGlobEntryFont()); ++i2; } } void PwM::activateMpButton(bool activate) { managePopup->setItemEnabled(BUTTON_POPUP_MANAGE_CHANGEMP, activate); } void PwM::closeEvent(QCloseEvent *e) { e->accept(); } void PwM::docClosed(PwMDoc *doc) { PARAM_UNUSED(doc); PWM_ASSERT(doc == curDoc()); close(); } void PwM::find_slot() { PWM_ASSERT(curDoc()); if (curDoc()->isDocEmpty()) return; if (curDoc()->isDeepLocked()) return; curDoc()->timer()->getLock(DocTimer::id_autoLockTimer); FindWndImpl findWnd(view); findWnd.exec(); curDoc()->timer()->putLock(DocTimer::id_autoLockTimer); } void PwM::exportToText() { PWM_ASSERT(curDoc()); if (curDoc()->isDocEmpty()) { KMessageBox::information(this, i18n ("Sorry, there's nothing to export.\n" "Please first add some passwords."), i18n("nothing to do")); return; } curDoc()->timer()->getLock(DocTimer::id_autoLockTimer); QString fn(KFileDialog::getSaveFileName(QString::null, i18n("*|plain-text file"), this)); if (fn == "") { curDoc()->timer()->putLock(DocTimer::id_autoLockTimer); return; } PwMerror ret = curDoc()->exportToText(&fn); if (ret != e_success) { KMessageBox::error(this, i18n("Error: Couldn't write to file.\n" "Please check if you have permission to write " "to the file in that directory."), i18n("error while writing")); } else showStatMsg(i18n("Successfully exported data.")); curDoc()->timer()->putLock(DocTimer::id_autoLockTimer); } bool PwM::importFromText() { if (!isVirgin()) { if (KMessageBox::questionYesNo(this, i18n("Do you want to import the data " "into the current document? (If you " "select \"no\", a new document will be " "opened.)"), i18n("import into this document?")) == KMessageBox::No) { // import the data to a new window. PwM *newInstance = init->createMainWnd(); bool ok = newInstance->importFromText(); if (!ok) { newInstance->setForceQuit(true); delete_and_null(newInstance); } return ok; } } curDoc()->timer()->getLock(DocTimer::id_autoLockTimer); PwMerror ret; QString path(KFileDialog::getOpenFileName(QString::null, i18n("*|PWM-exported text file"), this)); if (path == "") goto cancelImport; ret = curDoc()->importFromText(&path, 0); if (ret == e_fileFormat) { KMessageBox::error(this, i18n("Could not read file-format.\n" "This seems to be _not_ a valid file " "exported by PwM."), i18n("invalid file-format")); goto cancelImport; } else if (ret == e_invalidArg) { BUG(); goto cancelImport; } else if (ret != e_success) { KMessageBox::error(this, i18n("Could not import file!\n" "Do you have permission to read this file? " "Do you have enough free memory?"), i18n("import failed")); goto cancelImport; } setVirgin(false); curDoc()->timer()->putLock(DocTimer::id_autoLockTimer); return true; cancelImport: curDoc()->timer()->putLock(DocTimer::id_autoLockTimer); return false; } void PwM::exportToGpasman() { PWM_ASSERT(curDoc()); if (curDoc()->isDocEmpty()) { KMessageBox::information(this, i18n ("Sorry, there's nothing to export.\n" "Please first add some passwords."), i18n("nothing to do")); return; } curDoc()->timer()->getLock(DocTimer::id_autoLockTimer); QString fn(KFileDialog::getSaveFileName(QString::null, i18n("*|Gpasman or Kpasman file"), this)); if (fn == "") { curDoc()->timer()->putLock(DocTimer::id_autoLockTimer); return; } PwMerror ret = curDoc()->exportToGpasman(&fn); if (ret != e_success) { if (ret == e_noPw) { curDoc()->timer()->putLock(DocTimer::id_autoLockTimer); return; } KMessageBox::error(this, i18n("Error: Couldn't write to file.\n" "Please check if you have permission to write " "to the file in that directory."), i18n("error while writing")); } else showStatMsg(i18n("Successfully exported data.")); curDoc()->timer()->putLock(DocTimer::id_autoLockTimer); } void PwM::exportToKWallet() { #ifdef CONFIG_KWALLETIF if (!checkAndAskForKWalletEmu()) return; PWM_ASSERT(curDoc()); if (curDoc()->isDocEmpty()) { KMessageBox::information(this, i18n ("Sorry, there's nothing to export.\n" "Please first add some passwords."), i18n("nothing to do")); init->initKWalletEmu(); return; } curDoc()->timer()->getLock(DocTimer::id_autoLockTimer); KWalletIf walletIf(this); if (walletIf.kwalletExport(curDoc())) { KMessageBox::information(this, i18n("Successfully exported the data of the current " "document to KWallet."), i18n("Successfully exported data.")); showStatMsg(i18n("Successfully exported data.")); } init->initKWalletEmu(); curDoc()->timer()->putLock(DocTimer::id_autoLockTimer); #endif // CONFIG_KWALLETIF } bool PwM::importFromGpasman() { if (!isVirgin()) { if (KMessageBox::questionYesNo(this, i18n("Do you want to import the data " "into the current document? (If you " "select \"no\", a new document will be " "opened.)"), i18n("import into this document?")) == KMessageBox::No) { // import the data to a new window. PwM *newInstance = init->createMainWnd(); bool ok = newInstance->importFromGpasman(); if (!ok) { newInstance->setForceQuit(true); delete_and_null(newInstance); } return ok; } } curDoc()->timer()->getLock(DocTimer::id_autoLockTimer); PwMerror ret; QString path(KFileDialog::getOpenFileName(QString::null, i18n("*|Gpasman or Kpasman file"), this)); if (path == "") goto cancelImport; ret = curDoc()->importFromGpasman(&path); if (ret == e_wrongPw) { if (KMessageBox::questionYesNo(this, i18n ("This is probably the wrong master-password" "you have typed in.\n" "There is no real way to determine the " "correctness of the password in the Gpasman " "file-format. But I think this " "password ist wrong.\n" "Do you want to continue nevertheless?"), i18n("password error")) == KMessageBox::No) { goto cancelImport; } } else if (ret != e_success) { KMessageBox::error(this, i18n("Could not import file!\n" "Do you have permission to read this file?"), i18n("import failed")); goto cancelImport; } setVirgin(false); curDoc()->timer()->putLock(DocTimer::id_autoLockTimer); return true; cancelImport: curDoc()->timer()->putLock(DocTimer::id_autoLockTimer); return false; } #ifdef CONFIG_KWALLETIF bool PwM::checkAndAskForKWalletEmu() { if (init->kwalletEmu()) { /* KWallet emulation is enabled. We can't import/export * data from/to it, while emulation is active. */ if (KMessageBox::questionYesNo(this, i18n("KWallet emulation is enabled.\n" "You can't import or export data from/to " "the original KWallet, while the emulation " "is active.\n" "Do you want to tempoarly disable the KWallet emulation?"), i18n("Tempoarly disable KWallet emulation?")) == KMessageBox::Yes) { init->initKWalletEmu(true); PWM_ASSERT(!init->kwalletEmu()); return true; } return false; } return true; } #endif // CONFIG_KWALLETIF bool PwM::importKWallet() { #ifdef CONFIG_KWALLETIF if (!checkAndAskForKWalletEmu()) return false; KWalletIf walletIf(this); if (!isVirgin()) { if (KMessageBox::questionYesNo(this, i18n("Do you want to import the data " "into the current document? (If you " "select \"no\", a new document will be " "opened.)"), i18n("import into this document?")) == KMessageBox::No) { // import the data to a new window. PwM *newInstance = init->createMainWnd(); bool ok = newInstance->importKWallet(); if (!ok) { newInstance->setForceQuit(true); delete_and_null(newInstance); goto exit_fail; } else { goto exit_ok; } } } curDoc()->timer()->getLock(DocTimer::id_autoLockTimer); if (!walletIf.kwalletImport(curDoc())) { curDoc()->timer()->putLock(DocTimer::id_autoLockTimer); showStatMsg(i18n("KWallet import failed")); goto exit_fail; } KMessageBox::information(this, i18n("Successfully imported the KWallet data " "into the current document."), i18n("successfully imported")); showStatMsg(i18n("successfully imported")); setVirgin(false); curDoc()->timer()->putLock(DocTimer::id_autoLockTimer); exit_ok: init->initKWalletEmu(); return true; exit_fail: init->initKWalletEmu(); #endif // CONFIG_KWALLETIF return false; } void PwM::print_slot() { curDoc()->timer()->getLock(DocTimer::id_autoLockTimer); #ifndef PWM_EMBEDDED PwMPrint p(curDoc(), this); p.printNow(); #else qDebug("PwM::print_slot , PRINTING IS NOT IMPLEMENTED"); #endif curDoc()->timer()->putLock(DocTimer::id_autoLockTimer); } void PwM::genNewCard_slot() { #ifdef CONFIG_KEYCARD init->keycard()->genNewCard(); #endif } void PwM::eraseCard_slot() { #ifdef CONFIG_KEYCARD init->keycard()->eraseCard(); #endif } void PwM::readCardId_slot() { #ifdef CONFIG_KEYCARD init->keycard()->displayKey(); #endif } void PwM::makeCardBackup_slot() { #ifdef CONFIG_KEYCARD init->keycard()->makeBackupImage(); #endif } void PwM::replayCardBackup_slot() { #ifdef CONFIG_KEYCARD init->keycard()->replayBackupImage(); #endif } void PwM::execLauncher_slot() { PWM_ASSERT(curDoc()); if (curDoc()->isDeepLocked()) return; unsigned int curEntryIndex; if (!view->getCurEntryIndex(&curEntryIndex)) return; bool ret = curDoc()->execLauncher(view->getCurrentCategory(), curEntryIndex); if (ret) showStatMsg(i18n("Executed the \"Launcher\".")); else showStatMsg(i18n("ERROR: Couldn't execute the \"Launcher\"!")); } void PwM::goToURL_slot() { PWM_ASSERT(curDoc()); if (curDoc()->isDeepLocked()) return; unsigned int curEntryIndex; if (!view->getCurEntryIndex(&curEntryIndex)) return; bool ret = curDoc()->goToURL(view->getCurrentCategory(), curEntryIndex); if (ret) showStatMsg(i18n("started browser with current URL.")); else showStatMsg(i18n("ERROR: Couldn't start browser! Maybe invalid URL?")); } void PwM::copyToClipboard(const QString &s) { QClipboard *cb = QApplication::clipboard(); #ifndef PWM_EMBEDDED if (cb->supportsSelection()) cb->setText(s, QClipboard::Selection); cb->setText(s, QClipboard::Clipboard); #else cb->setText(s); #endif } void PwM::showStatMsg(const QString &msg) { #ifndef PWM_EMBEDDED KStatusBar *statBar = statusBar(); statBar->message(msg, STATUSBAR_MSG_TIMEOUT * 1000); #else qDebug("Statusbar : %s",msg.latin1()); #endif } void PwM::focusInEvent(QFocusEvent *e) { if (e->gotFocus()) { emit gotFocus(this); } else if (e->lostFocus()) { emit lostFocus(this); } } #ifdef PWM_EMBEDDED void PwM::showLicense_slot() { KApplication::showLicence(); } void PwM::faq_slot() { KApplication::showFile( "PWM/Pi FAQ", "kdepim/pwmanager/pwmanagerFAQ.txt" ); } void PwM::createAboutData_slot() { QString version; #include <../version> QMessageBox::about( this, "About PwManager/Pi", "PwManager/Platform-independent\n" "(PWM/Pi) " +version + " - " + #ifdef DESKTOP_VERSION "Desktop Edition\n" #else "PDA-Edition\n" "for: Zaurus 5500 / 7x0 / 8x0\n" #endif "(c) 2004 Ulf Schenk\n" "(c) 2004 Lutz Rogowski\n" "(c) 1997-2003, The KDE PIM Team\n" "Michael Buesch - main programming and current maintainer\nmbuesch@freenet.de\n" "Matt Scifo - original implementaion of \n" "\"categories\" and the password-tree \n" "in the system-tray. Original implementations of \n" "numerous view-improvements.\n" "mscifo@o1.com\n" "Elias Probst - Gentoo ebuild maintainer.\nelias.probst@gmx.de\n" "George Staikos - KWallet\nstaikos@kde.org\n" "Matthew Palmer - rc2 code\nmjp16@uow.edu.au\n" "Olivier Sessink - gpasman\ngpasman@nl.linux.org\n" "The libgcrypt developers - Blowfish and SHA1 algorithms\nftp://ftp.gnupg.org/gcrypt/alpha/libgcrypt/\n" "Troy Engel - kpasman\n tengel@sonic.net\n" "Wickey - graphics-design in older versions\nwickey@gmx.at\n" "Ian MacGregor - original documentation author.\n" ); } #endif #ifndef PWM_EMBEDDED #include "pwm.moc" #endif diff --git a/pwmanager/pwmanager/pwmanagerE.pro b/pwmanager/pwmanager/pwmanagerE.pro index 2cd69a5..5c29ea4 100644 --- a/pwmanager/pwmanager/pwmanagerE.pro +++ b/pwmanager/pwmanager/pwmanagerE.pro @@ -1,144 +1,153 @@ TEMPLATE = app CONFIG += qt warn_on TARGET = pwmpi OBJECTS_DIR = obj/$(PLATFORM) MOC_DIR = moc/$(PLATFORM) DESTDIR=$(QPEDIR)/bin -INCLUDEPATH += . ../../qtcompat ../../qtcompat/xml ../../microkde ../../microkde/kdecore ../../microkde/kdeui $(QPEDIR)/include +INCLUDEPATH += . ../../qtcompat ../../qtcompat/xml ../../libkdepim ../../microkde ../../microkde/kdecore ../../microkde/kdeui ../../microkde/kutils $(QPEDIR)/include DEFINES += PWM_EMBEDDED PWM_DEBUG LIBS += -lmicrokde LIBS += -lmicroqtcompat +LIBS += -lmicrokdepim LIBS += -L$(QPEDIR)/lib LIBS += -lqpe LIBS += -lbz2 LIBS += $(QTOPIALIB) #INTERFACES = \ #addentrywnd.ui \ #configwnd.ui \ #findwnd.ui \ #getmasterpwwnd.ui \ #pwgenwnd.ui \ #setmasterpwwnd.ui \ #subtbledit.ui #INTERFACES = \ #subtbledit.ui \ #HEADERS = \ +#configuration_31compat.h \ +#configuration.h \ +#configwnd.h \ +#configwndimpl.h \ #selftest.h HEADERS = \ addentrywnd.h \ addentrywndimpl.h \ base64.h \ binentrygen.h \ blowfish.h \ commentbox.h \ compiler.h \ compressbzip2.h \ compressgzip.h \ -configuration_31compat.h \ -configuration.h \ -configwnd.h \ -configwndimpl.h \ findwnd.h \ findwndimpl.h \ genpasswd.h \ getkeycardwnd.h \ getmasterpwwnd.h \ getmasterpwwndimpl.h \ globalstuff.h \ gpasmanfile.h \ htmlgen.h \ htmlparse.h \ ipc.h \ listobjselectwnd.h \ listviewpwm.h \ printtext.h \ pwgenwnd.h \ pwgenwndimpl.h \ pwmdoc.h \ pwmdocui.h \ pwmexception.h \ pwm.h \ pwminit.h \ +pwmprefs.h \ pwmprint.h \ pwmtray.h \ pwmview.h \ pwmviewstyle_0.h \ pwmviewstyle_1.h \ pwmviewstyle.h \ randomizer.h \ rc2.h \ rencatwnd.h \ serializer.h \ setmasterpwwnd.h \ setmasterpwwndimpl.h \ sha1.h \ subtbledit.h \ subtbleditimpl.h \ -waitwnd.h +waitwnd.h \ +kcmconfigs/kcmpwmconfig.h \ +kcmconfigs/pwmconfigwidget.h \ +#sources that need not be build #SOURCES = \ #advcommeditimpl.cpp \ +#configuration.cpp \ +#configwnd.cpp \ +#configwndimpl.cpp \ #configuration_31compat.cpp \ #htmlparse.cpp \ #printtext.cpp \ #selftest.cpp \ #pwmprint.cpp \ #spinforsignal.cpp SOURCES = \ addentrywnd.cpp \ addentrywndimpl.cpp \ base64.cpp \ binentrygen.cpp \ blowfish.cpp \ commentbox.cpp \ compressbzip2.cpp \ compressgzip.cpp \ -configuration.cpp \ -configwnd.cpp \ -configwndimpl.cpp \ findwnd.cpp \ findwndimpl.cpp \ genpasswd.cpp \ getkeycardwnd.cpp \ getmasterpwwnd.cpp \ getmasterpwwndimpl.cpp \ globalstuff.cpp \ gpasmanfile.cpp \ htmlgen.cpp \ ipc.cpp \ listobjselectwnd.cpp \ listviewpwm.cpp \ main.cpp \ pwgenwnd.cpp \ pwgenwndimpl.cpp \ pwm.cpp \ pwmdoc.cpp \ pwmdocui.cpp \ pwmexception.cpp \ pwminit.cpp \ +pwmprefs.cpp \ pwmtray.cpp \ pwmview.cpp \ pwmviewstyle_0.cpp \ pwmviewstyle_1.cpp \ pwmviewstyle.cpp \ randomizer.cpp \ rc2.cpp \ rencatwnd.cpp \ serializer.cpp \ setmasterpwwnd.cpp \ setmasterpwwndimpl.cpp \ sha1.cpp \ subtbledit.cpp \ subtbleditimpl.cpp \ waitwnd.cpp \ +kcmconfigs/kcmpwmconfig.cpp \ +kcmconfigs/pwmconfigwidget.cpp \ + diff --git a/pwmanager/pwmanager/pwmdoc.cpp b/pwmanager/pwmanager/pwmdoc.cpp index 04af360..9fe4809 100644 --- a/pwmanager/pwmanager/pwmdoc.cpp +++ b/pwmanager/pwmanager/pwmdoc.cpp @@ -1,2775 +1,2777 @@ /*************************************************************************** * * * copyright (C) 2003, 2004 by Michael Buesch * * email: mbuesch@freenet.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License version 2 * * as published by the Free Software Foundation. * * * ***************************************************************************/ /*************************************************************************** * copyright (C) 2004 by Ulf Schenk * This file is originaly based on version 2.0 of pwmanager * and was modified to run on embedded devices that run microkde * * $Id$ **************************************************************************/ #include "pwmdoc.h" #include "pwmview.h" #include "blowfish.h" #include "sha1.h" #include "globalstuff.h" #include "gpasmanfile.h" #include "serializer.h" #include "compressgzip.h" #include "compressbzip2.h" #include "randomizer.h" #include "pwminit.h" #ifndef PWM_EMBEDDED //US #include "libgryptif.h" #else +#include "pwmprefs.h" +#include "kglobal.h" #endif #ifdef CONFIG_KWALLETIF # include "kwalletemu.h" #endif // CONFIG_KWALLETIF #include <qdatetime.h> #include <qsize.h> #include <qfileinfo.h> #include <qfile.h> #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <string.h> #include <iostream> #include <algorithm> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <stdint.h> //TODO: reset to its normal value. #define META_CHECK_TIMER_INTERVAL 10/*300*/ /* sek */ using namespace std; void PwMDocList::add(PwMDoc *doc, const string &id) { #ifdef PWM_DEBUG // check for existance of object in debug mode only. vector<listItem>::iterator begin = docList.begin(), end = docList.end(), i = begin; while (i != end) { if (i->doc == doc) { BUG(); return; } ++i; } #endif listItem newItem; newItem.doc = doc; newItem.docId = id; docList.push_back(newItem); } void PwMDocList::edit(PwMDoc *doc, const string &newId) { vector<listItem>::iterator begin = docList.begin(), end = docList.end(), i = begin; while (i != end) { if (i->doc == doc) { i->docId = newId; return; } ++i; } } void PwMDocList::del(PwMDoc *doc) { vector<listItem>::iterator begin = docList.begin(), end = docList.end(), i = begin; while (i != end) { if (i->doc == doc) { docList.erase(i); return; } ++i; } } bool PwMDocList::find(const string &id, listItem *ret) { vector<listItem>::iterator begin = docList.begin(), end = docList.end(), i = begin; while (i != end) { if (i->docId == id) { if (ret) *ret = *i; return true; } ++i; } return false; } DocTimer::DocTimer(PwMDoc *_doc) : doc (_doc) , mpwLock (0) , autoLockLock (0) , metaCheckLock (0) { mpwTimer = new QTimer; autoLockTimer = new QTimer; metaCheckTimer = new QTimer; connect(mpwTimer, SIGNAL(timeout()), this, SLOT(mpwTimeout())); connect(autoLockTimer, SIGNAL(timeout()), this, SLOT(autoLockTimeout())); connect(metaCheckTimer, SIGNAL(timeout()), this, SLOT(metaCheckTimeout())); } DocTimer::~DocTimer() { delete mpwTimer; delete autoLockTimer; delete metaCheckTimer; } void DocTimer::start(TimerIDs timer) { switch (timer) { case id_mpwTimer: if (mpwTimer->isActive()) mpwTimer->stop(); doc->setDocStatFlag(DOC_STAT_UNLOCK_WITHOUT_PW); mpwTimer->start(conf()->confGlobPwTimeout() * 1000, true); break; case id_autoLockTimer: if (autoLockTimer->isActive()) autoLockTimer->stop(); if (conf()->confGlobLockTimeout() > 0) autoLockTimer->start(conf()->confGlobLockTimeout() * 1000, true); break; case id_metaCheckTimer: if (metaCheckTimer->isActive()) metaCheckTimer->stop(); metaCheckTimer->start(META_CHECK_TIMER_INTERVAL * 1000, true); break; } } void DocTimer::stop(TimerIDs timer) { switch (timer) { case id_mpwTimer: mpwTimer->stop(); break; case id_autoLockTimer: autoLockTimer->stop(); break; case id_metaCheckTimer: metaCheckTimer->stop(); break; } } void DocTimer::getLock(TimerIDs timer) { switch (timer) { case id_mpwTimer: ++mpwLock; break; case id_autoLockTimer: ++autoLockLock; break; case id_metaCheckTimer: ++metaCheckLock; break; } } void DocTimer::putLock(TimerIDs timer) { switch (timer) { case id_mpwTimer: if (mpwLock) --mpwLock; break; case id_autoLockTimer: if (autoLockLock) --autoLockLock; break; case id_metaCheckTimer: if (metaCheckLock) --metaCheckLock; break; } } void DocTimer::mpwTimeout() { if (mpwLock) { mpwTimer->start(1000, true); return; } doc->unsetDocStatFlag(DOC_STAT_UNLOCK_WITHOUT_PW); } void DocTimer::autoLockTimeout() { if (autoLockLock) { autoLockTimer->start(1000, true); return; } if (conf()->confGlobAutoDeepLock() && doc->filename != QString::null && doc->filename != "") { doc->deepLock(true); } else { doc->lockAll(true); } } void DocTimer::metaCheckTimeout() { if (metaCheckLock) { // check again in one second. metaCheckTimer->start(1000, true); return; } if (doc->isDeepLocked()) { metaCheckTimer->start(META_CHECK_TIMER_INTERVAL * 1000, true); return; } if (doc->isDocEmpty()) { metaCheckTimer->start(META_CHECK_TIMER_INTERVAL * 1000, true); return; } #ifdef CONFIG_KWALLETIF KWalletEmu *kwlEmu = doc->init->kwalletEmu(); if (kwlEmu) kwlEmu->suspendDocSignals(); #endif // CONFIG_KWALLETIF /* We simply trigger all views to update their * displayed values. This way they have a chance * to get notified when some meta changes over time. * (for example an entry expired). * The _view_ is responsive for not updating its * contents if nothing really changed! */ emit doc->dataChanged(doc); #ifdef CONFIG_KWALLETIF if (kwlEmu) kwlEmu->resumeDocSignals(); #endif // CONFIG_KWALLETIF metaCheckTimer->start(META_CHECK_TIMER_INTERVAL * 1000, true); } PwMDocList PwMDoc::openDocList; unsigned int PwMDocList::unnamedDocCnt = 1; PwMDoc::PwMDoc(QObject *parent, const char *name) : PwMDocUi(parent, name) , dataChangedLock (0) { deleted = false; unnamedNum = 0; getOpenDocList()->add(this, getTitle().latin1()); curDocStat = 0; setMaxNumEntries(); _timer = new DocTimer(this); timer()->start(DocTimer::id_mpwTimer); timer()->start(DocTimer::id_autoLockTimer); timer()->start(DocTimer::id_metaCheckTimer); addCategory(DEFAULT_CATEGORY, 0, false); listView = 0; emit docCreated(this); } PwMDoc::~PwMDoc() { emit docClosed(this); getOpenDocList()->del(this); delete _timer; } PwMerror PwMDoc::saveDoc(char compress, const QString *file) { PwMerror ret, e; if (!file) { if (filename == "") return e_filename; } else { if (*file == "" && filename == "") return e_filename; if (*file != "") filename = *file; } bool wasDeepLocked = isDeepLocked(); if (wasDeepLocked) { if (deepLock(false) != e_success) return e_noPw; } if (!isPwAvailable()) { /* password is not available. This means, the * document wasn't saved, yet. */ bool useChipcard = getDocStatFlag(DOC_STAT_USE_CHIPCARD); QString pw(requestNewMpw(&useChipcard)); if (pw != "") { currentPw = pw; } else { return e_noPw; } if (useChipcard) { setDocStatFlag(DOC_STAT_USE_CHIPCARD); } else { unsetDocStatFlag(DOC_STAT_USE_CHIPCARD); } } #ifndef PWM_EMBEDDED int _cryptAlgo = conf()->confGlobCryptAlgo(); int _hashAlgo = conf()->confGlobHashAlgo(); #else int _cryptAlgo = PWM_CRYPT_BLOWFISH; int _hashAlgo = PWM_HASH_SHA1; #endif // sanity check for the selected algorithms if (_cryptAlgo < PWM_CRYPT_BLOWFISH || _cryptAlgo > PWM_CRYPT_TWOFISH128) { printWarn("Invalid Crypto-Algorithm selected! " "Config-file seems to be corrupt. " "Falling back to Blowfish."); _cryptAlgo = PWM_CRYPT_BLOWFISH; } if (_hashAlgo < PWM_HASH_SHA1 || _hashAlgo > PWM_HASH_TIGER) { printWarn("Invalid Hash-Algorithm selected! " "Config-file seems to be corrupt. " "Falling back to SHA1."); _hashAlgo = PWM_HASH_SHA1; } char cryptAlgo = static_cast<char>(_cryptAlgo); char hashAlgo = static_cast<char>(_hashAlgo); if (conf()->confGlobMakeFileBackup()) { if (!backupFile(filename)) return e_fileBackup; } QString tmpFileMoved(QString::null); if (QFile::exists(filename)) { /* Move the existing file to some tmp file. * When saving file succeeds, delete tmp file. Otherwise * move tmp file back. See below. */ Randomizer *rnd = Randomizer::obj(); char rnd_buf[5]; sprintf(rnd_buf, "%X%X%X%X", rnd->genRndChar() & 0xFF, rnd->genRndChar() & 0xFF, rnd->genRndChar() & 0xFF, rnd->genRndChar() & 0xFF); tmpFileMoved = filename + "." + rnd_buf + ".mv"; if (!copyFile(filename, tmpFileMoved)) return e_openFile; if (!QFile::remove(filename)) { printWarn(string("removing orig file ") + filename.latin1() + " failed!"); } } QFile f(filename); string serialized; if (!f.open(IO_ReadWrite)) { ret = e_openFile; goto out_moveback; } e = writeFileHeader(hashAlgo, hashAlgo, cryptAlgo, compress, ¤tPw, &f); if (e == e_hashNotImpl) { printDebug("PwMDoc::saveDoc(): writeFileHeader() failed: e_hashNotImpl"); f.close(); ret = e_hashNotImpl; goto out_moveback; } else if (e != e_success) { printDebug("PwMDoc::saveDoc(): writeFileHeader() failed"); f.close(); ret = e_writeHeader; goto out_moveback; } if (!serializeDta(&serialized)) { printDebug("PwMDoc::saveDoc(): serializeDta() failed"); f.close(); ret = e_serializeDta; goto out_moveback; } e = writeDataHash(hashAlgo, &serialized, &f); if (e == e_hashNotImpl) { printDebug("PwMDoc::saveDoc(): writeDataHash() failed: e_hashNotImpl"); f.close(); ret = e_hashNotImpl; goto out_moveback; } else if (e != e_success) { printDebug("PwMDoc::saveDoc(): writeDataHash() failed"); f.close(); ret = e_writeHeader; goto out_moveback; } if (!compressDta(&serialized, compress)) { printDebug("PwMDoc::saveDoc(): compressDta() failed"); f.close(); ret = e_enc; goto out_moveback; } e = encrypt(&serialized, ¤tPw, &f, cryptAlgo); if (e == e_weakPw) { printDebug("PwMDoc::saveDoc(): encrypt() failed: e_weakPw"); f.close(); ret = e_weakPw; goto out_moveback; } else if (e == e_cryptNotImpl) { printDebug("PwMDoc::saveDoc(): encrypt() failed: e_cryptNotImpl"); f.close(); ret = e_cryptNotImpl; goto out_moveback; } else if (e != e_success) { printDebug("PwMDoc::saveDoc(): encrypt() failed"); f.close(); ret = e_enc; goto out_moveback; } unsetDocStatFlag(DOC_STAT_DISK_DIRTY); f.close(); if (chmod(filename.latin1(), conf()->confGlobFilePermissions())) { printWarn(string("chmod failed: ") + strerror(errno)); } openDocList.edit(this, getTitle().latin1()); if (wasDeepLocked) deepLock(true); if (tmpFileMoved != QString::null) { // now remove the moved file. if (!QFile::remove(tmpFileMoved)) { printWarn(string("removing file ") + tmpFileMoved.latin1() + " failed!"); } } ret = e_success; printDebug(string("writing file { compress: ") + tostr(static_cast<int>(compress)) + " cryptAlgo: " + tostr(static_cast<int>(cryptAlgo)) + " hashAlgo: " + tostr(static_cast<int>(hashAlgo)) + " }"); goto out; out_moveback: if (tmpFileMoved != QString::null) { if (copyFile(tmpFileMoved, filename)) { if (!QFile::remove(tmpFileMoved)) { printWarn(string("removing tmp file ") + filename.latin1() + " failed!"); } } else { printWarn(string("couldn't copy file ") + tmpFileMoved.latin1() + " back to " + filename.latin1()); } } out: return ret; } PwMerror PwMDoc::openDoc(const QString *file, int openLocked) { PWM_ASSERT(file); PWM_ASSERT(openLocked == 0 || openLocked == 1 || openLocked == 2); string decrypted, dataHash; PwMerror ret; char cryptAlgo, dataHashType, compress; unsigned int headerLen; if (*file == "") return e_readFile; filename = *file; /* check if this file is already open. * This does not catch symlinks! */ if (!isDeepLocked()) { if (getOpenDocList()->find(filename.latin1())) return e_alreadyOpen; } QFile f(filename); if (openLocked == 2) { // open deep-locked if (!QFile::exists(filename)) return e_openFile; if (deepLock(true, false) != e_success) return e_openFile; goto out_success; } if (!f.open(IO_ReadOnly)) return e_openFile; ret = checkHeader(&cryptAlgo, ¤tPw, &compress, &headerLen, &dataHashType, &dataHash, &f); if (ret != e_success) { printDebug("PwMDoc::openDoc(): checkHeader() failed"); f.close(); if (ret == e_wrongPw) { wrongMpwMsgBox(getDocStatFlag(DOC_STAT_USE_CHIPCARD)); return ret; } else if (ret == e_noPw || ret == e_fileVer || ret == e_fileFormat || ret == e_hashNotImpl) { return ret; } else return e_readFile; } ret = decrypt(&decrypted, headerLen, ¤tPw, cryptAlgo, &f); if (ret == e_cryptNotImpl) { printDebug("PwMDoc::openDoc(): decrypt() failed: e_cryptNotImpl"); f.close(); return e_cryptNotImpl; } else if (ret != e_success) { printDebug("PwMDoc::openDoc(): decrypt() failed"); f.close(); return e_readFile; } if (!decompressDta(&decrypted, compress)) { printDebug("PwMDoc::openDoc(): decompressDta() failed"); f.close(); return e_fileCorrupt; } ret = checkDataHash(dataHashType, &dataHash, &decrypted); if (ret == e_hashNotImpl) { printDebug("PwMDoc::openDoc(): checkDataHash() failed: e_hashNotImpl"); f.close(); return e_hashNotImpl; } else if (ret != e_success) { printDebug("PwMDoc::openDoc(): checkDataHash() failed"); f.close(); return e_fileCorrupt; } if (!deSerializeDta(&decrypted, openLocked == 1)) { printDebug("PwMDoc::openDoc(): deSerializeDta() failed"); f.close(); return e_readFile; } f.close(); timer()->start(DocTimer::id_mpwTimer); timer()->start(DocTimer::id_autoLockTimer); out_success: openDocList.edit(this, getTitle().latin1()); emit docOpened(this); return e_success; } PwMerror PwMDoc::writeFileHeader(char keyHash, char dataHash, char crypt, char compress, QString *pw, QFile *f) { PWM_ASSERT(pw); PWM_ASSERT(f); PWM_ASSERT(listView); #ifndef PWM_EMBEDDED if (f->writeBlock(FILE_ID_HEADER, strlen(FILE_ID_HEADER)) != static_cast<Q_LONG>(strlen(FILE_ID_HEADER))) { return e_writeFile; } if (f->putch(PWM_FILE_VER) == -1 || f->putch(keyHash) == -1 || f->putch(dataHash) == -1 || f->putch(crypt) == -1 || f->putch(compress) == -1 || f->putch((getDocStatFlag(DOC_STAT_USE_CHIPCARD)) ? (static_cast<char>(0x01)) : (static_cast<char>(0x00))) == -1) { return e_writeFile; } #else if (f->writeBlock(FILE_ID_HEADER, strlen(FILE_ID_HEADER)) != (long)(strlen(FILE_ID_HEADER))) { return e_writeFile; } if (f->putch(PWM_FILE_VER) == -1 || f->putch(keyHash) == -1 || f->putch(dataHash) == -1 || f->putch(crypt) == -1 || f->putch(compress) == -1 || f->putch((getDocStatFlag(DOC_STAT_USE_CHIPCARD)) ? ((char)(0x01)) : ((char)(0x00))) == -1) { return e_writeFile; } #endif // write bytes of NUL-data. These bytes are reserved for future-use. const int bufSize = 64; char tmp_buf[bufSize]; memset(tmp_buf, 0x00, bufSize); if (f->writeBlock(tmp_buf, bufSize) != bufSize) return e_writeFile; switch (keyHash) { case PWM_HASH_SHA1: { const int hashlen = SHA1_HASH_LEN_BYTE; Sha1 hash; hash.sha1_write(reinterpret_cast<const byte *>(pw->latin1()), pw->length()); string ret = hash.sha1_read(); if (f->writeBlock(ret.c_str(), hashlen) != hashlen) return e_writeFile; break; } #ifndef PWM_EMBEDDED case PWM_HASH_SHA256: /*... fall through */ case PWM_HASH_SHA384: case PWM_HASH_SHA512: case PWM_HASH_MD5: case PWM_HASH_RMD160: case PWM_HASH_TIGER: { if (!LibGCryptIf::available()) return e_hashNotImpl; LibGCryptIf gc; PwMerror err; unsigned char *buf; size_t hashLen; err = gc.hash(&buf, &hashLen, reinterpret_cast<const unsigned char *>(pw->latin1()), pw->length(), keyHash); if (err != e_success) return e_hashNotImpl; if (f->writeBlock(reinterpret_cast<const char *>(buf), hashLen) != static_cast<Q_LONG>(hashLen)) { delete [] buf; return e_hashNotImpl; } delete [] buf; break; } #endif default: { return e_hashNotImpl; } } return e_success; } PwMerror PwMDoc::checkHeader(char *cryptAlgo, QString *pw, char *compress, unsigned int *headerLength, char *dataHashType, string *dataHash, QFile *f) { PWM_ASSERT(cryptAlgo); PWM_ASSERT(pw); PWM_ASSERT(headerLength); PWM_ASSERT(dataHashType); PWM_ASSERT(dataHash); PWM_ASSERT(f); int tmpRet; // check "magic" header const char magicHdr[] = FILE_ID_HEADER; const int hdrLen = array_size(magicHdr) - 1; char tmp[hdrLen]; if (f->readBlock(tmp, hdrLen) != hdrLen) return e_readFile; if (memcmp(tmp, magicHdr, hdrLen) != 0) return e_fileFormat; // read and check file ver int fileV = f->getch(); if (fileV == -1) return e_fileFormat; if (fileV != PWM_FILE_VER) return e_fileVer; // read hash hash type int keyHash = f->getch(); if (keyHash == -1) return e_fileFormat; // read data hash type tmpRet = f->getch(); if (tmpRet == -1) return e_fileFormat; *dataHashType = tmpRet; // read crypt algo tmpRet = f->getch(); if (tmpRet == -1) return e_fileFormat; *cryptAlgo = tmpRet; // get compression-algo tmpRet = f->getch(); if (tmpRet == -1) return e_fileFormat; *compress = tmpRet; // get the MPW-flag int mpw_flag = f->getch(); if (mpw_flag == -1) return e_fileFormat; if (mpw_flag == 0x01) setDocStatFlag(DOC_STAT_USE_CHIPCARD); else unsetDocStatFlag(DOC_STAT_USE_CHIPCARD); // skip the "RESERVED"-bytes if (!(f->at(f->at() + 64))) return e_fileFormat; *pw = requestMpw(getDocStatFlag(DOC_STAT_USE_CHIPCARD)); if (*pw == "") { /* the user didn't give a master-password * or didn't insert a chipcard */ return e_noPw; } // verify key-hash switch (keyHash) { case PWM_HASH_SHA1: { // read hash from header const int hashLen = SHA1_HASH_LEN_BYTE; string readHash; int i; for (i = 0; i < hashLen; ++i) readHash.push_back(f->getch()); Sha1 hash; hash.sha1_write(reinterpret_cast<const byte *>(pw->latin1()), pw->length()); string ret = hash.sha1_read(); if (ret != readHash) return e_wrongPw; // hash doesn't match (wrong key) break; } #ifndef PWM_EMBEDDED case PWM_HASH_SHA256: /*... fall through */ case PWM_HASH_SHA384: case PWM_HASH_SHA512: case PWM_HASH_MD5: case PWM_HASH_RMD160: case PWM_HASH_TIGER: { if (!LibGCryptIf::available()) return e_hashNotImpl; LibGCryptIf gc; PwMerror err; unsigned char *buf; size_t hashLen; err = gc.hash(&buf, &hashLen, reinterpret_cast<const unsigned char *>(pw->latin1()), pw->length(), keyHash); if (err != e_success) return e_hashNotImpl; string calcHash(reinterpret_cast<const char *>(buf), static_cast<string::size_type>(hashLen)); delete [] buf; // read hash from header string readHash; size_t i; for (i = 0; i < hashLen; ++i) readHash.push_back(f->getch()); if (calcHash != readHash) return e_wrongPw; // hash doesn't match (wrong key) break; } #endif default: { return e_hashNotImpl; } } // read the data-hash from the file unsigned int hashLen, i; switch (*dataHashType) { case PWM_HASH_SHA1: hashLen = SHA1_HASH_LEN_BYTE; break; #ifndef PWM_EMBEDDED case PWM_HASH_SHA256: /*... fall through */ case PWM_HASH_SHA384: case PWM_HASH_SHA512: case PWM_HASH_MD5: case PWM_HASH_RMD160: case PWM_HASH_TIGER: { if (!LibGCryptIf::available()) return e_hashNotImpl; LibGCryptIf gc; hashLen = gc.hashLength(*dataHashType); if (hashLen == 0) return e_hashNotImpl; break; } #endif default: return e_hashNotImpl; } *dataHash = ""; for (i = 0; i < hashLen; ++i) { tmpRet = f->getch(); if (tmpRet == -1) return e_fileFormat; dataHash->push_back(static_cast<char>(tmpRet)); } *headerLength = f->at(); #ifndef PWM_EMBEDDED printDebug(string("opening file { compress: ") + tostr(static_cast<int>(*compress)) + " cryptAlgo: " + tostr(static_cast<int>(*cryptAlgo)) + " keyHashAlgo: " + tostr(static_cast<int>(keyHash)) + " }"); #else printDebug(string("opening file { compress: ") + tostr((int)(*compress)) + " cryptAlgo: " + tostr((int)(*cryptAlgo)) + " keyHashAlgo: " + tostr((int)(keyHash)) + " }"); #endif return e_success; } PwMerror PwMDoc::writeDataHash(char dataHash, string *d, QFile *f) { PWM_ASSERT(d); PWM_ASSERT(f); switch (dataHash) { case PWM_HASH_SHA1: { const int hashLen = SHA1_HASH_LEN_BYTE; Sha1 h; h.sha1_write(reinterpret_cast<const byte *>(d->c_str()), d->size()); string hRet = h.sha1_read(); if (f->writeBlock(hRet.c_str(), hashLen) != hashLen) return e_writeFile; break; } #ifndef PWM_EMBEDDED case PWM_HASH_SHA256: /*... fall through */ case PWM_HASH_SHA384: case PWM_HASH_SHA512: case PWM_HASH_MD5: case PWM_HASH_RMD160: case PWM_HASH_TIGER: { if (!LibGCryptIf::available()) return e_hashNotImpl; LibGCryptIf gc; PwMerror err; unsigned char *buf; size_t hashLen; err = gc.hash(&buf, &hashLen, reinterpret_cast<const unsigned char *>(d->c_str()), d->size(), dataHash); if (err != e_success) return e_hashNotImpl; if (f->writeBlock(reinterpret_cast<const char *>(buf), hashLen) != static_cast<Q_LONG>(hashLen)) { delete [] buf; return e_hashNotImpl; } delete [] buf; break; } #endif default: { return e_hashNotImpl; } } return e_success; } bool PwMDoc::backupFile(const QString &filePath) { QFileInfo fi(filePath); if (!fi.exists()) return true; // Yes, true is correct. QString pathOnly(fi.dirPath(true)); QString nameOnly(fi.fileName()); QString backupPath = pathOnly + "/~" + nameOnly + ".backup"; return copyFile(filePath, backupPath); } bool PwMDoc::copyFile(const QString &src, const QString &dst) { QFileInfo fi(src); if (!fi.exists()) return false; if (QFile::exists(dst)) { if (!QFile::remove(dst)) return false; } QFile srcFd(src); if (!srcFd.open(IO_ReadOnly)) return false; QFile dstFd(dst); if (!dstFd.open(IO_ReadWrite)) { srcFd.close(); return false; } const int tmpBuf_size = 512; char tmpBuf[tmpBuf_size]; #ifndef PWM_EMBEDDED Q_LONG bytesRead, bytesWritten; #else long bytesRead, bytesWritten; #endif while (!srcFd.atEnd()) { #ifndef PWM_EMBEDDED bytesRead = srcFd.readBlock(tmpBuf, static_cast<Q_ULONG>(tmpBuf_size)); #else bytesRead = srcFd.readBlock(tmpBuf, (unsigned long)(tmpBuf_size)); #endif if (bytesRead == -1) { srcFd.close(); dstFd.close(); return false; } #ifndef PWM_EMBEDDED bytesWritten = dstFd.writeBlock(tmpBuf, static_cast<Q_ULONG>(bytesRead)); #else bytesWritten = dstFd.writeBlock(tmpBuf, (unsigned long)(bytesRead)); #endif if (bytesWritten != bytesRead) { srcFd.close(); dstFd.close(); return false; } } srcFd.close(); dstFd.close(); return true; } PwMerror PwMDoc::addEntry(const QString &category, PwMDataItem *d, bool dontFlagDirty, bool updateMeta) { PWM_ASSERT(d); unsigned int cat = 0; if (isDeepLocked()) { PwMerror ret; ret = deepLock(false); if (ret != e_success) return e_lock; } addCategory(category, &cat); if (numEntries(category) >= maxEntries) return e_maxAllowedEntr; vector<unsigned int> foundPositions; /* historically this was: * const int searchIn = SEARCH_IN_DESC | SEARCH_IN_NAME | * SEARCH_IN_URL | SEARCH_IN_LAUNCHER; * But for now we only search in desc. * That's a tweak to be KWallet compatible. But it should not add * usability-drop onto PwManager, does it? * (And yes, "int" was a bug. Correct is "unsigned int") */ const unsigned int searchIn = SEARCH_IN_DESC; findEntry(cat, *d, searchIn, &foundPositions, true); if (foundPositions.size()) { // DOH! We found this entry. return e_entryExists; } d->listViewPos = -1; d->lockStat = conf()->confGlobNewEntrLockStat(); if (updateMeta) { d->meta.create = QDateTime::currentDateTime(); d->meta.update = d->meta.create; } dta[cat].d.push_back(*d); delAllEmptyCat(true); if (!dontFlagDirty) flagDirty(); return e_success; } PwMerror PwMDoc::addCategory(const QString &category, unsigned int *categoryIndex, bool checkIfExist) { if (isDeepLocked()) { PwMerror ret; ret = deepLock(false); if (ret != e_success) return e_lock; } if (checkIfExist) { if (findCategory(category, categoryIndex)) return e_categoryExists; } PwMCategoryItem item; item.name = category.latin1(); dta.push_back(item); if (categoryIndex) *categoryIndex = dta.size() - 1; return e_success; } bool PwMDoc::delEntry(const QString &category, unsigned int index, bool dontFlagDirty) { unsigned int cat = 0; if (!findCategory(category, &cat)) { BUG(); return false; } return delEntry(cat, index, dontFlagDirty); } bool PwMDoc::delEntry(unsigned int category, unsigned int index, bool dontFlagDirty) { if (isDeepLocked()) return false; if (index > dta[category].d.size() - 1) return false; getDataChangedLock(); if (!lockAt(category, index, false)) { putDataChangedLock(); return false; } putDataChangedLock(); int lvPos = dta[category].d[index].listViewPos; // delete entry dta[category].d.erase(dta[category].d.begin() + index); unsigned int i, entries = numEntries(category); if (!entries) { // no more entries in this category, so // we can delete it, too. BUG_ON(!delCategory(category)); // delCategory() flags it dirty, so we need not to do so. return true; } for (i = 0; i < entries; ++i) { // decrement all listViewPositions that are greater than the deleted. if (dta[category].d[i].listViewPos > lvPos) --dta[category].d[i].listViewPos; } if (!dontFlagDirty) flagDirty(); return true; } bool PwMDoc::editEntry(const QString &oldCategory, const QString &newCategory, unsigned int index, PwMDataItem *d, bool updateMeta) { PWM_ASSERT(d); unsigned int oldCat = 0; if (!findCategory(oldCategory, &oldCat)) { BUG(); return false; } return editEntry(oldCat, newCategory, index, d, updateMeta); } bool PwMDoc::editEntry(unsigned int oldCategory, const QString &newCategory, unsigned int index, PwMDataItem *d, bool updateMeta) { if (isDeepLocked()) return false; if (updateMeta) { d->meta.update = QDateTime::currentDateTime(); if (d->meta.create.isNull()) { d->meta.create = d->meta.update; } } if (dta[oldCategory].name != newCategory.latin1()) { // the user changed the category. PwMerror ret; d->rev = 0; ret = addEntry(newCategory, d, true, false); if (ret != e_success) return false; if (!delEntry(oldCategory, index, true)) return false; } else { d->rev = dta[oldCategory].d[index].rev + 1; // increment revision counter. dta[oldCategory].d[index] = *d; } flagDirty(); return true; } unsigned int PwMDoc::numEntries(const QString &category) { unsigned int cat = 0; if (!findCategory(category, &cat)) { BUG(); return 0; } return numEntries(cat); } bool PwMDoc::serializeDta(string *d) { PWM_ASSERT(d); Serializer ser; if (!ser.serialize(dta)) return false; d->assign(ser.getXml()); if (!d->size()) return false; return true; } bool PwMDoc::deSerializeDta(const string *d, bool entriesLocked) { PWM_ASSERT(d); try { Serializer ser(d->c_str()); ser.setDefaultLockStat(entriesLocked); if (!ser.deSerialize(&dta)) return false; } catch (PwMException) { return false; } emitDataChanged(this); return true; } bool PwMDoc::getEntry(const QString &category, unsigned int index, PwMDataItem * d, bool unlockIfLocked) { PWM_ASSERT(d); unsigned int cat = 0; if (!findCategory(category, &cat)) { BUG(); return false; } return getEntry(cat, index, d, unlockIfLocked); } bool PwMDoc::getEntry(unsigned int category, unsigned int index, PwMDataItem *d, bool unlockIfLocked) { if (index > dta[category].d.size() - 1) return false; bool locked = isLocked(category, index); if (locked) { /* this entry is locked. We don't return a password, * until it's unlocked by the user by inserting * chipcard or entering the mpw */ if (unlockIfLocked) { if (!lockAt(category, index, false)) { return false; } locked = false; } } *d = dta[category].d[index]; if (locked) d->pw = LOCKED_STRING.latin1(); return true; } PwMerror PwMDoc::getCommentByLvp(const QString &category, int listViewPos, string *foundComment) { PWM_ASSERT(foundComment); unsigned int cat = 0; if (!findCategory(category, &cat)) return e_invalidArg; unsigned int i, entries = numEntries(cat); for (i = 0; i < entries; ++i) { if (dta[cat].d[i].listViewPos == listViewPos) { *foundComment = dta[cat].d[i].comment; if (dta[cat].d[i].binary) return e_binEntry; return e_normalEntry; } } BUG(); return e_generic; } bool PwMDoc::compressDta(string *d, char algo) { PWM_ASSERT(d); switch (algo) { case PWM_COMPRESS_GZIP: { CompressGzip comp; return comp.compress(d); } case PWM_COMPRESS_BZIP2: { CompressBzip2 comp; return comp.compress(d); } case PWM_COMPRESS_NONE: { return true; } default: { BUG(); } } return false; } bool PwMDoc::decompressDta(string *d, char algo) { PWM_ASSERT(d); switch (algo) { case PWM_COMPRESS_GZIP: { CompressGzip comp; return comp.decompress(d); } case PWM_COMPRESS_BZIP2: { CompressBzip2 comp; return comp.decompress(d); } case PWM_COMPRESS_NONE: { return true; } } return false; } PwMerror PwMDoc::encrypt(string *d, const QString *pw, QFile *f, char algo) { PWM_ASSERT(d); PWM_ASSERT(pw); PWM_ASSERT(f); size_t encSize; byte *encrypted = 0; switch (algo) { case PWM_CRYPT_BLOWFISH: { Blowfish::padNull(d); encSize = d->length(); encrypted = new byte[encSize]; Blowfish bf; if (bf.bf_setkey((byte *) pw->latin1(), pw->length())) { delete [] encrypted; return e_weakPw; } bf.bf_encrypt((byte *) encrypted, (byte *) d->c_str(), encSize); break; } #ifndef PWM_EMBEDDED case PWM_CRYPT_AES128: /*... fall through */ case PWM_CRYPT_AES192: case PWM_CRYPT_AES256: case PWM_CRYPT_3DES: case PWM_CRYPT_TWOFISH: case PWM_CRYPT_TWOFISH128: { if (!LibGCryptIf::available()) return e_cryptNotImpl; LibGCryptIf gc; PwMerror err; unsigned char *plain = new unsigned char[d->length() + 1024]; memcpy(plain, d->c_str(), d->length()); err = gc.encrypt(&encrypted, &encSize, plain, d->length(), reinterpret_cast<const unsigned char *>(pw->latin1()), pw->length(), algo); delete [] plain; if (err != e_success) return e_cryptNotImpl; break; } #endif default: { delete_ifnot_null_array(encrypted); return e_cryptNotImpl; } } // write encrypted data to file #ifndef PWM_EMBEDDED if (f->writeBlock(reinterpret_cast<const char *>(encrypted), static_cast<Q_ULONG>(encSize)) != static_cast<Q_LONG>(encSize)) { delete_ifnot_null_array(encrypted); return e_writeFile; } #else if (f->writeBlock((const char *)(encrypted), (unsigned long)(encSize)) != (long)(encSize)) { delete_ifnot_null_array(encrypted); return e_writeFile; } #endif delete_ifnot_null_array(encrypted); return e_success; } PwMerror PwMDoc::decrypt(string *d, unsigned int pos, const QString *pw, char algo, QFile *f) { PWM_ASSERT(d); PWM_ASSERT(pw); PWM_ASSERT(f); unsigned int cryptLen = f->size() - pos; byte *encrypted = new byte[cryptLen]; byte *decrypted = new byte[cryptLen]; f->at(pos); #ifndef PWM_EMBEDDED if (f->readBlock(reinterpret_cast<char *>(encrypted), static_cast<Q_ULONG>(cryptLen)) != static_cast<Q_LONG>(cryptLen)) { delete [] encrypted; delete [] decrypted; return e_readFile; } #else if (f->readBlock((char *)(encrypted), (unsigned long)(cryptLen)) != (long)(cryptLen)) { delete [] encrypted; delete [] decrypted; return e_readFile; } #endif switch (algo) { case PWM_CRYPT_BLOWFISH: { Blowfish bf; bf.bf_setkey((byte *) pw->latin1(), pw->length()); bf.bf_decrypt(decrypted, encrypted, cryptLen); break; } #ifndef PWM_EMBEDDED case PWM_CRYPT_AES128: /*... fall through */ case PWM_CRYPT_AES192: case PWM_CRYPT_AES256: case PWM_CRYPT_3DES: case PWM_CRYPT_TWOFISH: case PWM_CRYPT_TWOFISH128: { if (!LibGCryptIf::available()) return e_cryptNotImpl; LibGCryptIf gc; PwMerror err; err = gc.decrypt(&decrypted, &cryptLen, encrypted, cryptLen, reinterpret_cast<const unsigned char *>(pw->latin1()), pw->length(), algo); if (err != e_success) { delete [] encrypted; delete [] decrypted; return e_cryptNotImpl; } break; } #endif default: { delete [] encrypted; delete [] decrypted; return e_cryptNotImpl; } } delete [] encrypted; #ifndef PWM_EMBEDDED d->assign(reinterpret_cast<const char *>(decrypted), static_cast<string::size_type>(cryptLen)); #else d->assign((const char *)(decrypted), (string::size_type)(cryptLen)); #endif delete [] decrypted; if (algo == PWM_CRYPT_BLOWFISH) { if (!Blowfish::unpadNull(d)) { BUG(); return e_readFile; } } return e_success; } PwMerror PwMDoc::checkDataHash(char dataHashType, const string *dataHash, const string *dataStream) { PWM_ASSERT(dataHash); PWM_ASSERT(dataStream); switch(dataHashType) { case PWM_HASH_SHA1: { Sha1 hash; hash.sha1_write((byte*)dataStream->c_str(), dataStream->length()); string ret = hash.sha1_read(); if (ret != *dataHash) return e_fileCorrupt; break; } #ifndef PWM_EMBEDDED case PWM_HASH_SHA256: /*... fall through */ case PWM_HASH_SHA384: case PWM_HASH_SHA512: case PWM_HASH_MD5: case PWM_HASH_RMD160: case PWM_HASH_TIGER: { if (!LibGCryptIf::available()) return e_hashNotImpl; LibGCryptIf gc; PwMerror err; unsigned char *buf; size_t hashLen; err = gc.hash(&buf, &hashLen, reinterpret_cast<const unsigned char *>(dataStream->c_str()), dataStream->length(), dataHashType); if (err != e_success) return e_hashNotImpl; string calcHash(reinterpret_cast<const char *>(buf), static_cast<string::size_type>(hashLen)); delete [] buf; if (calcHash != *dataHash) return e_fileCorrupt; break; } #endif default: return e_hashNotImpl; } return e_success; } bool PwMDoc::lockAt(unsigned int category, unsigned int index, bool lock) { if (index >= numEntries(category)) { BUG(); return false; } if (lock == dta[category].d[index].lockStat) return true; if (!lock && currentPw != "") { // "unlocking" and "password is already set" if (!getDocStatFlag(DOC_STAT_UNLOCK_WITHOUT_PW)) { // unlocking without pw not allowed QString pw; pw = requestMpw(getDocStatFlag(DOC_STAT_USE_CHIPCARD)); if (pw != "") { if (pw != currentPw) { wrongMpwMsgBox(getDocStatFlag(DOC_STAT_USE_CHIPCARD)); return false; } else { timer()->start(DocTimer::id_mpwTimer); } } else { return false; } } else { timer()->start(DocTimer::id_mpwTimer); } } dta[category].d[index].lockStat = lock; dta[category].d[index].rev++; // increment revision counter. emitDataChanged(this); if (!lock) timer()->start(DocTimer::id_autoLockTimer); return true; } bool PwMDoc::lockAt(const QString &category,unsigned int index, bool lock) { unsigned int cat = 0; if (!findCategory(category, &cat)) { BUG(); return false; } return lockAt(cat, index, lock); } bool PwMDoc::lockAll(bool lock) { if (!lock && isDeepLocked()) { PwMerror ret; ret = deepLock(false); if (ret != e_success) return false; return true; } if (isDocEmpty()) { return true; } if (!lock && currentPw != "") { // unlocking and password is already set if (!getDocStatFlag(DOC_STAT_UNLOCK_WITHOUT_PW)) { // unlocking without pw not allowed QString pw; pw = requestMpw(getDocStatFlag(DOC_STAT_USE_CHIPCARD)); if (pw != "") { if (pw != currentPw) { wrongMpwMsgBox(getDocStatFlag(DOC_STAT_USE_CHIPCARD)); return false; } else { timer()->start(DocTimer::id_mpwTimer); } } else { return false; } } else { timer()->start(DocTimer::id_mpwTimer); } } vector<PwMCategoryItem>::iterator catBegin = dta.begin(), catEnd = dta.end(), catI = catBegin; vector<PwMDataItem>::iterator entrBegin, entrEnd, entrI; while (catI != catEnd) { entrBegin = catI->d.begin(); entrEnd = catI->d.end(); entrI = entrBegin; while (entrI != entrEnd) { entrI->lockStat = lock; entrI->rev++; // increment revision counter. ++entrI; } ++catI; } emitDataChanged(this); if (lock) timer()->stop(DocTimer::id_autoLockTimer); else timer()->start(DocTimer::id_autoLockTimer); return true; } bool PwMDoc::isLocked(const QString &category, unsigned int index) { unsigned int cat = 0; if (!findCategory(category, &cat)) { BUG(); return false; } return isLocked(cat, index); } bool PwMDoc::unlockAll_tempoary(bool revert) { static vector< vector<bool> > *oldLockStates = 0; static bool wasDeepLocked; if (revert) { // revert the unlocking if (oldLockStates) { /* we actually _have_ unlocked something, because * we have allocated space for the oldLockStates. * So, go on and revert them! */ if (wasDeepLocked) { PwMerror ret = deepLock(true); if (ret == e_success) { /* deep-lock succeed. We are save. * (but if it failed, just go on * lock them normally) */ delete_and_null(oldLockStates); timer()->start(DocTimer::id_autoLockTimer); printDebug("tempoary unlocking of dta " "reverted by deep-locking."); return true; } printDebug("deep-lock failed while reverting! " "Falling back to normal-lock."); } if (unlikely(!wasDeepLocked && numCategories() != oldLockStates->size())) { /* DOH! We have modified "dta" while * it was unlocked tempoary. DON'T DO THIS! */ BUG(); delete_and_null(oldLockStates); timer()->start(DocTimer::id_autoLockTimer); return false; } vector<PwMCategoryItem>::iterator catBegin = dta.begin(), catEnd = dta.end(), catI = catBegin; vector<PwMDataItem>::iterator entrBegin, entrEnd, entrI; vector< vector<bool> >::iterator oldCatStatI = oldLockStates->begin(); vector<bool>::iterator oldEntrStatBegin, oldEntrStatEnd, oldEntrStatI; while (catI != catEnd) { entrBegin = catI->d.begin(); entrEnd = catI->d.end(); entrI = entrBegin; if (likely(!wasDeepLocked)) { oldEntrStatBegin = oldCatStatI->begin(); oldEntrStatEnd = oldCatStatI->end(); oldEntrStatI = oldEntrStatBegin; if (unlikely(catI->d.size() != oldCatStatI->size())) { /* DOH! We have modified "dta" while * it was unlocked tempoary. DON'T DO THIS! */ BUG(); delete_and_null(oldLockStates); timer()->start(DocTimer::id_autoLockTimer); return false; } } while (entrI != entrEnd) { if (wasDeepLocked) { /* this is an error-fallback if * deeplock didn't succeed */ entrI->lockStat = true; } else { entrI->lockStat = *oldEntrStatI; } ++entrI; if (likely(!wasDeepLocked)) ++oldEntrStatI; } ++catI; if (likely(!wasDeepLocked)) ++oldCatStatI; } delete_and_null(oldLockStates); if (unlikely(wasDeepLocked)) { /* error fallback... */ unsetDocStatFlag(DOC_STAT_DEEPLOCKED); emitDataChanged(this); printDebug("WARNING: unlockAll_tempoary(true) " "deeplock fallback!"); } printDebug("tempoary unlocking of dta reverted."); } else { printDebug("unlockAll_tempoary(true): nothing to do."); } timer()->start(DocTimer::id_autoLockTimer); } else { // unlock all data tempoary if (unlikely(oldLockStates != 0)) { /* DOH! We have already unlocked the data tempoarly. * No need to do it twice. ;) */ BUG(); return false; } wasDeepLocked = false; bool mustUnlock = false; if (isDeepLocked()) { PwMerror ret; while (1) { ret = deepLock(false); if (ret == e_success) { break; } else if (ret == e_wrongPw) { wrongMpwMsgBox(getDocStatFlag(DOC_STAT_USE_CHIPCARD)); } else { printDebug("deep-unlocking failed while " "tempoary unlocking!"); return false; } } wasDeepLocked = true; mustUnlock = true; } else { // first check if it's needed to unlock some entries vector<PwMCategoryItem>::iterator catBegin = dta.begin(), catEnd = dta.end(), catI = catBegin; vector<PwMDataItem>::iterator entrBegin, entrEnd, entrI; while (catI != catEnd) { entrBegin = catI->d.begin(); entrEnd = catI->d.end(); entrI = entrBegin; while (entrI != entrEnd) { if (entrI->lockStat == true) { mustUnlock = true; break; } ++entrI; } if (mustUnlock) break; ++catI; } } if (!mustUnlock) { // nothing to do. timer()->stop(DocTimer::id_autoLockTimer); printDebug("unlockAll_tempoary(): nothing to do."); return true; } else if (!wasDeepLocked) { if (!getDocStatFlag(DOC_STAT_UNLOCK_WITHOUT_PW) && currentPw != "") { /* we can't unlock without mpw, so * we need to ask for it. */ QString pw; while (1) { pw = requestMpw(getDocStatFlag(DOC_STAT_USE_CHIPCARD)); if (pw == "") { return false; } else if (pw == currentPw) { break; } wrongMpwMsgBox(getDocStatFlag(DOC_STAT_USE_CHIPCARD)); } } } timer()->stop(DocTimer::id_autoLockTimer); oldLockStates = new vector< vector<bool> >; vector<bool> tmp_vec; vector<PwMCategoryItem>::iterator catBegin = dta.begin(), catEnd = dta.end(), catI = catBegin; vector<PwMDataItem>::iterator entrBegin, entrEnd, entrI; while (catI != catEnd) { entrBegin = catI->d.begin(); entrEnd = catI->d.end(); entrI = entrBegin; while (entrI != entrEnd) { if (!wasDeepLocked) { tmp_vec.push_back(entrI->lockStat); } entrI->lockStat = false; ++entrI; } if (!wasDeepLocked) { oldLockStates->push_back(tmp_vec); tmp_vec.clear(); } ++catI; } printDebug("tempoary unlocked dta."); } return true; } PwMerror PwMDoc::deepLock(bool lock, bool saveToFile) { PwMerror ret; if (lock) { if (isDeepLocked()) return e_lock; if (saveToFile) { if (isDocEmpty()) return e_docIsEmpty; ret = saveDoc(conf()->confGlobCompression()); if (ret == e_filename) { /* the doc wasn't saved to a file * by the user, yet. */ cantDeeplock_notSavedMsgBox(); return e_docNotSaved; } else if (ret != e_success) { return e_lock; } } timer()->stop(DocTimer::id_autoLockTimer); clearDoc(); PwMDataItem d; d.desc = IS_DEEPLOCKED_SHORTMSG.latin1(); d.comment = IS_DEEPLOCKED_MSG.latin1(); d.listViewPos = 0; addEntry(DEFAULT_CATEGORY, &d, true); lockAt(DEFAULT_CATEGORY, 0, true); unsetDocStatFlag(DOC_STAT_DISK_DIRTY); setDocStatFlag(DOC_STAT_DEEPLOCKED); } else { if (!isDeepLocked()) return e_lock; ret = openDoc(&filename, (conf()->confGlobUnlockOnOpen()) ? 0 : 1); if (ret == e_wrongPw) { return e_wrongPw; } else if (ret != e_success) { printDebug(string("PwMDoc::deepLock(false): ERR! openDoc() == ") + tostr(static_cast<int>(ret))); return e_lock; } unsetDocStatFlag(DOC_STAT_DEEPLOCKED); timer()->start(DocTimer::id_autoLockTimer); } emitDataChanged(this); return e_success; } void PwMDoc::_deepUnlock() { deepLock(false); } void PwMDoc::clearDoc() { dta.clear(); PwMCategoryItem d; d.name = DEFAULT_CATEGORY.latin1(); dta.push_back(d); currentPw = ""; unsetDocStatFlag(DOC_STAT_UNLOCK_WITHOUT_PW); } void PwMDoc::changeCurrentPw() { if (currentPw == "") return; // doc hasn't been saved. No mpw available. bool useChipcard = getDocStatFlag(DOC_STAT_USE_CHIPCARD); QString pw = requestMpwChange(¤tPw, &useChipcard); if (pw == "") return; if (useChipcard) setDocStatFlag(DOC_STAT_USE_CHIPCARD); else unsetDocStatFlag(DOC_STAT_USE_CHIPCARD); setCurrentPw(pw); } void PwMDoc::setListViewPos(const QString &category, unsigned int index, int pos) { unsigned int cat = 0; if (!findCategory(category, &cat)) { BUG(); return; } setListViewPos(cat, index, pos); } void PwMDoc::setListViewPos(unsigned int category, unsigned int index, int pos) { dta[category].d[index].listViewPos = pos; /* FIXME workaround: don't flag dirty, because this function sometimes * get's called when it shouldn't. It's because PwMView assumes * the user resorted the UI on behalf of signal layoutChanged(). * This is somewhat broken and incorrect, but I've no other * solution for now. */ // setDocStatFlag(DOC_STAT_DISK_DIRTY); } int PwMDoc::getListViewPos(const QString &category, unsigned int index) { unsigned int cat = 0; if (!findCategory(category, &cat)) { BUG(); return -1; } return dta[cat].d[index].listViewPos; } void PwMDoc::findEntry(unsigned int category, PwMDataItem find, unsigned int searchIn, vector<unsigned int> *foundPositions, bool breakAfterFound, bool caseSensitive, bool exactWordMatch, bool sortByLvp) { PWM_ASSERT(foundPositions); PWM_ASSERT(searchIn); foundPositions->clear(); unsigned int i, entries = numEntries(category); for (i = 0; i < entries; ++i) { if (searchIn & SEARCH_IN_DESC) { if (!compareString(find.desc, dta[category].d[i].desc, caseSensitive, exactWordMatch)) { continue; } } if (searchIn & SEARCH_IN_NAME) { if (!compareString(find.name, dta[category].d[i].name, caseSensitive, exactWordMatch)) { continue; } } if (searchIn & SEARCH_IN_PW) { bool wasLocked = isLocked(category, i); getDataChangedLock(); lockAt(category, i, false); if (!compareString(find.pw, dta[category].d[i].pw, caseSensitive, exactWordMatch)) { lockAt(category, i, wasLocked); putDataChangedLock(); continue; } lockAt(category, i, wasLocked); putDataChangedLock(); } if (searchIn & SEARCH_IN_COMMENT) { if (!compareString(find.comment, dta[category].d[i].comment, caseSensitive, exactWordMatch)) { continue; } } if (searchIn & SEARCH_IN_URL) { if (!compareString(find.url, dta[category].d[i].url, caseSensitive, exactWordMatch)) { continue; } } if (searchIn & SEARCH_IN_LAUNCHER) { if (!compareString(find.launcher, dta[category].d[i].launcher, caseSensitive, exactWordMatch)) { continue; } } // all selected "searchIn" matched. foundPositions->push_back(i); if (breakAfterFound) break; } if (sortByLvp && foundPositions->size() > 1) { vector< pair<unsigned int /* foundPosition (real doc pos) */, unsigned int /* lvp-pos */> > tmp_vec; unsigned int i, items = foundPositions->size(); pair<unsigned int, unsigned int> tmp_pair; for (i = 0; i < items; ++i) { tmp_pair.first = (*foundPositions)[i]; tmp_pair.second = dta[category].d[(*foundPositions)[i]].listViewPos; tmp_vec.push_back(tmp_pair); } sort(tmp_vec.begin(), tmp_vec.end(), dta_lvp_greater()); foundPositions->clear(); for (i = 0; i < items; ++i) { foundPositions->push_back(tmp_vec[i].first); } } } void PwMDoc::findEntry(const QString &category, PwMDataItem find, unsigned int searchIn, vector<unsigned int> *foundPositions, bool breakAfterFound, bool caseSensitive, bool exactWordMatch, bool sortByLvp) { PWM_ASSERT(foundPositions); unsigned int cat = 0; if (!findCategory(category, &cat)) { foundPositions->clear(); return; } findEntry(cat, find, searchIn, foundPositions, breakAfterFound, caseSensitive, exactWordMatch, sortByLvp); } bool PwMDoc::compareString(const string &s1, const string &s2, bool caseSensitive, bool exactWordMatch) { QString _s1(s1.c_str()); QString _s2(s2.c_str()); if (!caseSensitive) { _s1 = _s1.lower(); _s2 = _s2.lower(); } if (exactWordMatch ? (_s1 == _s2) : (_s2.find(_s1) != -1)) return true; return false; } bool PwMDoc::findCategory(const QString &name, unsigned int *index) { vector<PwMCategoryItem>::iterator i = dta.begin(), end = dta.end(); while (i != end) { if ((*i).name == name.latin1()) { if (index) { *index = i - dta.begin(); } return true; } ++i; } return false; } bool PwMDoc::renameCategory(const QString &category, const QString &newName) { unsigned int cat = 0; if (!findCategory(category, &cat)) return false; return renameCategory(cat, newName); } bool PwMDoc::renameCategory(unsigned int category, const QString &newName, bool dontFlagDirty) { if (category > numCategories() - 1) return false; dta[category].name = newName.latin1(); if (!dontFlagDirty) flagDirty(); return true; } bool PwMDoc::delCategory(const QString &category) { unsigned int cat = 0; if (!findCategory(category, &cat)) return false; return delCategory(cat); } bool PwMDoc::delCategory(unsigned int category, bool dontFlagDirty) { if (category > numCategories() - 1) return false; // We don't delete it, if it is the last existing // category! Instead we rename it to "Default". if (numCategories() > 1) { dta.erase(dta.begin() + category); } else { renameCategory(category, DEFAULT_CATEGORY, dontFlagDirty); return true; } if (!dontFlagDirty) flagDirty(); return true; } void PwMDoc::delAllEmptyCat(bool dontFlagDirty) { vector<PwMCategoryItem>::iterator begin = dta.begin(), end = dta.end(), i = begin; while (i != end) { if (i->d.empty()) { delCategory(begin - i, dontFlagDirty); } ++i; } } void PwMDoc::getCategoryList(vector<string> *list) { PWM_ASSERT(list); list->clear(); vector<PwMCategoryItem>::iterator i = dta.begin(), end = dta.end(); while (i != end) { list->push_back(i->name); ++i; } } void PwMDoc::getCategoryList(QStringList *list) { PWM_ASSERT(list); list->clear(); vector<PwMCategoryItem>::iterator i = dta.begin(), end = dta.end(); while (i != end) { #ifndef PWM_EMBEDDED list->push_back(i->name.c_str()); #else list->append(i->name.c_str()); #endif ++i; } } void PwMDoc::getEntryList(const QString &category, QStringList *list) { PWM_ASSERT(list); unsigned int cat = 0; if (!findCategory(category, &cat)) { list->clear(); return; } getEntryList(cat, list); } void PwMDoc::getEntryList(const QString &category, vector<string> *list) { PWM_ASSERT(list); unsigned int cat = 0; if (!findCategory(category, &cat)) { list->clear(); return; } getEntryList(cat, list); } void PwMDoc::getEntryList(unsigned int category, vector<string> *list) { PWM_ASSERT(list); list->clear(); vector<PwMDataItem>::iterator begin = dta[category].d.begin(), end = dta[category].d.end(), i = begin; while (i != end) { list->push_back(i->desc); ++i; } } void PwMDoc::getEntryList(unsigned int category, QStringList *list) { PWM_ASSERT(list); list->clear(); vector<PwMDataItem>::iterator begin = dta[category].d.begin(), end = dta[category].d.end(), i = begin; while (i != end) { #ifndef PWM_EMBEDDED list->push_back(i->desc.c_str()); #else list->append(i->desc.c_str()); #endif ++i; } } bool PwMDoc::execLauncher(const QString &category, unsigned int entryIndex) { unsigned int cat = 0; if (!findCategory(category, &cat)) return false; return execLauncher(cat, entryIndex); } bool PwMDoc::execLauncher(unsigned int category, unsigned int entryIndex) { if (geteuid() == 0) { rootAlertMsgBox(); return false; } QString command(dta[category].d[entryIndex].launcher.c_str()); bool wasLocked = isLocked(category, entryIndex); if (command.find("$p") != -1) { /* the user requested the password to be included * into the command. We have to ask for the password, * if it's locked. We do that by unlocking the entry */ if (!lockAt(category, entryIndex, false)) return false; } #ifndef PWM_EMBEDDED command.replace("$d", dta[category].d[entryIndex].desc.c_str()); command.replace("$n", dta[category].d[entryIndex].name.c_str()); command.replace("$p", dta[category].d[entryIndex].pw.c_str()); command.replace("$u", dta[category].d[entryIndex].url.c_str()); command.replace("$c", dta[category].d[entryIndex].comment.c_str()); #else command.replace(QRegExp("$d"), dta[category].d[entryIndex].desc.c_str()); command.replace(QRegExp("$n"), dta[category].d[entryIndex].name.c_str()); command.replace(QRegExp("$p"), dta[category].d[entryIndex].pw.c_str()); command.replace(QRegExp("$u"), dta[category].d[entryIndex].url.c_str()); command.replace(QRegExp("$c"), dta[category].d[entryIndex].comment.c_str()); #endif command.append(" &"); QString customXterm(conf()->confGlobXtermCommand()); if (!customXterm.isEmpty()) command = customXterm + " " + command; system(command.latin1()); lockAt(category, entryIndex, wasLocked); return true; } bool PwMDoc::goToURL(const QString &category, unsigned int entryIndex) { unsigned int cat = 0; if (!findCategory(category, &cat)) return false; return goToURL(cat, entryIndex); } bool PwMDoc::goToURL(unsigned int category, unsigned int entryIndex) { if (geteuid() == 0) { rootAlertMsgBox(); return false; } QString url(dta[category].d[entryIndex].url.c_str()); if (url.isEmpty()) return false; QString customBrowser(conf()->confGlobBrowserCommand()); if (!customBrowser.isEmpty()) { browserProc.clearArguments(); browserProc << customBrowser << url; if (browserProc.start(KProcess::DontCare)) return true; } browserProc.clearArguments(); browserProc << "konqueror" << url; if (browserProc.start(KProcess::DontCare)) return true; browserProc.clearArguments(); browserProc << "mozilla" << url; if (browserProc.start(KProcess::DontCare)) return true; browserProc.clearArguments(); browserProc << "opera" << url; if (browserProc.start(KProcess::DontCare)) return true; return false; } PwMerror PwMDoc::exportToText(const QString *file) { PWM_ASSERT(file); if (QFile::exists(*file)) { if (!QFile::remove(*file)) return e_accessFile; } QFile f(*file); if (!f.open(IO_ReadWrite)) return e_openFile; if (!unlockAll_tempoary()) { f.close(); return e_lock; } // write header string header = i18n("Password table generated by\nPwM v").latin1(); header += PACKAGE_VER; header += i18n("\non ").latin1(); QDate currDate = QDate::currentDate(); QTime currTime = QTime::currentTime(); #ifndef PWM_EMBEDDED header += currDate.toString("ddd MMMM d ").latin1(); header += currTime.toString("hh:mm:ss ").latin1(); #else QString dfs = KGlobal::locale()->dateFormatShort(); bool ampm = KGlobal::locale()->use12Clock(); KGlobal::locale()->setDateFormatShort("%A %B %d"); KGlobal::locale()->setHore24Format(true); header += KGlobal::locale()->formatDate(currDate, true, KLocale::Userdefined); header += KGlobal::locale()->formatTime(currTime, true); KGlobal::locale()->setDateFormatShort(dfs); KGlobal::locale()->setHore24Format(!ampm); #endif header += tostr(currDate.year()); header += "\n==============================\n\n"; #ifndef PWM_EMBEDDED if (f.writeBlock(header.c_str(), header.length()) != (Q_LONG)header.length()) { unlockAll_tempoary(true); f.close(); return e_writeFile; } #else if (f.writeBlock(header.c_str(), header.length()) != (long)header.length()) { unlockAll_tempoary(true); f.close(); return e_writeFile; } #endif unsigned int i, numCat = numCategories(); unsigned int j, numEnt; string exp; for (i = 0; i < numCat; ++i) { numEnt = numEntries(i); exp = "\n== Category: "; exp += dta[i].name; exp += " ==\n"; #ifndef PWM_EMBEDDED if (f.writeBlock(exp.c_str(), exp.length()) != (Q_LONG)exp.length()) { unlockAll_tempoary(true); f.close(); return e_writeFile; } #else if (f.writeBlock(exp.c_str(), exp.length()) != (long)exp.length()) { unlockAll_tempoary(true); f.close(); return e_writeFile; } #endif for (j = 0; j < numEnt; ++j) { exp = "\n-- "; exp += dta[i].d[j].desc; exp += " --\n"; exp += i18n("Username: ").latin1(); exp += dta[i].d[j].name; exp += "\n"; exp += i18n("Password: ").latin1(); exp += dta[i].d[j].pw; exp += "\n"; exp += i18n("Comment: ").latin1(); exp += dta[i].d[j].comment; exp += "\n"; exp += i18n("URL: ").latin1(); exp += dta[i].d[j].url; exp += "\n"; exp += i18n("Launcher: ").latin1(); exp += dta[i].d[j].launcher; exp += "\n"; #ifndef PWM_EMBEDDED if (f.writeBlock(exp.c_str(), exp.length()) != (Q_LONG)exp.length()) { unlockAll_tempoary(true); f.close(); return e_writeFile; } #else if (f.writeBlock(exp.c_str(), exp.length()) != (long)exp.length()) { unlockAll_tempoary(true); f.close(); return e_writeFile; } #endif } } unlockAll_tempoary(true); f.close(); return e_success; } PwMerror PwMDoc::importFromText(const QString *file, int format) { PWM_ASSERT(file); if (format == 0) return importText_PwM(file); else if (format == -1) { // probe for all formats if (importText_PwM(file) == e_success) return e_success; dta.clear(); emitDataChanged(this); // add next format here... return e_fileFormat; } return e_invalidArg; } PwMerror PwMDoc::importText_PwM(const QString *file) { PWM_ASSERT(file); FILE *f; int tmp; ssize_t ret; string curCat; unsigned int entriesRead = 0; PwMDataItem currItem; f = fopen(file->latin1(), "r"); if (!f) return e_openFile; size_t ch_tmp_size = 1024; char *ch_tmp = (char*)malloc(ch_tmp_size); if (!ch_tmp) { fclose(f); return e_outOfMem; } // - check header if (getline(&ch_tmp, &ch_tmp_size, f) == -1) // skip first line. goto formatError; // check version-string and return version in "ch_tmp". if (fscanf(f, "PwM v%s", ch_tmp) != 1) { // header not recognized as PwM generated header goto formatError; } // set filepointer behind version-string-line previously checked if (getline(&ch_tmp, &ch_tmp_size, f) == -1) goto formatError; // skip next line containing the build-date if (getline(&ch_tmp, &ch_tmp_size, f) == -1) goto formatError; // read header termination line if (getline(&ch_tmp, &ch_tmp_size, f) == -1) goto formatError; if (strcmp(ch_tmp, "==============================\n")) goto formatError; // - read entries do { // find beginning of next category do { tmp = fgetc(f); } while (tmp == '\n' && tmp != EOF); if (tmp == EOF) break; // decrement filepos by one fseek(f, -1, SEEK_CUR); // read cat-name if (getline(&ch_tmp, &ch_tmp_size, f) == -1) goto formatError; // check cat-name format if (memcmp(ch_tmp, "== Category: ", 13) != 0) goto formatError; if (memcmp(ch_tmp + (strlen(ch_tmp) - 1 - 3), " ==", 3) != 0) goto formatError; // copy cat-name curCat.assign(ch_tmp + 13, strlen(ch_tmp) - 1 - 16); do { // find beginning of next entry do { tmp = fgetc(f); } while (tmp == '\n' && tmp != EOF && tmp != '='); if (tmp == EOF) break; if (tmp == '=') { fseek(f, -1, SEEK_CUR); break; } // decrement filepos by one fseek(f, -1, SEEK_CUR); // read desc-line if (getline(&ch_tmp, &ch_tmp_size, f) == -1) goto formatError; // check desc-line format if (memcmp(ch_tmp, "-- ", 3) != 0) goto formatError; if (memcmp(ch_tmp + (strlen(ch_tmp) - 1 - 3), " --", 3) != 0) goto formatError; // add desc-line currItem.desc.assign(ch_tmp + 3, strlen(ch_tmp) - 1 - 6); // read username-line if ((ret = getline(&ch_tmp, &ch_tmp_size, f)) == -1) goto formatError; if (!textExtractEntry_PwM(ch_tmp, ret, &currItem.name)) goto formatError; // read pw-line if ((ret = getline(&ch_tmp, &ch_tmp_size, f)) == -1) goto formatError; if (!textExtractEntry_PwM(ch_tmp, ret, &currItem.pw)) goto formatError; // read comment-line if ((ret = getline(&ch_tmp, &ch_tmp_size, f)) == -1) goto formatError; if (!textExtractEntry_PwM(ch_tmp, ret, &currItem.comment)) goto formatError; // read URL-line if ((ret = getline(&ch_tmp, &ch_tmp_size, f)) == -1) goto formatError; if (!textExtractEntry_PwM(ch_tmp, ret, &currItem.url)) goto formatError; // read launcher-line if ((ret = getline(&ch_tmp, &ch_tmp_size, f)) == -1) goto formatError; if (!textExtractEntry_PwM(ch_tmp, ret, &currItem.launcher)) goto formatError; currItem.lockStat = true; currItem.listViewPos = -1; addEntry(curCat.c_str(), &currItem, true); ++entriesRead; } while (1); } while (1); if (!entriesRead) goto formatError; free(ch_tmp); fclose(f); flagDirty(); return e_success; formatError: free(ch_tmp); fclose(f); return e_fileFormat; } bool PwMDoc::textExtractEntry_PwM(const char *in, ssize_t in_size, string *out) { PWM_ASSERT(in && out); ssize_t i = 0, len = in_size - 1; while (i < len) { if (in[i] == ':') break; ++i; } i += 2; *out = ""; out->append(in + i, in_size - i - 1); return true; } PwMerror PwMDoc::exportToGpasman(const QString *file) { PWM_ASSERT(file); GpasmanFile gp; int ret; if (!unlockAll_tempoary()) return e_lock; QString gpmPassword; while (1) { gpmPassword = requestNewMpw(0); if (gpmPassword == "") { unlockAll_tempoary(true); return e_noPw; } if (gpmPassword.length() < 4) { gpmPwLenErrMsgBox(); } else { break; } } ret = gp.save_init(file->latin1(), gpmPassword.latin1()); if (ret != 1) { unlockAll_tempoary(true); return e_accessFile; } char *entry[4]; unsigned int numCat = numCategories(), i; unsigned int numEntr, j; int descLen, nameLen, pwLen, commentLen; for (i = 0; i < numCat; ++i) { numEntr = numEntries(i); for (j = 0; j < numEntr; ++j) { descLen = dta[i].d[j].desc.length(); nameLen = dta[i].d[j].name.length(); pwLen = dta[i].d[j].pw.length(); commentLen = dta[i].d[j].comment.length(); entry[0] = new char[descLen + 1]; entry[1] = new char[nameLen + 1]; entry[2] = new char[pwLen + 1]; entry[3] = new char[commentLen + 1]; strcpy(entry[0], descLen == 0 ? " " : dta[i].d[j].desc.c_str()); strcpy(entry[1], nameLen == 0 ? " " : dta[i].d[j].name.c_str()); strcpy(entry[2], pwLen == 0 ? " " : dta[i].d[j].pw.c_str()); strcpy(entry[3], commentLen == 0 ? " " : dta[i].d[j].comment.c_str()); entry[0][descLen == 0 ? descLen + 1 : descLen] = '\0'; entry[1][nameLen == 0 ? nameLen + 1 : nameLen] = '\0'; entry[2][pwLen == 0 ? pwLen + 1 : pwLen] = '\0'; entry[3][commentLen == 0 ? commentLen + 1 : commentLen] = '\0'; ret = gp.save_entry(entry); if (ret == -1){ delete [] entry[0]; delete [] entry[1]; delete [] entry[2]; delete [] entry[3]; gp.save_finalize(); unlockAll_tempoary(true); return e_writeFile; } delete [] entry[0]; delete [] entry[1]; delete [] entry[2]; delete [] entry[3]; } } unlockAll_tempoary(true); if (gp.save_finalize() == -1) return e_writeFile; return e_success; } PwMerror PwMDoc::importFromGpasman(const QString *file) { PWM_ASSERT(file); QString pw = requestMpw(false); if (pw == "") return e_noPw; GpasmanFile gp; int ret, i; PwMerror ret2; char *entry[4]; PwMDataItem tmpData; ret = gp.load_init(file->latin1(), pw.latin1()); if (ret != 1) return e_accessFile; do { ret = gp.load_entry(entry); if(ret != 1) break; tmpData.desc = entry[0]; tmpData.name = entry[1]; tmpData.pw = entry[2]; tmpData.comment = entry[3]; tmpData.lockStat = true; tmpData.listViewPos = -1; ret2 = addEntry(DEFAULT_CATEGORY, &tmpData, true); for (i = 0; i < 4; ++i) free(entry[i]); if (ret2 == e_maxAllowedEntr) { gp.load_finalize(); return e_maxAllowedEntr; } } while (1); gp.load_finalize(); if (isDocEmpty()) return e_wrongPw; // we assume this. flagDirty(); return e_success; } void PwMDoc::ensureLvp() { if (isDocEmpty()) return; vector< vector<PwMDataItem>::iterator > undefined; vector< vector<PwMDataItem>::iterator >::iterator undefBegin, undefEnd, undefI; vector<PwMCategoryItem>::iterator catBegin = dta.begin(), catEnd = dta.end(), catI = catBegin; vector<PwMDataItem>::iterator entrBegin, entrEnd, entrI; int lvpTop, tmpLvp; while (catI != catEnd) { lvpTop = -1; undefined.clear(); entrBegin = catI->d.begin(); entrEnd = catI->d.end(); entrI = entrBegin; while (entrI != entrEnd) { tmpLvp = entrI->listViewPos; if (tmpLvp == -1) undefined.push_back(entrI); else if (tmpLvp > lvpTop) lvpTop = tmpLvp; ++entrI; } undefBegin = undefined.begin(); undefEnd = undefined.end(); undefI = undefBegin; while (undefI != undefEnd) { (*undefI)->listViewPos = ++lvpTop; ++undefI; } ++catI; } } QString PwMDoc::getTitle() { /* NOTE: We have to ensure, that the returned title * is unique and not reused somewhere else while * this document is valid (open). */ QString title(getFilename()); if (title.isEmpty()) { if (unnamedNum == 0) { unnamedNum = PwMDocList::getNewUnnamedNumber(); PWM_ASSERT(unnamedNum != 0); } title = DEFAULT_TITLE; title += " "; title += tostr(unnamedNum).c_str(); } return title; } bool PwMDoc::tryDelete() { if (deleted) return true; int ret; if (isDirty()) { ret = dirtyAskSave(getTitle()); if (ret == 0) { // save to disk if (!saveDocUi(this)) goto out_ignore; } else if (ret == 1) { // don't save and delete goto out_accept; } else { // cancel operation goto out_ignore; } } out_accept: deleted = true; delete this; return true; out_ignore: return false; } #ifndef PWM_EMBEDDED #include "pwmdoc.moc" #endif diff --git a/pwmanager/pwmanager/pwmdoc.h b/pwmanager/pwmanager/pwmdoc.h index 9650d55..193247e 100644 --- a/pwmanager/pwmanager/pwmdoc.h +++ b/pwmanager/pwmanager/pwmdoc.h @@ -1,701 +1,701 @@ /*************************************************************************** * * * copyright (C) 2003, 2004 by Michael Buesch * * email: mbuesch@freenet.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License version 2 * * as published by the Free Software Foundation. * * * ***************************************************************************/ /*************************************************************************** * copyright (C) 2004 by Ulf Schenk * This file is originaly based on version 2.0 of pwmanager * and was modified to run on embedded devices that run microkde * * $Id$ **************************************************************************/ #ifndef __PWMDOC_H #define __PWMDOC_H #define PWM_FILE_VER (static_cast<char>(0x05)) #define PWM_HASH_SHA1 (static_cast<char>(0x01)) #define PWM_HASH_SHA256 (static_cast<char>(0x02)) #define PWM_HASH_SHA384 (static_cast<char>(0x03)) #define PWM_HASH_SHA512 (static_cast<char>(0x04)) #define PWM_HASH_MD5 (static_cast<char>(0x05)) #define PWM_HASH_RMD160 (static_cast<char>(0x06)) #define PWM_HASH_TIGER (static_cast<char>(0x07)) #define PWM_CRYPT_BLOWFISH (static_cast<char>(0x01)) #define PWM_CRYPT_AES128 (static_cast<char>(0x02)) #define PWM_CRYPT_AES192 (static_cast<char>(0x03)) #define PWM_CRYPT_AES256 (static_cast<char>(0x04)) #define PWM_CRYPT_3DES (static_cast<char>(0x05)) #define PWM_CRYPT_TWOFISH (static_cast<char>(0x06)) #define PWM_CRYPT_TWOFISH128 (static_cast<char>(0x07)) #define PWM_COMPRESS_NONE (static_cast<char>(0x00)) #define PWM_COMPRESS_GZIP (static_cast<char>(0x01)) #define PWM_COMPRESS_BZIP2 (static_cast<char>(0x02)) #define DEFAULT_MAX_ENTRIES (~(static_cast<unsigned int>(0))) #define FILE_ID_HEADER "PWM_PASSWORD_FILE" #include "pwmexception.h" #include "pwmdocui.h" -#include "configuration.h" #include <qobject.h> #include <qtimer.h> #include <qdatetime.h> #include <kprocess.h> #ifndef PWM_EMBEDDED +#include "configuration.h" #else #include <kapplication.h> #endif #include <string> #include <vector> #include <utility> using std::vector; using std::string; using std::pair; /* used in findEntry() function */ #define SEARCH_IN_DESC (1) #define SEARCH_IN_NAME (1 << 1) #define SEARCH_IN_PW (1 << 2) #define SEARCH_IN_COMMENT (1 << 3) #define SEARCH_IN_URL (1 << 4) #define SEARCH_IN_LAUNCHER (1 << 5) #define SEARCH_IN_ALL (SEARCH_IN_DESC | SEARCH_IN_NAME | \ SEARCH_IN_PW | SEARCH_IN_COMMENT | \ SEARCH_IN_URL | SEARCH_IN_LAUNCHER) /** document deeplocked. Data is out for lunch to disk */ #define DOC_STAT_DEEPLOCKED (1) /** encrypted document on disk is dirty. data has to go to disk. */ #define DOC_STAT_DISK_DIRTY (1 << 1) /** we are using a chipcard to encrypt the data */ #define DOC_STAT_USE_CHIPCARD (1 << 2) /** use "currentPw" to unlock. (This flag is set/unset by a timer) */ #define DOC_STAT_UNLOCK_WITHOUT_PW (1 << 3) class PwMDoc; class PwMView; class QFile; /* meta data for a PwMDataItem */ struct PwMMetaData { PwMMetaData() : updateInt (0) { } /** creation date of the PwMDataItem to which * this meta data belongs. */ QDateTime create; /** becomes valid on this date */ QDateTime valid; /** expire date */ QDateTime expire; /** update date (last updated at this date) */ QDateTime update; /** update interval (in minutes). Time since the * last update to remind the user to update the item. * 0 disables. */ unsigned long updateInt; //US ENH: enhancements of the filestructure /* each entry gets a unique id assigned */ QString uniqueid; void clear() { create = QDateTime(); expire = QDateTime(); update = QDateTime(); updateInt = 0; uniqueid = KApplication::randomString(8); } inline bool isValid() const { if (valid.isNull()) return true; return (valid < QDateTime::currentDateTime()); } inline bool isExpired() const { if (expire.isNull()) return false; return (expire < QDateTime::currentDateTime()); } inline bool isUpdateIntOver() const { if (updateInt == 0 || update.isNull()) return false; QDateTime d(update); return (d.addSecs(updateInt * 60) < QDateTime::currentDateTime()); } }; struct PwMDataItem { PwMDataItem() : lockStat (true) , listViewPos (-1) , binary (false) , rev (0) { } /** password description */ string desc; /** user-name */ string name; /** the password itself */ string pw; /** some comment */ string comment; /** an URL string */ string url; /** launcher. Can be executed as a system() command */ string launcher; /** locking status. If locked (true), pw is not emitted through getEntry() */ bool lockStat; /** position of this item in main "list-view" * If -1, the position is not yet specified and should be appended to the list */ int listViewPos; /** does this entry contain binary data? */ bool binary; /** meta data for this data item. */ PwMMetaData meta; /** data revision counter. This counter can be used * to easily, efficiently determine if this data item * has changed since some time. * This counter is incremented on every update. */ unsigned int rev; void clear(bool clearMeta = true) { /* NOTE: Don't use .clear() here to be * backward compatible with gcc-2 (Debian Woody) */ desc = ""; name = ""; pw = ""; comment = ""; url = ""; launcher = ""; lockStat = true; listViewPos = -1; binary = false; if (clearMeta) meta.clear(); } }; struct PwMCategoryItem { /** all PwMDataItems (all passwords) within this category */ vector<PwMDataItem> d; /** category name/description */ string name; void clear() { d.clear(); name = ""; } }; /** "Function Object" for sort()ing PwMDataItem::listViewPos */ class dta_lvp_greater { public: bool operator() (const pair<unsigned int, unsigned int> &d1, const pair<unsigned int, unsigned int> &d2) { return d1.second > d2.second; } }; /** list of PwMDoc documents and it's IDs */ class PwMDocList { public: struct listItem { /** document filename (known as ID, here) */ string docId; /** pointer to the document class */ PwMDoc *doc; }; PwMDocList() {} /** add a new item to the list */ void add(PwMDoc *doc, const string &id); /** changes the contents of an existing item */ void edit(PwMDoc *doc, const string &newId); /** remove the given item */ void del(PwMDoc *doc); /** get the item at index */ listItem getAt(int index) { return docList[index]; } /** find an entry with this id */ bool find(const string &id, listItem *ret = 0); /** returns a copy of the list */ const vector<listItem>* getList() const { return &docList; } /** returns a new unique number to extend the name of * an unnamed document. */ static unsigned int getNewUnnamedNumber() { return unnamedDocCnt++; } protected: /* Hm, I think we shouldn't really use a "list" here, should we? * So I decided to actually use a vector. */ vector<listItem> docList; /** This value is used to get a new number for yet unnamed * documents. It is incremented on every request. So it's * theoretically possible to overflow it, but... :) */ static unsigned int unnamedDocCnt; }; /** implements timers for the document */ class DocTimer : public QObject { Q_OBJECT public: enum TimerIDs { id_mpwTimer, id_autoLockTimer, id_metaCheckTimer }; public: DocTimer(PwMDoc *_doc); ~DocTimer(); /** start the timer */ void start(TimerIDs timer); /** stop the timer */ void stop(TimerIDs timer); /** get the lock for a timer. * This lock is a recursive lock. When a lock is * held, the timer will be stopped and timeout is * guaranteed to not happen */ void getLock(TimerIDs timer); /** put a recursive timer lock */ void putLock(TimerIDs timer); protected slots: /** timeout slot for the mpw timer */ void mpwTimeout(); /** timeout slot for the autoLock timer */ void autoLockTimeout(); /** timeout slot for the metaCheck timer */ void metaCheckTimeout(); protected: /** pointer to the document associated with this timer. */ PwMDoc *doc; /** timer object for mpw timer */ QTimer *mpwTimer; /** timer object for the autoLock timer */ QTimer *autoLockTimer; /** timer object for the metaCheck timer */ QTimer *metaCheckTimer; /** lock counter for the mpw timer */ unsigned int mpwLock; /** lock counter for the autoLock timer */ unsigned int autoLockLock; /** lock counter for the metaCheck timer */ unsigned int metaCheckLock; }; /** Document class for PwM */ class PwMDoc : public PwMDocUi { Q_OBJECT friend class DocTimer; public: /** construtor */ PwMDoc(QObject* parent = 0, const char *name = 0); /** destructor */ ~PwMDoc(); /** returns a pointer to a list of all open documents */ static PwMDocList* getOpenDocList() { return &openDocList; } /** flag document dirty. dta changed */ void flagDirty() { setDocStatFlag(DOC_STAT_DISK_DIRTY); emitDataChanged(this); } /** modified? */ bool isDirty() { return getDocStatFlag(DOC_STAT_DISK_DIRTY); } /** save document to disk */ PwMerror saveDoc(char compress, const QString *file = 0); /** read document from file. * "openLocked is must be set to either of these values: * 0 == open with all entries unlocked * 1 == open with all entries locked * 2 == open deep-locked */ PwMerror openDoc(const QString *file, int openLocked); /** export document to ascii-textfile */ PwMerror exportToText(const QString *file); /** export document to gpasman / kpasman file */ PwMerror exportToGpasman(const QString *file); /** import document from ascii-textfile */ PwMerror importFromText(const QString *file, int format = -1); /** import document from gpasman / kpasman file */ PwMerror importFromGpasman(const QString *file); /** add new entry */ PwMerror addEntry(const QString &category, PwMDataItem *d, bool dontFlagDirty = false, bool updateMeta = true); /** add new category. This function doesn't flag the document dirty! */ PwMerror addCategory(const QString &category, unsigned int *categoryIndex, bool checkIfExist = true); /** rename an existing category */ bool renameCategory(const QString &category, const QString &newName); /** rename an existing category */ bool renameCategory(unsigned int category, const QString &newName, bool dontFlagDirty = false); /** delete an existing category */ bool delCategory(const QString &category); /** delete an existing category */ bool delCategory(unsigned int category, bool dontFlagDirty = false); /** returns a list of all category-names */ void getCategoryList(vector<string> *list); /** returns a list of all category-names */ void getCategoryList(QStringList *list); /** returns a list of all entry-descs in the given category */ void getEntryList(const QString &category, QStringList *list); /** returns a list of all entry-descs in the given category */ void getEntryList(const QString &category, vector<string> *list); /** returns a list of all entry-descs in the given category */ void getEntryList(unsigned int category, vector<string> *list); /** returns a list of all entry-descs in the given category */ void getEntryList(unsigned int category, QStringList *list); /** delete entry */ bool delEntry(const QString &category, unsigned int index, bool dontFlagDirty = false); /** delete entry */ bool delEntry(unsigned int category, unsigned int index, bool dontFlagDirty = false); /** edit entry */ bool editEntry(const QString &oldCategory, const QString &newCategory, unsigned int index, PwMDataItem *d, bool updateMeta = true); /** edit entry */ bool editEntry(unsigned int oldCategory, const QString &newCategory, unsigned int index, PwMDataItem *d, bool updateMeta = true); /** finds the category with the "name" and return it's index */ bool findCategory(const QString &name, unsigned int *index); /** search for an entry "find" and check while searching only for * the data-fields specified by "searchIn". To set the "searchIn" * value, we may use one or more of the SEARCH_IN_* defines at * the top of this header-file. It returns the positions of all * matched entries in "foundPositions". If "breakAfterFound" is true, * the function terminates after the first occurence of the entry * and doesn't go on searching. So foundPositions->size() is never * > 1 if breakAfterFound is true. */ void findEntry(unsigned int category, PwMDataItem find, unsigned int searchIn, vector<unsigned int> *foundPositions, bool breakAfterFound = false, bool caseSensitive = true, bool exactWordMatch = true, bool sortByLvp = false); /** see the above funtion. This function allows to set the category by name. */ void findEntry(const QString &category, PwMDataItem find, unsigned int searchIn, vector<unsigned int> *foundPositions, bool breakAfterFound = false, bool caseSensitive = true, bool exactWordMatch = true, bool sortByLvp = false); /** returns number of entries */ unsigned int numEntries(const QString &category); unsigned int numEntries(unsigned int category) { return dta[category].d.size(); } /** returns number of categories */ unsigned int numCategories() { return dta.size(); } /** returns the name of the category at "index" */ const string* getCategory(unsigned int index) { return (&(dta[index].name)); } /** returns the data of item at "index". * It unlocks the entry if it's locked and unlockIfLocked is true. * If the entry is locked, but unlockIfLocked is false, it'll not return * the pw. */ bool getEntry(const QString &category, unsigned int index, PwMDataItem *d, bool unlockIfLocked = false); bool getEntry(unsigned int category, unsigned int index, PwMDataItem *d, bool unlockIfLocked = false); /** returns the comment-string by looking at the category * and the listViewPos */ PwMerror getCommentByLvp(const QString &category, int listViewPos, string *foundComment); /** checks if a password is already available. (currentPw) */ bool isPwAvailable() { return (currentPw != ""); } /** un/lock entry at "index". If needed, ask for password. */ bool lockAt(const QString &category, unsigned int index, bool lock = true); bool lockAt(unsigned int category, unsigned int index, bool lock = true); /** returns the lock-status at "index" */ bool isLocked(const QString &category, unsigned int index); bool isLocked(unsigned int category, unsigned int index) { return dta[category].d[index].lockStat; } /** returns the deeplock status */ bool isDeepLocked() { return getDocStatFlag(DOC_STAT_DEEPLOCKED); } /** (un)lock all entries */ bool lockAll(bool lock); /** unlocks all entries tempoarly. * 1st NOTE: Be very careful with this function! :) * 2nd NOTE: After you have called unlockAll_Tempoary(); , * please DON'T forget to call unlockAll_Tempoary(true); * _before_ the user (or someone else) is able to change * the document! * 3rd NOTE: Please DON'T change "dta" while the data is tempoary * unlocked! This will cause corruption. */ bool unlockAll_tempoary(bool revert = false); /** deep-(un)locks the document. * deep-locking writes all data to the file, deletes all data * in memory, but doesn't close the document. * deep-locking is only available, if the user previously saved * the doc to a file (with a password). * If "saveToFile" is false, it does NOT write the data to the file! */ PwMerror deepLock(bool lock = true, bool saveToFile = true); /** is unlockable without pw? */ bool unlockWoPw() { return getDocStatFlag(DOC_STAT_UNLOCK_WITHOUT_PW); } /** get the "currentPassword" */ const QString& getCurrentPw() { return currentPw; } /** open a window and request the user to change the mpw */ void changeCurrentPw(); /** set the "listViewPos" variable of "dta" */ void setListViewPos(const QString &category, unsigned int index, int pos); /** set the "listViewPos" variable of "dta" */ void setListViewPos(unsigned int category, unsigned int index, int pos); /** get the "listViewPos" variable of "dta" */ int getListViewPos(const QString &category, unsigned int index); /** set the maximum number of entries allowed */ void setMaxNumEntries(unsigned int num = DEFAULT_MAX_ENTRIES) { maxEntries = num; } /** get the maximum number of entries allowed */ unsigned int getMaxNumEntries() { return maxEntries; } /** ensure all listViewPos of all dta items are set. (are ! -1). * If there are some undefined entries, add them to the end of * the listViewPos(itions). */ void ensureLvp(); /** execute the "launcher" of this entry */ bool execLauncher(const QString &category, unsigned int entryIndex); /** see above */ bool execLauncher(unsigned int category, unsigned int entryIndex); /** open a browser with the URL-section of the given entry */ bool goToURL(const QString &category, unsigned int entryIndex); /** see above */ bool goToURL(unsigned int category, unsigned int entryIndex); /** returns true if there is no entry present in the document. * Note: The "default" Category is present everytime, so * it's checked for it's entries. */ bool isDocEmpty() { if (numCategories() > 1) return false; if (numEntries(0)) return false; return true; } /** returns the filename of this doc */ const QString& getFilename() { return filename; } /** returns the title of the doc */ QString getTitle(); /** sets the list-view-pointer hold in the doc */ void setListViewPointer(PwMView *_listView) { listView = _listView; } /** returns the list-view-pointer */ PwMView * getListViewPointer() { return listView; } /** try to delete the doc. The user may be asked to save * the data. The user may cancel the whole operation. * false is returned, then. */ bool tryDelete(); /** is the doc deleted? (with tryDelete() ) */ bool isDeleted() { return deleted; } /** returns the document timer object */ DocTimer * timer() { return _timer; } /** get a lock on the dataChanged signal. * If someone is holding a lock, the signal is not emitted. */ void getDataChangedLock() { ++dataChangedLock; } /** put the dataChanged lock */ void putDataChangedLock() { --dataChangedLock; } /** returns the revision count of the item at cat/index */ unsigned int getEntryRevCnt(unsigned int category, unsigned int index) { return dta[category].d[index].rev; } /** returns a const pointer to the entries meta */ const PwMMetaData * getEntryMeta(unsigned int category, unsigned int index) { return &(dta[category].d[index].meta); } /** is the entry at "category" "index" a binary entry? */ bool isBinEntry(unsigned int category, unsigned int index) { return dta[category].d[index].binary; } public slots: /** wrapper for PwMTray */ void _deepUnlock(); signals: /** the data of the document has changed and must be updated * in all views. * NOTE: use emitDataChanged(PwMDoc *document) to emit this signal! */ void dataChanged(PwMDoc *document); /** the document class is going to close. This signal may be * used to nofify all views, that the user closed the document, * so the views can go down, too. */ void docClosed(PwMDoc *document); /** somebody just opened the document */ void docOpened(PwMDoc *document); /** this document object just got created */ void docCreated(PwMDoc *document); public: /** emit the dataChanged signal after checking for a lock */ void emitDataChanged(PwMDoc *document) { if (!dataChangedLock) emit dataChanged(document); } protected: /** current file for this doc */ QString filename; /** holds all data */ vector<PwMCategoryItem> dta; /** maximum number of entries */ unsigned int maxEntries; /** currently used password to encrypt data */ QString currentPw; /** current global document status flags */ unsigned int curDocStat; /** browser process for goToURL() */ KProcess browserProc; /** pointer to the list-view, using this document. * As there can only be one list-view per doc, we * don't need a list here. */ PwMView *listView; /** unnamedNum is used to store the "unnamed counter" * for this document, while it's unnamed. If it's 0, * we have to get a new unique one. */ unsigned int unnamedNum; /** is this doc going to be deleted (executing in destructor context) */ bool deleted; /** document timer */ DocTimer *_timer; /** lock counter for the "dataChanged" signal */ unsigned int dataChangedLock; /** list of all open documents */ static PwMDocList openDocList; protected: /** serialize "dta" and return it in "d". */ bool serializeDta(string *d); /** de-serialize "d" and overwrite "dta" */ bool deSerializeDta(const string *d, bool entriesLocked); /** write header to file */ PwMerror writeFileHeader(char keyHash, char dataHash, char crypt, char compress, QString *pw, QFile *f); /** write data-hash to file */ PwMerror writeDataHash(char dataHash, string *d, QFile *f); /** check header. Read header info and verify key-hash and filever. * returns length of header in "headerLength" */ PwMerror checkHeader(char *cryptAlgo, QString *pw, char *compress, unsigned int *headerLength, char *dataHashType, string *dataHash, QFile *f); /** check the data-hash */ PwMerror checkDataHash(char dataHashType, const string *dataHash, const string *dataStream); /** encrypt data "d" and write to "filename" */ PwMerror encrypt(string *d, const QString *pw, QFile *f, char algo); /** read data from file beginning at "pos", decrypt and return it */ PwMerror decrypt(string *d, unsigned int pos, const QString *pw, char algo, QFile *f); /** compress the data */ bool compressDta(string *d, char algo); /** uncompress the data */ bool decompressDta(string *d, char algo); /** internal import function for a text-file generated by PwM. * If this is not a valid PwM-exported file, it returns e_fileFormat */ PwMerror importText_PwM(const QString *file); /** PwM-text-import helper function to extract the name/pw/comment out * of one entry-line */ bool textExtractEntry_PwM(const char *in, ssize_t in_size, string *out); /** compare two strings */ bool compareString(const string &s1, const string &s2, bool caseSensitive, bool exactWordMatch); /** clears all document-data */ void clearDoc(); /** delete all empty categories */ void delAllEmptyCat(bool dontFlagDirty); /** set a document status flag */ void setDocStatFlag(unsigned int statFlag) { curDocStat |= statFlag; } /** unset a document status flag */ void unsetDocStatFlag(unsigned int statFlag) { curDocStat &= ~statFlag; } /** get a document status flag */ bool getDocStatFlag(unsigned int statFlag) const { return (curDocStat & statFlag); } /** set the "currentPassword" */ void setCurrentPw(const QString &pw) { currentPw = pw; setDocStatFlag(DOC_STAT_DISK_DIRTY); } /** make a backup-copy of the given file */ bool backupFile(const QString &filePath); /** copy a file from src to dst */ bool copyFile(const QString &src, const QString &dst); }; #endif diff --git a/pwmanager/pwmanager/pwmdocui.cpp b/pwmanager/pwmanager/pwmdocui.cpp index b308b40..3993fa8 100644 --- a/pwmanager/pwmanager/pwmdocui.cpp +++ b/pwmanager/pwmanager/pwmdocui.cpp @@ -1,453 +1,454 @@ /*************************************************************************** * * * copyright (C) 2003, 2004 by Michael Buesch * * email: mbuesch@freenet.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License version 2 * * as published by the Free Software Foundation. * * * ***************************************************************************/ /*************************************************************************** * copyright (C) 2004 by Ulf Schenk * This file is originaly based on version 1.0.1 of pwmanager * and was modified to run on embedded devices that run microkde * * $Id$ **************************************************************************/ #include "pwmdocui.h" #include "setmasterpwwndimpl.h" #include "getmasterpwwndimpl.h" #include "pwmexception.h" #include "getkeycardwnd.h" #include "pwm.h" #include "globalstuff.h" #include "spinforsignal.h" #include <qlineedit.h> #include <qtabwidget.h> #include <kmessagebox.h> #include <kfiledialog.h> #ifndef PWM_EMBEDDED #include <kwin.h> #else #include <qdir.h> +#include "pwmprefs.h" #endif #ifdef CONFIG_KEYCARD # include "pwmkeycard.h" #endif PwMDocUi::PwMDocUi(QObject *parent, const char *name) : QObject(parent, name) { currentView = 0; keyCard = 0; } PwMDocUi::~PwMDocUi() { } QString PwMDocUi::requestMpw(bool chipcard) { QString pw; if (chipcard) { #ifdef CONFIG_KEYCARD PWM_ASSERT(keyCard); uint32_t id; string ret; SpinForSignal *spinner = keyCard->getSpinner(); connect(keyCard, SIGNAL(keyAvailable(uint32_t, const string &)), spinner, SLOT(u32_str_slot(uint32_t, const string &))); keyCard->getKey(); spinner->spin(&id, &ret); disconnect(keyCard, SIGNAL(keyAvailable(uint32_t, const string &)), spinner, SLOT(u32_str_slot(uint32_t, const string &))); if (ret == "") return ""; pw = ret.c_str(); #else // CONFIG_KEYCARD no_keycard_support_msg_box(currentView); #endif // CONFIG_KEYCARD } else { GetMasterPwWndImpl pwWnd; #ifndef PWM_EMBEDDED KWin::setState(pwWnd.winId(), NET::StaysOnTop); #endif if (pwWnd.exec() != 1) return ""; pw = pwWnd.pwLineEdit->text(); } return pw; } QString PwMDocUi::requestNewMpw(bool *chipcard) { QString pw; SetMasterPwWndImpl pwWnd(currentView); pwWnd.setPwMKeyCard(keyCard); #ifndef PWM_EMBEDDED if (!chipcard) { pwWnd.mainTab->removePage(pwWnd.mainTab->page(1)); } #else qDebug("PwMDocUi::requestNewMpw must be implemented"); #endif if (pwWnd.exec() != 1) return ""; pw = pwWnd.getPw(chipcard).c_str(); return pw; } QString PwMDocUi::requestMpwChange(const QString *currentPw, bool *chipcard) { QString pw(requestMpw(*chipcard)); if (pw == "") return ""; if (pw != *currentPw) { wrongMpwMsgBox(*chipcard); return ""; } pw = requestNewMpw(chipcard); if (pw == "") return ""; return pw; } void PwMDocUi::wrongMpwMsgBox(bool chipcard, QString prefix, QString postfix) { QString msg; if (prefix != "") { msg += prefix; msg += "\n"; } if (chipcard) { msg += i18n("Wrong key-card!\n" "Please try again with the " "correct key-card."); } else { msg += i18n("Wrong master-password!\n" "Please try again."); } if (postfix != "") { msg += "\n"; msg += postfix; } KMessageBox::error(currentView, msg, (chipcard) ? (i18n("wrong chipcard")) : (i18n("password error"))); } void PwMDocUi::noMpwMsgBox(bool chipcard, QString prefix, QString postfix) { QString msg; if (prefix != "") { msg += prefix; msg += "\n"; } if (chipcard) { msg += i18n("No key-card found!\n" "Please insert the " "correct key-card."); } else { msg += i18n("No master-password given!"); } if (postfix != "") { msg += "\n"; msg += postfix; } KMessageBox::error(currentView, msg, (chipcard) ? (i18n("no chipcard")) : (i18n("password error"))); } void PwMDocUi::rootAlertMsgBox() { KMessageBox::error(currentView, i18n("This feature is not available, " "if you execute PwM with \"root\" " "UID 0 privileges, for security reasons!"), i18n("not allowed as root!")); } void PwMDocUi::cantDeeplock_notSavedMsgBox() { KMessageBox::error(currentView, i18n("Can't deep-lock, because the document " "hasn't been saved, yet. Please save " "to a file and try again."), i18n("not saved, yet")); } void PwMDocUi::gpmPwLenErrMsgBox() { KMessageBox::error(currentView, i18n("GPasman does not support passwords " "shorter than 4 characters! Please try " "again with a longer password."), i18n("password too short")); } int PwMDocUi::dirtyAskSave(const QString &docTitle) { int ret; #ifndef PWM_EMBEDDED ret = KMessageBox::questionYesNoCancel(currentView, i18n("The list \"") + docTitle + i18n ("\" has been modified.\n" "Do you want to save it?"), i18n("save?")); if (ret == KMessageBox::Yes) { return 0; } else if (ret == KMessageBox::No) { return 1; } #else ret = KMessageBox::warningYesNoCancel(currentView, i18n("The list \"") + docTitle + i18n ("\" has been modified.\n" "Do you want to save it?"), i18n("save?")); if (ret == KMessageBox::Yes) { return 0; } else if (ret == KMessageBox::No) { return 1; } #endif // cancel return -1; } bool PwMDocUi::saveDocUi(PwMDoc *doc) { PWM_ASSERT(doc); doc->timer()->getLock(DocTimer::id_autoLockTimer); if (doc->isDocEmpty()) { KMessageBox::information(currentView, i18n ("Sorry, there's nothing to save.\n" "Please first add some passwords."), i18n("nothing to do")); doc->timer()->putLock(DocTimer::id_autoLockTimer); return true; } PwMerror ret = doc->saveDoc(conf()->confGlobCompression()); if (ret == e_filename) { doc->timer()->putLock(DocTimer::id_autoLockTimer); return saveAsDocUi(doc); } else if (ret == e_weakPw) { KMessageBox::error(currentView, i18n("Error: This is a weak password.\n" "Please select another password."), i18n("weak password")); doc->timer()->putLock(DocTimer::id_autoLockTimer); return false; } else if (ret == e_fileBackup) { KMessageBox::error(currentView, i18n("Error: Couldn't make backup-file!"), i18n("backup failed")); doc->timer()->putLock(DocTimer::id_autoLockTimer); return false; } else if (ret != e_success) { KMessageBox::error(currentView, i18n("Error: Couldn't write to file.\n" "Please check if you have permission to " "write to the file in that directory."), i18n("error while writing")); doc->timer()->putLock(DocTimer::id_autoLockTimer); return false; } doc->timer()->putLock(DocTimer::id_autoLockTimer); return true; } bool PwMDocUi::saveAsDocUi(PwMDoc *doc) { PWM_ASSERT(doc); doc->timer()->getLock(DocTimer::id_autoLockTimer); if (doc->isDocEmpty()) { KMessageBox::information(currentView, i18n ("Sorry, there's nothing to save.\n" "Please first add some passwords."), i18n("nothing to do")); doc->timer()->putLock(DocTimer::id_autoLockTimer); return true; } #ifndef PWM_EMBEDDED QString fn(KFileDialog::getSaveFileName(QString::null, i18n("*.pwm|PwManager Password file"), currentView)); #else QString fn = locateLocal( "data", KGlobal::getAppName() + "/*.pwm" ); fn = KFileDialog::getSaveFileName(fn, i18n("password filename(*.pwm)"), currentView); #endif if (fn == "") { doc->timer()->putLock(DocTimer::id_autoLockTimer); return false; } if (fn.right(4) != ".pwm") fn += ".pwm"; PwMerror ret = doc->saveDoc(conf()->confGlobCompression(), &fn); if (ret != e_success) { KMessageBox::error(currentView, i18n("Error: Couldn't write to file.\n" "Please check if you have permission to " "write to the file in that directory."), i18n("error while writing")); doc->timer()->putLock(DocTimer::id_autoLockTimer); return false; } doc->timer()->putLock(DocTimer::id_autoLockTimer); return true; } bool PwMDocUi::openDocUi(PwMDoc *doc, QString filename, bool openDeepLocked) { if (filename.isEmpty()) { #ifndef PWM_EMBEDDED filename = KFileDialog::getOpenFileName(QString::null, i18n("*.pwm|PwManager Password file\n" "*|All files"), getCurrentView()); #else filename = locateLocal( "data", KGlobal::getAppName() + "/*.pwm"); filename = KFileDialog::getOpenFileName(filename, i18n("password filename(*.pwm)"), getCurrentView()); #endif } if (filename.isEmpty()) goto cancelOpen; PwMerror ret; while (true) { int lockStat = -1; if (openDeepLocked) { lockStat = 2; } else { if (conf()->confGlobUnlockOnOpen()) { lockStat = 0; } else { lockStat = 1; } } ret = doc->openDoc(&filename, lockStat); if (ret != e_success) { if (ret == e_readFile || ret == e_openFile) { KMessageBox::error(getCurrentView(), i18n("Could not read file!") + "\n" + filename, i18n("file error")); goto cancelOpen; } if (ret == e_alreadyOpen) { KMessageBox::error(getCurrentView(), i18n("This file is already open."), i18n("already open")); goto cancelOpen; } if (ret == e_fileVer) { KMessageBox::error(getCurrentView(), i18n ("File-version is not supported!\n" "Did you create this file with an older or newer version of PwM?"), i18n ("incompatible version")); goto cancelOpen; } if (ret == e_wrongPw) { continue; } if (ret == e_noPw) { goto cancelOpen; } if (ret == e_fileFormat) { KMessageBox::error(getCurrentView(), i18n ("Sorry, this file has not been recognized " "as a PwM Password file.\n" "Probably you have selected the wrong file."), i18n ("no PwM password-file")); goto cancelOpen; } if (ret == e_fileCorrupt) { KMessageBox::error(getCurrentView(), i18n ("File corrupt!\n" "Maybe the media, you stored this file on, " "had bad sectors?"), i18n ("checksum error")); goto cancelOpen; } } break; } return true; cancelOpen: return false; } QString PwMDocUi::string_defaultCategory() { return i18n("Default"); } QString PwMDocUi::string_locked() { return i18n("<LOCKED>"); } QString PwMDocUi::string_deepLockedShort() { return i18n("DEEP-LOCKED"); } QString PwMDocUi::string_deepLockedLong() { return i18n("This file is DEEP-LOCKED!\n" "That means all data has been encrypted " "and written out to the file. If you want " "to see the entries, please UNLOCK the file. " "While unlocking, you will be prompted for the " "master-password or the key-card."); } QString PwMDocUi::string_defaultTitle() { return i18n("Untitled"); } #ifndef PWM_EMBEDDED #include "pwmdocui.moc" #endif diff --git a/pwmanager/pwmanager/pwminit.cpp b/pwmanager/pwmanager/pwminit.cpp index 2f1aa4e..8946443 100644 --- a/pwmanager/pwmanager/pwminit.cpp +++ b/pwmanager/pwmanager/pwminit.cpp @@ -1,615 +1,632 @@ /*************************************************************************** * * * copyright (C) 2004 by Michael Buesch * * email: mbuesch@freenet.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License version 2 * * as published by the Free Software Foundation. * * * ***************************************************************************/ /*************************************************************************** * copyright (C) 2004 by Ulf Schenk * This file is originaly based on version 1.0.1 of pwmanager * and was modified to run on embedded devices that run microkde * * $Id$ **************************************************************************/ #include "pwminit.h" -#include "configuration.h" #include "randomizer.h" #ifndef PWM_EMBEDDED #include "selftest.h" +#include "configuration.h" +#else +#include "pwmprefs.h" #endif #include "pwm.h" #include "pwmexception.h" #include "pwmtray.h" #include "pwmdoc.h" #ifdef CONFIG_KWALLETIF # include "kwalletemu.h" #endif // CONFIG_KWALLETIF #ifdef CONFIG_KEYCARD # include "pwmkeycard.h" #endif // CONFIG_KEYCARD #include <qmessagebox.h> #include <kmessagebox.h> #ifndef PWM_EMBEDDED #include <kcmdlineargs.h> #include <kwin.h> #include <dcopclient.h> #endif #include <kapplication.h> #include <kiconloader.h> #include <signal.h> static PwMInit *sig_init_pointer; static NOREGPARM void sig_handler(int signum) { switch (signum) { case SIGINT: case SIGTERM: sig_init_pointer->shutdownApp(20 + signum); break; default: printDebug(string("unhandled signal ") + tostr(signum)); } } PwMInit::PwMInit(PwMApplication *_app) : runStatus (unknown) , _curWidget (0) , _dcopClient (0) , _kwalletEmu (0) , _keycard (0) , _tray (0) { sig_init_pointer = this; app = _app; } PwMInit::~PwMInit() { #ifndef PWM_EMBEDDED SelfTest::cancel(); // close all open mainwnds QValueList<PwM *>::iterator i = _mainWndList.begin(), end = _mainWndList.end(); #else // close all open mainwnds QValueList<PwM *>::Iterator i = _mainWndList.begin(), end = _mainWndList.end(); #endif while (i != end) { disconnect(*i, SIGNAL(closed(PwM *)), this, SLOT(mainWndClosed(PwM *))); delete *i; ++i; } _mainWndList.clear(); // close all remaining open documents PwMDocList *_dl = PwMDoc::getOpenDocList(); vector<PwMDocList::listItem> dl = *(_dl->getList()); vector<PwMDocList::listItem>::iterator i2 = dl.begin(), end2 = dl.end(); while (i2 != end2) { delete (*i2).doc; ++i2; } #ifdef CONFIG_KWALLETIF delete_ifnot_null(_kwalletEmu); #endif // CONFIG_KWALLETIF #ifdef CONFIG_KEYCARD delete_ifnot_null(_keycard); #endif // CONFIG_KEYCARD delete_ifnot_null(_tray); Randomizer::cleanup(); +#ifndef PWM_EMBEDDED Configuration::cleanup(); +#endif } void PwMInit::initializeApp() { PWM_ASSERT(runStatus == unknown); runStatus = init; initPosixSignalHandler(); Randomizer::init(); +#ifndef PWM_EMBEDDED Configuration::init(); +#endif initDCOP(); initKWalletEmu(); initKeycard(); initTray(); handleCmdLineArgs(); bool openDeeplocked = false; if (conf()->confGlobAutostartDeepLocked() || savedCmd.open_deeplocked) openDeeplocked = true; if (conf()->confWndAutoMinimizeOnStart() || savedCmd.minToTray) { PwMDoc *newDoc = createDoc(); if (!newDoc->openDocUi(newDoc, conf()->confGlobAutoStart(), openDeeplocked)) { delete newDoc; + + //US ENH for embedded devices: in the case of failure, open a document the default way + createMainWnd(conf()->confGlobAutoStart(), + openDeeplocked, + true, + 0, + savedCmd.minimized); + + + + } } else { createMainWnd(conf()->confGlobAutoStart(), openDeeplocked, true, 0, savedCmd.minimized); } runStatus = running; } void PwMInit::shutdownApp(int exitStatus) { printDebug(string("PwMInit::shutdownApp(") + tostr(exitStatus) + ") called."); PWM_ASSERT((runStatus == running) || (runStatus == init)); runStatus = shutdown; QApplication::exit(exitStatus); /* The destructor of PwMInit is called when control * leaves main() */ } void PwMInit::initPosixSignalHandler() { signal(SIGINT, sig_handler); signal(SIGTERM, sig_handler); } void PwMInit::initDCOP() { #ifndef PWM_EMBEDDED _dcopClient = app->dcopClient(); _dcopClient->setNotifications(true); #endif } void PwMInit::initKWalletEmu(bool forceDisable, bool forceReload) { #ifdef CONFIG_KWALLETIF if (!conf()->confGlobKwalletEmu() || forceDisable) { delete_ifnot_null(_kwalletEmu); return; } try { if (_kwalletEmu && forceReload) delete_and_null(_kwalletEmu); if (!_kwalletEmu) _kwalletEmu = new KWalletEmu(this); } catch (PwMException e) { string errMsg("initializing KWallet emulation failed. ID: "); errMsg += tostr(static_cast<int>(e.getId())); errMsg += " err-message: "; errMsg += e.getMessage(); printWarn(errMsg); return; } #else // CONFIG_KWALLETIF PARAM_UNUSED(forceDisable); PARAM_UNUSED(forceReload); #endif // CONFIG_KWALLETIF } void PwMInit::initKeycard() { #ifdef CONFIG_KEYCARD PWM_ASSERT(!_keycard); _keycard = new PwMKeyCard(this); #endif // CONFIG_KEYCARD } void PwMInit::initTray() { #ifdef PWM_EMBEDDED //US ENH : embedded version does not support a tray return; #endif if (!conf()->confGlobTray()) { if (!_tray) return; _tray->hide(); delete_and_null(_tray); return; } if (_tray) return; _tray = new PwMTray(this); connect(_tray, SIGNAL(quitSelected()), this, SLOT(removeTrayAndQuit())); connect(_tray, SIGNAL(closed(PwMTray *)), this, SLOT(trayIconClosed(PwMTray *))); KIconLoader icons; #ifndef PWM_EMBEDDED _tray->setPixmap(icons.loadIcon(PACKAGE_NAME, KIcon::Small)); #endif _tray->show(); // connect the signals of all open documents. const vector<PwMDocList::listItem> *dl = PwMDoc::getOpenDocList()->getList(); vector<PwMDocList::listItem>::const_iterator i = dl->begin(), end = dl->end(); while (i != end) { _tray->connectDocToTray((*i).doc); ++i; } } void PwMInit::removeTrayAndQuit() { PWM_ASSERT(_tray); // _tray is deleted in ~PwMInit shutdownApp(0); } PwM * PwMInit::createMainWnd(const QString &loadFile, bool loadFileDeepLocked, bool virginity, PwMDoc *doc, bool minimized) { PwM *newWnd; if (!doc) doc = createDoc(); newWnd = new PwM(this, doc, virginity); #ifndef PWM_EMBEDDED _mainWndList.push_back(newWnd); #else _mainWndList.append(newWnd); #endif connect(newWnd, SIGNAL(closed(PwM *)), this, SLOT(mainWndClosed(PwM *))); connect(newWnd, SIGNAL(gotFocus(PwM *)), this, SLOT(setCurWidget(PwM *))); connect(newWnd, SIGNAL(lostFocus(PwM *)), this, SLOT(resetCurWidget())); //US ENH #ifndef PWM_EMBEDDED if (minimized) newWnd->showMinimized(); else newWnd->show(); #else //PWM_EMBEDDED #ifndef DESKTOP_VERSION app->showMainWidget( newWnd ); #else //DESKTOP_VERSION app->setMainWidget( newWnd ); newWnd->resize (640, 480 ); newWnd->show(); #endif //DESKTOP_VERSION #endif //PWM_EMBEDDED if (loadFile != QString::null && loadFile != "") { newWnd->openDoc(loadFile, loadFileDeepLocked); } return newWnd; } PwMDoc * PwMInit::createDoc() { PwMDoc *doc = new PwMDoc(this); #ifdef CONFIG_KEYCARD doc->setPwMKeyCard(keycard()); #endif #ifdef CONFIG_KWALLETIF if (kwalletEmu()) kwalletEmu()->connectDocSignals(doc); #endif if (_tray) _tray->connectDocToTray(doc); return doc; } void PwMInit::mainWndClosed(PwM *wnd) { bool doMinimizeToTray = false; bool doDeleteDoc = false; #ifndef PWM_EMBEDDED dcopClient()->suspend(); dcopClient()->setAcceptCalls(false); #endif again: if (wnd->isForceMinimizeToTray()) { if (unlikely(!_tray)) { /* This should not happen! If we set forceMinimizeToTray , * we must be sure that _tray exists. */ BUG(); wnd->setForceMinimizeToTray(false); goto again; } doMinimizeToTray = true; } else { // Ask to minimize to tray. If not, delete doc. if (_tray && runStatus != shutdown && !wnd->isForceQuit() && !wnd->curDoc()->isDeleted()) { if (conf()->confWndClose()) doDeleteDoc = true; else doMinimizeToTray = true; } else { doDeleteDoc = true; } } if (doMinimizeToTray) { PWM_ASSERT(_tray); int mmlock = conf()->confGlobMinimizeLock(); switch (mmlock) { case 0: // don't lock anything break; case 1: // normal lock wnd->curDoc()->lockAll(true); break; case 2: // deep-lock wnd->curDoc()->deepLock(); break; default: WARN(); } } else if (doDeleteDoc) { if (!wnd->curDoc()->tryDelete()) { /* We failed deleting the doc, * so open a new window with it, again. */ createMainWnd(QString::null, false, false, wnd->curDoc()); } } #ifndef PWM_EMBEDDED // find the closed window in the "mainWndList" and delete it. QValueList<PwM *>::iterator i = _mainWndList.begin(), end = _mainWndList.end(); #else // find the closed window in the "mainWndList" and delete it. QValueList<PwM *>::Iterator i = _mainWndList.begin(), end = _mainWndList.end(); #endif while (i != end) { if (*i == wnd) { #ifndef PWM_EMBEDDED _mainWndList.erase(i); #else _mainWndList.remove(i); #endif goto out_success; } ++i; } BUG(); out_success: #ifndef PWM_EMBEDDED if (!_mainWndList.size()) #else if (!_mainWndList.count()) #endif { /* If there's no main window and no tray icon * left, we have no user interface, so we can * shut down the application. */ if (!_tray) { #ifndef PWM_EMBEDDED dcopClient()->setAcceptCalls(true); dcopClient()->resume(); #endif shutdownApp(0); return; } /* There is no widget left, so set * _curWidget to 0 */ resetCurWidget(); } #ifndef PWM_EMBEDDED dcopClient()->setAcceptCalls(true); dcopClient()->resume(); #endif } void PwMInit::trayIconClosed(PwMTray *tray) { if (runStatus != running) return; PARAM_UNUSED(tray); PWM_ASSERT(tray == _tray); /* If there's no main wnd left we have to * shutdown the app (same as in mainWndClosed()) */ #ifndef PWM_EMBEDDED if (!_mainWndList.size()) shutdownApp(0); #else if (!_mainWndList.count()) shutdownApp(0); #endif } void PwMInit::handleCmdLineArgs(bool initial) { #ifndef PWM_EMBEDDED KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); PWM_ASSERT(args); int i, numArgs = args->count(); const char *curArg; // read all cmdline options savedCmd.open_deeplocked = args->isSet("open-deeplocked"); savedCmd.minimized = args->isSet("minimized"); savedCmd.minToTray = args->isSet("mintray"); savedCmd.skipSelfTest = args->isSet("skip-self-test"); if (savedCmd.minimized && savedCmd.minToTray) { printInfo(i18n("Commandline option \"--minimized\" and " "\"--mintray\" selected. These are incompatible. " "\"--mintray\" will be selected.").latin1()); } /* Iterate through all non-option arguments. * Every non-option arg is a filename to open. */ for (i = 0; i < numArgs; ++i) { curArg = args->arg(i); PWM_ASSERT(curArg); if (savedCmd.minToTray) { PwMDoc *newDoc = createDoc(); if (!newDoc->openDocUi(newDoc, curArg, savedCmd.open_deeplocked)) { delete newDoc; } } else { PwM *newInstance = createMainWnd(QString::null, false, true, 0, savedCmd.minimized); PwMDoc *newDoc = newInstance->openDoc(curArg, savedCmd.open_deeplocked); if (!newDoc) { newInstance->setForceQuit(true); delete_and_null(newInstance); } } } if (savedCmd.minToTray) { minimizeAllMainWnd(true); } else if (savedCmd.minimized) { minimizeAllMainWnd(false); } if (!savedCmd.skipSelfTest && initial) { SelfTest::schedule(); } args->clear(); #endif } void PwMInit::minimizeAllMainWnd(bool toTray) { #ifndef PWM_EMBEDDED if (!_mainWndList.size()) return; #else if (!_mainWndList.count()) return; #endif const QValueList<PwM *> *ml = mainWndList(); #ifndef PWM_EMBEDDED QValueList<PwM *>::const_iterator it = ml->begin(), end = ml->end(); #else QValueList<PwM *>::ConstIterator it = ml->begin(), end = ml->end(); #endif PwM *wnd; if (toTray && _tray) { /* minimize to tray. * close all mainWnd. */ while (it != end) { wnd = *it; wnd->setForceMinimizeToTray(true); wnd->close_slot(); ++it; } } else { // normal minimize while (it != end) { wnd = *it; wnd->hide(); wnd->showMinimized(); ++it; } } } #ifdef PWM_EMBEDDED #ifndef DESKTOP_VERSION PwMApplication::PwMApplication(int & argc, char ** argv) : QPEApplication( argc, argv ) , init (0) { this->setKeepRunning (); } PwMApplication::~PwMApplication() { delete_ifnot_null(init); } #else //DESKTOP_VERSION PwMApplication::PwMApplication(int & argc, char ** argv) : QApplication( argc, argv ) , init (0) { setStyle( new QPlatinumStyle ()); QString hdir = QDir::homeDirPath(); // there is a bug when creating dirs for WIN 98 // it is difficult to fix, because we have no WIN 98 runnung // such that we try it to create the dirs at startup here if ( hdir == "C:\\" ) { // win 98 or ME QDir app_dir; if ( !app_dir.exists("C:\\kdepim") ) app_dir.mkdir ("C:\\kdepim"); if ( !app_dir.exists("C:\\kdepim\\apps") ) app_dir.mkdir ("C:\\kdepim\\apps"); if ( !app_dir.exists("C:\\kdepim\\config") ) app_dir.mkdir ("C:\\kdepim\\config"); if ( !app_dir.exists("C:\\kdepim\\apps\\pwmanager") ) app_dir.mkdir ("C:\\kdepim\\apps\\pwmanager"); } } PwMApplication::~PwMApplication() { delete_ifnot_null(init); } #endif //DESKTOP_VERSION #endif //PWM_EMBEDDED #ifndef PWM_EMBEDDED #include "pwminit.moc" #endif diff --git a/pwmanager/pwmanager/pwmtray.cpp b/pwmanager/pwmanager/pwmtray.cpp index 0f286c1..fe074ca 100644 --- a/pwmanager/pwmanager/pwmtray.cpp +++ b/pwmanager/pwmanager/pwmtray.cpp @@ -1,482 +1,486 @@ /*************************************************************************** * * * copyright (C) 2003, 2004 by Michael Buesch * * email: mbuesch@freenet.de * * * * Original implementation of the tray-tree * * (c) by Matt Scifo <mscifo@o1.com> * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License version 2 * * as published by the Free Software Foundation. * * * ***************************************************************************/ /*************************************************************************** * copyright (C) 2004 by Ulf Schenk * This file is originaly based on version 1.0.1 of pwmanager * and was modified to run on embedded devices that run microkde * * $Id$ **************************************************************************/ #include "pwmtray.h" #include "pwmexception.h" #include "pwm.h" #include "pwmdoc.h" #include "pwminit.h" +#ifndef PWM_EMBEDDED #include "configuration.h" +#else +#include "pwmprefs.h" +#endif #include <klocale.h> void ActiveTreeItem::execIt() { #ifndef PWM_EMBEDDED unsigned int entr = static_cast<unsigned int>(entry); unsigned int cat = static_cast<unsigned int>(category); #else unsigned int entr = (unsigned int)(entry); unsigned int cat = (unsigned int)(category); #endif switch (task) { case pwToClipboard: { PwMDataItem d; doc->getDataChangedLock(); bool wasLocked = doc->isLocked(cat, entr); doc->getEntry(cat, entr, &d, true); if (wasLocked) doc->lockAt(cat, entr, true); doc->putDataChangedLock(); PwM::copyToClipboard(d.pw.c_str()); break; } case nameToClipboard: { PwMDataItem d; doc->getEntry(cat, entr, &d); PwM::copyToClipboard(d.name.c_str()); break; } case descToClipboard: { PwMDataItem d; doc->getEntry(cat, entr, &d); PwM::copyToClipboard(d.desc.c_str()); break; } case urlToClipboard: { PwMDataItem d; doc->getEntry(cat, entr, &d); PwM::copyToClipboard(d.url.c_str()); break; } case launcherToClipboard: { PwMDataItem d; doc->getEntry(cat, entr, &d); PwM::copyToClipboard(d.launcher.c_str()); break; } case commentToClipboard: { PwMDataItem d; doc->getEntry(cat, entr, &d); PwM::copyToClipboard(d.comment.c_str()); break; } case execLauncher: { doc->execLauncher(cat, entr); break; } case goToURL: { doc->goToURL(cat, entr); break; } case openMainWnd: { // search if there is already an open window. const QValueList<PwM *> *wl = tray->init->mainWndList(); #ifndef PWM_EMBEDDED QValueList<PwM *>::const_iterator i = wl->begin(), end = wl->end(); #else QValueList<PwM *>::ConstIterator i = wl->begin(), end = wl->end(); #endif PwM *wnd; while (i != end) { wnd = *i; if (wnd->curDoc() == doc) { // now bring this window to the foreground. if (!wnd->hasFocus()) { wnd->hide(); wnd->showNormal(); wnd->setFocus(); } return; } ++i; } // there is no open window, so open a new one. tray->init->createMainWnd(QString::null, false, false, doc); break; } case closeDoc: { doc->tryDelete(); break; } case lock: { doc->lockAll(true); break; } case deepLock: { doc->deepLock(); break; } case unlock: { doc->lockAll(false); break; } default: { BUG(); } } } #ifndef PWM_EMBEDDED PwMTray::PwMTray(PwMInit *_init, QWidget * parent, const char *name) : KSystemTray(parent, name) #else PwMTray::PwMTray(PwMInit *_init, QWidget * parent, const char *name) : QWidget(parent, name) #endif { init = _init; buildMain(); } PwMTray::~PwMTray() { emit closed(this); } //US ENH for embedded tray class KPopupMenu* PwMTray::contextMenu() { if (m_ctxMenu == 0) { m_ctxMenu = new KPopupMenu(); } return m_ctxMenu; } void PwMTray::buildMain() { KPopupMenu *ctxMenu = contextMenu(); ctxMenu->insertSeparator(); ctxMenu->insertItem(i18n("&New main window..."), this, SLOT(newMainWnd())); ctxMenu->insertItem(i18n("&Open file..."), this, SLOT(openDoc())); ctxMenu->insertSeparator(); ctxMenu->insertItem(i18n("&Remove from tray"), this, SLOT(undock())); } void PwMTray::insertActiveTreeItem(KPopupMenu *insertIn, const QString &text, ActiveTreeItem::Task task, PwMDoc *doc, int docCategory, int docEntry, QValueList<int> *activeItemsList) { ActiveTreeItem *activeItem; int id; activeItem = new ActiveTreeItem(text, insertIn->font(), task, doc, docCategory, docEntry, this); id = insertIn->insertItem(activeItem); insertIn->connectItem(id, activeItem, SLOT(execIt())); #ifndef PWM_EMBEDDED activeItemsList->push_back(id); #else activeItemsList->append(id); #endif } void PwMTray::rebuildTree(KPopupMenu *popup, PwMDoc *doc, QValueList<int> *activeItems) { PWM_ASSERT(doc); PWM_ASSERT(popup); activeItems->clear(); popup->clear(); #ifndef PWM_EMBEDDED popup->insertTitle(i18n("Categories:")); #endif vector<string> catList; vector<string> entrList; doc->getCategoryList(&catList); KPopupMenu *newCatMenu; KPopupMenu *newEntrMenu; int i, size = catList.size(); int j, entries; for (i = 0; i < size; ++i) { newCatMenu = new KPopupMenu(popup); popup->insertItem(catList[i].c_str(), newCatMenu); doc->getEntryList(i, &entrList); entries = entrList.size(); for (j = 0; j < entries; ++j) { newEntrMenu = new KPopupMenu(newCatMenu); newCatMenu->insertItem(entrList[j].c_str(), newEntrMenu); if (doc->isBinEntry(i, j)) { /* This is a binary entry. Don't insert the usual * menu items. */ #ifndef PWM_EMBEDDED newEntrMenu->insertTitle(i18n("This is a binary entry.\n" "It is not a normal password-entry, as it contains " "binary data, which PwManager can't display here.")); #endif continue; } insertActiveTreeItem(newEntrMenu, i18n("copy password to clipboard"), ActiveTreeItem::pwToClipboard, doc, i, j, activeItems); insertActiveTreeItem(newEntrMenu, i18n("copy username to clipboard"), ActiveTreeItem::nameToClipboard, doc, i, j, activeItems); insertActiveTreeItem(newEntrMenu, i18n("copy description to clipboard"), ActiveTreeItem::descToClipboard, doc, i, j, activeItems); insertActiveTreeItem(newEntrMenu, i18n("copy url to clipboard"), ActiveTreeItem::urlToClipboard, doc, i, j, activeItems); insertActiveTreeItem(newEntrMenu, i18n("copy launcher to clipboard"), ActiveTreeItem::launcherToClipboard, doc, i, j, activeItems); insertActiveTreeItem(newEntrMenu, i18n("copy comment to clipboard"), ActiveTreeItem::commentToClipboard, doc, i, j, activeItems); newEntrMenu->insertSeparator(); insertActiveTreeItem(newEntrMenu, i18n("Execute \"Launcher\""), ActiveTreeItem::execLauncher, doc, i, j, activeItems); insertActiveTreeItem(newEntrMenu, i18n("Go to \"URL\""), ActiveTreeItem::goToURL, doc, i, j, activeItems); } } insertMainWndCtrl(popup, doc); } void PwMTray::insertMainWndCtrl(KPopupMenu *menu, PwMDoc *doc) { ActiveTreeItem *activeItem; int id; #ifndef PWM_EMBEDDED menu->insertTitle(i18n("Manager:")); #endif activeItem = new ActiveTreeItem(i18n("&Open main manager window ..."), menu->font(), ActiveTreeItem::openMainWnd, doc, 0, 0, this); id = menu->insertItem(activeItem); menu->connectItem(id, activeItem, SLOT(execIt())); activeItem = new ActiveTreeItem(i18n("&Close this document ..."), menu->font(), ActiveTreeItem::closeDoc, doc, 0, 0, this); id = menu->insertItem(activeItem); menu->connectItem(id, activeItem, SLOT(execIt())); menu->insertSeparator(); activeItem = new ActiveTreeItem(i18n("&Lock all entries"), menu->font(), ActiveTreeItem::lock, doc, 0, 0, this); id = menu->insertItem(activeItem); menu->connectItem(id, activeItem, SLOT(execIt())); activeItem = new ActiveTreeItem(i18n("&Deep-lock all entries"), menu->font(), ActiveTreeItem::deepLock, doc, 0, 0, this); id = menu->insertItem(activeItem); menu->connectItem(id, activeItem, SLOT(execIt())); activeItem = new ActiveTreeItem(i18n("&Unlock all entries"), menu->font(), ActiveTreeItem::unlock, doc, 0, 0, this); id = menu->insertItem(activeItem); menu->connectItem(id, activeItem, SLOT(execIt())); } void PwMTray::updateTree(PwMDoc *document) { PWM_ASSERT(document); KPopupMenu *treeEntry; int treeItemNum = -1; int id = findTreeEntry(document, &treeEntry, &treeItemNum); if (id == -1) { // tree-entry doesn't exist, yet. id = insertTreeEntry(document, &treeEntry); } if (treeItemNum != -1) { // delete all *old* active items KPopupMenu *ctxMenu = contextMenu(); QValueList<int> *oldItems = &tree[treeItemNum].activeItems; #ifndef PWM_EMBEDDED QValueList<int>::iterator i = oldItems->begin(); #else QValueList<int>::Iterator i = oldItems->begin(); #endif while (i != oldItems->end()) { ctxMenu->removeItem(*i); ++i; } oldItems->clear(); ctxMenu->changeItem(id, document->getTitle()); } treeItem newTreeItem; if (document->isDeepLocked()) { treeEntry->clear(); #ifndef PWM_EMBEDDED treeEntry->insertTitle(i18n("Categories:")); #endif QString msg(IS_DEEPLOCKED_SHORTMSG); msg += " "; msg += i18n("(Click here to unlock)"); treeEntry->insertItem(msg, document, SLOT(_deepUnlock())); insertMainWndCtrl(treeEntry, document); } else { rebuildTree(treeEntry, document, &newTreeItem.activeItems); } newTreeItem.menuId = id; newTreeItem.doc = document; newTreeItem.menu = treeEntry; if (treeItemNum == -1) { #ifndef PWM_EMBEDDED tree.push_back(newTreeItem); #else tree.append(newTreeItem); #endif } else { tree[treeItemNum] = newTreeItem; } } void PwMTray::closeTreeEntry(PwMDoc *document) { KPopupMenu *menu; int treeItem; int id = findTreeEntry(document, &menu, &treeItem); if (id != -1) { removeTreeEntry(id, treeItem, &menu); } } int PwMTray::findTreeEntry(PwMDoc *doc, KPopupMenu **menu, int *treeItem) { PWM_ASSERT(doc); #ifndef PWM_EMBEDDED int i, count = tree.size(); #else int i, count = tree.count(); #endif for (i = 0; i < count; ++i) { if (tree[i].doc == doc) { if (menu) *menu = tree[i].menu; if (treeItem) *treeItem = i; return tree[i].menuId; } } if (menu) *menu = 0; if (treeItem) *treeItem = -1; return -1; } int PwMTray::insertTreeEntry(PwMDoc *doc, KPopupMenu **popup) { PWM_ASSERT(doc); PWM_ASSERT(popup); KPopupMenu *ctxMenu = contextMenu(); *popup = new KPopupMenu(ctxMenu); return ctxMenu->insertItem(doc->getTitle(), *popup, -1, 1); } void PwMTray::removeTreeEntry(int menuId, int treeItem, KPopupMenu **menu) { PWM_ASSERT(menu); KPopupMenu *ctxMenu = contextMenu(); ctxMenu->removeItem(menuId); delete_and_null(*menu); #ifndef PWM_EMBEDDED tree.erase(tree.at(treeItem)); #else tree.remove(tree.at(treeItem)); #endif } void PwMTray::mouseReleaseEvent(QMouseEvent *e) { QWidget *curWnd = init->curWidget(); KPopupMenu *ctxMenu = contextMenu(); // give focus to init->curWidget() if (curWnd && !curWnd->hasFocus()) { curWnd->hide(); curWnd->showNormal(); curWnd->setFocus(); } // popup the context menu ctxMenu->popup(e->globalPos()); emit clickedIcon(this); } void PwMTray::connectDocToTray(PwMDoc *doc) { connect(doc, SIGNAL(dataChanged(PwMDoc *)), this, SLOT(updateTree(PwMDoc *))); connect(doc, SIGNAL(docClosed(PwMDoc *)), this, SLOT(closeTreeEntry(PwMDoc *))); // fake a dataChanged signal for this doc to update the tray tree. updateTree(doc); } void PwMTray::openDoc() { // open the document in a new window. PwM *newInstance = init->createMainWnd(); PwMDoc *newDoc = newInstance->openDoc(""); if (!newDoc) { newInstance->setForceQuit(true); delete_and_null(newInstance); } } void PwMTray::newMainWnd() { init->createMainWnd(); } void PwMTray::undock() { conf()->confGlobTray(false); init->initTray(); // Attention! "this" is already deleted here! } #ifndef PWM_EMBEDDED #include "pwmtray.moc" #endif diff --git a/pwmanager/pwmanager/pwmview.cpp b/pwmanager/pwmanager/pwmview.cpp index c09fbf5..58c2fca 100644 --- a/pwmanager/pwmanager/pwmview.cpp +++ b/pwmanager/pwmanager/pwmview.cpp @@ -1,452 +1,456 @@ /*************************************************************************** * * * copyright (C) 2003, 2004 by Michael Buesch * * email: mbuesch@freenet.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License version 2 * * as published by the Free Software Foundation. * * * ***************************************************************************/ /*************************************************************************** * copyright (C) 2004 by Ulf Schenk * This file is originaly based on version 1.0.1 of pwmanager * and was modified to run on embedded devices that run microkde * * $Id$ **************************************************************************/ #include "pwmview.h" #include "pwmexception.h" #include "globalstuff.h" #include "pwm.h" #include "rencatwnd.h" +#ifndef PWM_EMBEDDED #include "configuration.h" +#else +#include "pwmprefs.h" +#endif #include "commentbox.h" #include <kmessagebox.h> #include <klocale.h> #include <qlineedit.h> #include <qpoint.h> #include <qapplication.h> #define COLUMN_DESC 0 #define COLUMN_NAME 1 #define COLUMN_PW 2 #define COLUMN_URL 3 #define COLUMN_LAUNCHER 4 PwMView::PwMView(PwM *_mainClass, QWidget *parent, PwMDoc *_doc, const char *name) : PwMViewStyle(parent, name) { PWM_ASSERT(_mainClass); PWM_ASSERT(parent); PWM_ASSERT(_doc); setView(this); doc = _doc; doc->setListViewPointer(this); mainClass = _mainClass; resize(_mainClass->size()); initStyle(conf()->confWndMainViewStyle()); initCtxMenu(); doc->setCurrentView(this); connect(doc, SIGNAL(dataChanged(PwMDoc *)), this, SLOT(updateView())); } PwMView::~PwMView() { } void PwMView::initCtxMenu() { ctxMenu = new QPopupMenu(this); ctxMenu->insertItem(i18n("&Add password"), mainClass, SLOT(addPwd_slot())); ctxMenu->insertSeparator(); ctxMenu->insertItem(i18n("&Edit"), mainClass, SLOT(editPwd_slot())); ctxMenu->insertItem(i18n("&Delete"), mainClass, SLOT(deletePwd_slot())); ctxMenu->insertSeparator(); ctxMenu->insertItem(i18n("copy password to clipboard"), this, SLOT(copyPwToClip())); ctxMenu->insertItem(i18n("copy username to clipboard"), this, SLOT(copyNameToClip())); ctxMenu->insertItem(i18n("copy description to clipboard"), this, SLOT(copyDescToClip())); ctxMenu->insertItem(i18n("copy url to clipboard"), this, SLOT(copyUrlToClip())); ctxMenu->insertItem(i18n("copy launcher to clipboard"), this, SLOT(copyLauncherToClip())); ctxMenu->insertItem(i18n("copy comment to clipboard"), this, SLOT(copyCommentToClip())); ctxMenu->insertSeparator(); ctxMenu->insertItem(i18n("Execute \"Launcher\""), mainClass, SLOT(execLauncher_slot())); ctxMenu->insertItem(i18n("Go to \"URL\""), mainClass, SLOT(goToURL_slot())); } void PwMView::resizeEvent(QResizeEvent *) { resizeView(size()); } void PwMView::refreshCommentTextEdit(QListViewItem *curItem) { PWM_ASSERT(commentBox); if (!curItem) return; string comment; PwMerror ret; ret = document()->getCommentByLvp(getCurrentCategory(), lv->childCount() - lv->itemIndex(curItem) - 1, &comment); if (ret == e_binEntry) { commentBox->setContent(i18n("This is a binary entry.\n" "It is not a normal password-entry, as it contains " "binary data, which PwManager can't display here.")); } else if (ret == e_normalEntry) { commentBox->setContent(comment.c_str()); } else { BUG(); return; } lv->ensureItemVisible(curItem); } void PwMView::keyReleaseEvent(QKeyEvent * /*e*/) { refreshCommentTextEdit(lv->currentItem()); } bool PwMView::getCurEntryIndex(unsigned int *index) { QListViewItem *current = lv->currentItem(); if (!current) return false; return getDocEntryIndex(index, current); } bool PwMView::getDocEntryIndex(unsigned int *index, const QListViewItem *item) { vector<unsigned int> foundPositions; PwMDataItem curItem; curItem.desc = item->text(COLUMN_DESC).latin1(); curItem.name = item->text(COLUMN_NAME).latin1(); document()->getCommentByLvp(getCurrentCategory(), lv->childCount() - lv->itemIndex(item) - 1, &curItem.comment); curItem.url = item->text(COLUMN_URL).latin1(); curItem.launcher = item->text(COLUMN_LAUNCHER).latin1(); document()->findEntry(getCurrentCategory(), curItem, SEARCH_IN_DESC | SEARCH_IN_NAME | SEARCH_IN_COMMENT | SEARCH_IN_URL | SEARCH_IN_LAUNCHER, &foundPositions, true); if (foundPositions.size()) { *index = foundPositions[0]; return true; } return false; } void PwMView::handleToggle(QListViewItem *item) { PWM_ASSERT(doc); if (!item) return; QCheckListItem *clItem = (QCheckListItem *)item; QString curCat(getCurrentCategory()); // find document position of this entry. unsigned int curEntryDocIndex; if (!getDocEntryIndex(&curEntryDocIndex, item)) return; // hack to refresh the comment, if only one item is present if (lv->childCount() == 1) refreshCommentTextEdit(lv->currentItem()); if (doc->isLocked(curCat, curEntryDocIndex) != clItem->isOn()) return; // this is just a click somewhere on the entry if (doc->isDeepLocked()) { PwMerror ret; ret = doc->deepLock(false); if (ret != e_success) clItem->setOn(false); return; } doc->lockAt(curCat, curEntryDocIndex, !clItem->isOn()); } void PwMView::handleRightClick(QListViewItem *item, const QPoint &point, int) { if (!item) return; ctxMenu->move(point); /* don't use ctxMenu->exec() here, as it generates race conditions * with the card interface code. Believe it or not. :) */ ctxMenu->show(); } void PwMView::updateCategories() { QString oldSel(getCurrentCategory()); delAllCategories(); QStringList catList; document()->getCategoryList(&catList); catList.sort(); #ifndef PWM_EMBEDDED QStringList::iterator i = catList.begin(), end = catList.end(); #else QStringList::Iterator i = catList.begin(), end = catList.end(); #endif while (i != end) { addCategory(*i); ++i; } selectCategory(oldSel); } void PwMView::shiftToView() { int cX = lv->contentsX(); int cY = lv->contentsY(); commentBox->clear(); unsigned int catDocIndex; if (unlikely( !(document()->findCategory(getCurrentCategory(), &catDocIndex)))) { BUG(); } // ensure all listViewPos are set doc->ensureLvp(); // clear all tmp-data vectors unsigned int i, entries = doc->numEntries(catDocIndex); if (entries) { mainClass->setVirgin(false); } vector<PwMDataItem> tmpSorted; PwMDataItem currItem; currItem.clear(); tmpSorted.insert(tmpSorted.begin(), entries, currItem); // Sort items and store them in tempoary tmpSorted. for (i = 0; i < entries; ++i) { doc->getEntry(catDocIndex, i, &currItem); tmpSorted[currItem.listViewPos] = currItem; } // shift tempoary data to ListView. tmpDisableSort(); lv->clear(); QCheckListItem *newItem; vector<PwMDataItem>::iterator it = tmpSorted.begin(), end = tmpSorted.end(); while (it != end) { newItem = new ListViewItemPwM(lv); newItem->setText(COLUMN_DESC, (*it).desc.c_str()); if ((*it).binary) { newItem->setText(COLUMN_NAME, ""); newItem->setText(COLUMN_PW, i18n("<BINARY ENTRY>")); newItem->setText(COLUMN_URL, ""); newItem->setText(COLUMN_LAUNCHER, (*it).launcher.c_str()); } else { newItem->setText(COLUMN_NAME, (*it).name.c_str()); if ((*it).lockStat) { newItem->setText(COLUMN_PW, QString((*it).pw.c_str()) + " " + i18n("To unlock click the icon on the left.")); } else { newItem->setText(COLUMN_PW, (*it).pw.c_str()); } newItem->setText(COLUMN_URL, (*it).url.c_str()); newItem->setText(COLUMN_LAUNCHER, (*it).launcher.c_str()); } newItem->setOn(!((*it).lockStat)); lv->insertItem(newItem); ++it; } tmpReEnableSort(); if (cY || cX) lv->setContentsPos(cX, cY); } void PwMView::reorgLp() { if (!lv->childCount()) return; PWM_ASSERT(doc); PWM_ASSERT(!doc->isDocEmpty()); QListViewItem *currItem; vector<unsigned int> foundPos; /* This searchIn _should_ be: * const unsigned int searchIn = SEARCH_IN_DESC; * But we want backward compatibility (see comment in PwMDoc::addEntry()). * So we need to search again, if we don't find the entry. (see below) */ const unsigned int searchIn = SEARCH_IN_DESC | SEARCH_IN_NAME | SEARCH_IN_URL | SEARCH_IN_LAUNCHER; QString curCat(getCurrentCategory()); PwMDataItem findThis; unsigned int i, cnt = lv->childCount(); for (i = 0; i < cnt; ++i) { currItem = lv->itemAtIndex(i); findThis.desc = currItem->text(COLUMN_DESC).latin1(); findThis.name = currItem->text(COLUMN_NAME).latin1(); findThis.url = currItem->text(COLUMN_URL).latin1(); findThis.launcher = currItem->text(COLUMN_LAUNCHER).latin1(); doc->findEntry(curCat, findThis, searchIn, &foundPos, true); if (!foundPos.size()) { /* Did not find the entry. We seem to have a binary * entry here (pray for it!). So search again with * the "correct" searchIn flags. */ const unsigned int searchIn2 = SEARCH_IN_DESC; doc->findEntry(curCat, findThis, searchIn2, &foundPos, true); if (unlikely(!foundPos.size())) { BUG(); continue; } /* We assert that it's a binary entry, now. * No chance to efficiently verify it here. */ } doc->setListViewPos(curCat, foundPos[0], cnt - i - 1); } } void PwMView::selAt(int index) { QListViewItem *item = lv->itemAtIndex(index); if (!item) return; lv->setCurrentItem(item); lv->ensureItemVisible(item); } void PwMView::renCatButton_slot() { if (doc->isDeepLocked()) return; RenCatWnd wnd(this); if (wnd.exec() == 1) { QString newName(wnd.getNewName()); if (newName == "") return; document()->renameCategory(getCurrentCategory(), newName); } } void PwMView::delCatButton_slot() { if (doc->isDeepLocked()) return; if (numCategories() <= 1) { mainClass->showStatMsg(i18n("Can't remove the last category.")); return; } if (KMessageBox::questionYesNo(this, i18n("Do you really want to " "delete the selected " "category? All password-" "entries will be lost in " "this category!"), i18n("Delete category?")) == KMessageBox::No) { return; } document()->delCategory(getCurrentCategory()); } void PwMView::copyPwToClip() { if (doc->isDeepLocked()) return; unsigned int curIndex = 0; if (!getCurEntryIndex(&curIndex)) return; PwMDataItem d; document()->getDataChangedLock(); document()->getEntry(getCurrentCategory(), curIndex, &d, true); document()->putDataChangedLock(); PwM::copyToClipboard(d.pw.c_str()); } void PwMView::copyNameToClip() { if (doc->isDeepLocked()) return; unsigned int curIndex = 0; if (!getCurEntryIndex(&curIndex)) return; PwMDataItem d; document()->getEntry(getCurrentCategory(), curIndex, &d); PwM::copyToClipboard(d.name.c_str()); } void PwMView::copyDescToClip() { if (doc->isDeepLocked()) return; unsigned int curIndex = 0; if (!getCurEntryIndex(&curIndex)) return; PwMDataItem d; document()->getEntry(getCurrentCategory(), curIndex, &d); PwM::copyToClipboard(d.desc.c_str()); } void PwMView::copyUrlToClip() { if (doc->isDeepLocked()) return; unsigned int curIndex = 0; if (!getCurEntryIndex(&curIndex)) return; PwMDataItem d; document()->getEntry(getCurrentCategory(), curIndex, &d); PwM::copyToClipboard(d.url.c_str()); } void PwMView::copyLauncherToClip() { if (doc->isDeepLocked()) return; unsigned int curIndex = 0; if (!getCurEntryIndex(&curIndex)) return; PwMDataItem d; document()->getEntry(getCurrentCategory(), curIndex, &d); PwM::copyToClipboard(d.launcher.c_str()); } void PwMView::copyCommentToClip() { if (doc->isDeepLocked()) return; unsigned int curIndex = 0; if (!getCurEntryIndex(&curIndex)) return; PwMDataItem d; document()->getEntry(getCurrentCategory(), curIndex, &d); PwM::copyToClipboard(d.comment.c_str()); } #ifndef PWM_EMBEDDED #include "pwmview.moc" #endif diff --git a/pwmanager/pwmanager/serializer.cpp b/pwmanager/pwmanager/serializer.cpp index 65e442d..f29ef6c 100644 --- a/pwmanager/pwmanager/serializer.cpp +++ b/pwmanager/pwmanager/serializer.cpp @@ -1,664 +1,665 @@ /*************************************************************************** * * * copyright (C) 2004 by Michael Buesch * * email: mbuesch@freenet.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License version 2 * * as published by the Free Software Foundation. * * * ***************************************************************************/ /*************************************************************************** * copyright (C) 2004 by Ulf Schenk * This file is originaly based on version 2.0 of pwmanager * and was modified to run on embedded devices that run microkde * * $Id$ **************************************************************************/ #include "serializer.h" #include "pwmexception.h" #ifdef PWM_EMBEDDED +#include <kglobal.h> #include <klocale.h> #endif /* enable/disable serializer debugging (0/1) */ #define SERIALIZER_DEBUG 0 /* use the old xml tags for writing (0/1) */ #define USE_OLD_TAGS 0 /* write a CDATA section (0/1) */ #define WRITE_CDATA_SEC 0 #define META_CREATE_DATE "c" #define META_VALID_DATE "v" #define META_EXPIRE_DATE "e" #define META_UPDATE_DATE "u" #define META_UPDATE_INT "i" //US ENH : uniqueid #define META_UNIQUEID "n" /* This is compatibility stuff. * The names of the entries have changed and here are the * new and old ones */ #define ROOT_MAGIC_OLD "PwM-xml-dat" #define VER_STR_OLD "ver" #define COMPAT_VER_OLD "0x02" #define CAT_ROOT_OLD "categories" #define CAT_PREFIX_OLD "cat_" #define CAT_NAME_OLD "name" #define ENTRY_PREFIX_OLD "entry_" #define ENTRY_DESC_OLD "desc" #define ENTRY_NAME_OLD "name" #define ENTRY_PW_OLD "pw" #define ENTRY_COMMENT_OLD "comment" #define ENTRY_URL_OLD "url" #define ENTRY_LAUNCHER_OLD "launcher" #define ENTRY_LVP_OLD "listViewPos" #define ENTRY_BIN_OLD "b" #define ENTRY_META_OLD "m" #define ROOT_MAGIC_NEW "P" #define VER_STR_NEW "v" #define COMPAT_VER_NEW "2" #define CAT_ROOT_NEW "c" #define CAT_PREFIX_NEW "c" #define CAT_NAME_NEW "n" #define ENTRY_PREFIX_NEW "e" #define ENTRY_DESC_NEW "d" #define ENTRY_NAME_NEW "n" #define ENTRY_PW_NEW "p" #define ENTRY_COMMENT_NEW "c" #define ENTRY_URL_NEW "u" #define ENTRY_LAUNCHER_NEW "l" #define ENTRY_LVP_NEW "v" #define ENTRY_BIN_NEW ENTRY_BIN_OLD #define ENTRY_META_NEW ENTRY_META_OLD #if USE_OLD_TAGS != 0 # define ROOT_MAGIC_WR ROOT_MAGIC_OLD # define VER_STR_WR VER_STR_OLD # define COMPAT_VER_WR COMPAT_VER_OLD # define CAT_ROOT_WR CAT_ROOT_OLD # define CAT_PREFIX_WR CAT_PREFIX_OLD # define CAT_NAME_WR CAT_NAME_OLD # define ENTRY_PREFIX_WR ENTRY_PREFIX_OLD # define ENTRY_DESC_WR ENTRY_DESC_OLD # define ENTRY_NAME_WR ENTRY_NAME_OLD # define ENTRY_PW_WR ENTRY_PW_OLD # define ENTRY_COMMENT_WR ENTRY_COMMENT_OLD # define ENTRY_URL_WR ENTRY_URL_OLD # define ENTRY_LAUNCHER_WR ENTRY_LAUNCHER_OLD # define ENTRY_LVP_WR ENTRY_LVP_OLD # define ENTRY_BIN_WR ENTRY_BIN_OLD # define ENTRY_META_WR ENTRY_META_OLD #else # define ROOT_MAGIC_WR ROOT_MAGIC_NEW # define VER_STR_WR VER_STR_NEW # define COMPAT_VER_WR COMPAT_VER_NEW # define CAT_ROOT_WR CAT_ROOT_NEW # define CAT_PREFIX_WR CAT_PREFIX_NEW # define CAT_NAME_WR CAT_NAME_NEW # define ENTRY_PREFIX_WR ENTRY_PREFIX_NEW # define ENTRY_DESC_WR ENTRY_DESC_NEW # define ENTRY_NAME_WR ENTRY_NAME_NEW # define ENTRY_PW_WR ENTRY_PW_NEW # define ENTRY_COMMENT_WR ENTRY_COMMENT_NEW # define ENTRY_URL_WR ENTRY_URL_NEW # define ENTRY_LAUNCHER_WR ENTRY_LAUNCHER_NEW # define ENTRY_LVP_WR ENTRY_LVP_NEW # define ENTRY_BIN_WR ENTRY_BIN_NEW # define ENTRY_META_WR ENTRY_META_NEW #endif Serializer::Serializer() { defaultLockStat = true; domDoc = new QDomDocument; } Serializer::Serializer(const QCString &buffer) { defaultLockStat = true; domDoc = new QDomDocument; if (!parseXml(buffer)) { delete domDoc; #ifndef PWM_EMBEDDED throw PwMException(PwMException::EX_PARSE); #else qDebug("Serializer::Serializer : Parse Exception "); #endif } } Serializer::~Serializer() { delete_ifnot_null(domDoc); } void Serializer::clear() { delete_ifnot_null(domDoc); domDoc = new QDomDocument; } bool Serializer::parseXml(const QCString &buffer) { PWM_ASSERT(domDoc); #ifndef PWM_EMBEDDED if (!domDoc->setContent(buffer, true)) return false; #else if (!domDoc->setContent(buffer)) return false; #endif if (!checkValid()) return false; return true; } QCString Serializer::getXml() { PWM_ASSERT(domDoc); #ifndef PWM_EMBEDDED #if defined(PWM_DEBUG) && SERIALIZER_DEBUG != 0 QCString tmp(domDoc->toCString(8)); printDebug("<BEGIN Serializer::getXml() dump>\n"); cout << tmp << endl; printDebug("<END Serializer::getXml() dump>"); #endif // DEBUG QCString ret(domDoc->toCString(0)); ret.replace('\n', ""); return ret; #else #if defined(PWM_DEBUG) && SERIALIZER_DEBUG != 0 QCString tmp(" " + domDoc->toCString()); printDebug("<BEGIN Serializer::getXml() dump>\n"); cout << tmp << endl; printDebug("<END Serializer::getXml() dump>"); #endif // DEBUG QCString ret(domDoc->toCString()); ret.replace(QRegExp("\n"), ""); return ret; #endif } bool Serializer::serialize(const vector<PwMCategoryItem> &dta) { PWM_ASSERT(domDoc); QDomElement root(genNewRoot()); QDomElement catNode(domDoc->createElement(CAT_ROOT_WR)); root.appendChild(catNode); if (!addCategories(&catNode, dta)) return false; return true; } bool Serializer::deSerialize(vector<PwMCategoryItem> *dta) { PWM_ASSERT(domDoc); PWM_ASSERT(dta); QDomElement root(domDoc->documentElement()); QDomNode n; dta->clear(); for (n = root.firstChild(); !n.isNull(); n = n.nextSibling()) { // find <categories> ... </categories> // <c> ... </c> if (n.nodeName() == CAT_ROOT_NEW || n.nodeName() == CAT_ROOT_OLD) { if (!readCategories(n, dta)) { return false; } /* NOTE: We can stop processing here, as we * don't have more nodes in root, yet. */ return true; } } return false; } bool Serializer::readCategories(const QDomNode &n, vector<PwMCategoryItem> *dta) { QDomNodeList nl(n.childNodes()); QDomNode cur; QString name; unsigned int numCat = nl.count(), i; PwMCategoryItem curCat; vector<PwMDataItem> curEntr; if (!numCat) { printDebug("Serializer::readCategories(): empty"); return false; } for (i = 0; i < numCat; ++i) { cur = nl.item(i); if (cur.nodeName().left(1) == CAT_PREFIX_NEW || cur.nodeName().left(4) == CAT_PREFIX_OLD) { name = cur.toElement().attribute(CAT_NAME_NEW); if (name == QString::null) name = cur.toElement().attribute(CAT_NAME_OLD); PWM_ASSERT(name != QString::null); PWM_ASSERT(name != ""); curCat.clear(); curCat.name = name.latin1(); if (!readEntries(cur, &curEntr)) { dta->clear(); return false; } curCat.d = curEntr; dta->push_back(curCat); } else { printDebug("Serializer::readCategories(): uh? not a category?"); } } return true; } bool Serializer::readEntries(const QDomNode &n, vector<PwMDataItem> *dta) { QDomNodeList nl(n.childNodes()); QDomNode cur; unsigned int numEntr = nl.count(), i; PwMDataItem curEntr; dta->clear(); for (i = 0; i < numEntr; ++i) { cur = nl.item(i); if (cur.nodeName().left(1) == ENTRY_PREFIX_NEW || cur.nodeName().left(6) == ENTRY_PREFIX_OLD) { if (!extractEntry(cur, &curEntr)) { return false; } dta->push_back(curEntr); } else { printDebug("Serializer::readEntries(): hm? not an entry?"); } } return true; } bool Serializer::extractEntry(const QDomNode &n, PwMDataItem *dta) { QDomNodeList nl(n.childNodes()); QDomNode cur, cdata; unsigned int cnt = nl.count(), i; QString name, text; if (!cnt) { printDebug("Serializer::extractEntry(): empty"); return false; } dta->clear(); for (i = 0; i < cnt; ++i) { cur = nl.item(i); name = cur.nodeName(); cdata = cur.firstChild(); if (unlikely(cdata.isCDATASection())) { text = cdata.toCDATASection().data(); } else if (likely(cur.isElement())) { text = cur.toElement().text(); } else { printDebug("Serializer::extractEntry(): neither CDATA nor element."); return false; } if (text == " ") text = ""; // for backward compatibility. if (name == ENTRY_DESC_NEW || name == ENTRY_DESC_OLD) { dta->desc = unescapeEntryData(text).latin1(); } else if (name == ENTRY_NAME_NEW || name == ENTRY_NAME_OLD) { dta->name = unescapeEntryData(text).latin1(); } else if (name == ENTRY_PW_NEW || name == ENTRY_PW_OLD) { dta->pw = unescapeEntryData(text).latin1(); } else if (name == ENTRY_COMMENT_NEW || name == ENTRY_COMMENT_OLD) { dta->comment = unescapeEntryData(text).latin1(); } else if (name == ENTRY_URL_NEW || name == ENTRY_URL_OLD) { dta->url = unescapeEntryData(text).latin1(); } else if (name == ENTRY_LAUNCHER_NEW || name == ENTRY_LAUNCHER_OLD) { dta->launcher = unescapeEntryData(text).latin1(); } else if (name == ENTRY_LVP_NEW || name == ENTRY_LVP_OLD) { dta->listViewPos = strtol(text.latin1(), 0, 10); } else if (name == ENTRY_BIN_NEW) { // ENTRY_BIN_NEW == ENTRY_BIN_OLD if (text == "0") { dta->binary = false; } else { dta->binary = true; } } else if (name == ENTRY_META_NEW) { // ENTRY_META_NEW == ENTRY_META_OLD if (!extractMeta(cur, &dta->meta)) return false; } else { printDebug(string("Serializer::extractEntry(): invalid: ") + name.latin1()); } } dta->lockStat = defaultLockStat; return true; } bool Serializer::extractMeta(const QDomNode &n, PwMMetaData *dta) { QDomNode cur(n.firstChild()); QString name, val; while (!cur.isNull()) { name = cur.nodeName(); val = cur.toElement().text(); if (val == "") { cur = cur.nextSibling(); continue; } #ifndef PWM_EMBEDDED if (name == META_CREATE_DATE) { dta->create = QDateTime::fromString(val, Qt::ISODate); } else if (name == META_VALID_DATE) { dta->valid = QDateTime::fromString(val, Qt::ISODate); } else if (name == META_EXPIRE_DATE) { dta->expire = QDateTime::fromString(val, Qt::ISODate); } else if (name == META_UPDATE_DATE) { dta->update = QDateTime::fromString(val, Qt::ISODate); } else if (name == META_UPDATE_INT) { dta->updateInt = strtoul(val.latin1(), 0, 10); } else if (name == META_UNIQUEID) { dta->uniqueid = unescapeEntryData(val).latin1(); } else { printDebug(string("extractMeta(): invalid: ") + name.latin1()); } #else QDateTime m_dt; if ((name == META_CREATE_DATE) || (name == META_VALID_DATE) || (name == META_EXPIRE_DATE) || (name == META_UPDATE_DATE)) { int pos = val.find("T"); QString date = val.left(pos); QString time = val.mid(pos+1); qDebug("Serializer::extractMeta : date=%s ,time=%s",date.latin1(), time.latin1() ); bool ok1, ok2; QDate m_date = KGlobal::locale()->readDate(date, &ok1); QTime m_time = KGlobal::locale()->readTime(time, &ok2); if ((ok1 == false) || (ok2 == false)) qDebug("Serializer::extractMeta invalid date or time !!!!!!!!!!!!!"); m_dt.setDate(m_date); m_dt.setTime(m_time); } if (name == META_CREATE_DATE) { dta->create = m_dt; } else if (name == META_VALID_DATE) { dta->valid = m_dt; } else if (name == META_EXPIRE_DATE) { dta->expire = m_dt; } else if (name == META_UPDATE_DATE) { dta->update = m_dt; } else if (name == META_UPDATE_INT) { dta->updateInt = strtoul(val.latin1(), 0, 10); } else if (name == META_UNIQUEID) { dta->uniqueid = unescapeEntryData(val).latin1(); } else { printDebug(string("extractMeta(): invalid: ") + name.latin1()); } #endif cur = cur.nextSibling(); } return true; } bool Serializer::checkValid() { PWM_ASSERT(domDoc); QDomElement root(domDoc->documentElement()); if (root.nodeName() != ROOT_MAGIC_NEW && root.nodeName() != ROOT_MAGIC_OLD) { printDebug("Serializer: wrong magic"); return false; } if (root.attribute(VER_STR_NEW) != COMPAT_VER_NEW && root.attribute(VER_STR_OLD) != COMPAT_VER_OLD) { printDebug("Serializer: wrong version"); return false; } return true; } QDomElement Serializer::genNewRoot() { PWM_ASSERT(domDoc); QDomElement root(domDoc->createElement(ROOT_MAGIC_WR)); root.setAttribute(VER_STR_WR, COMPAT_VER_WR); domDoc->appendChild(root); return root; } bool Serializer::addCategories(QDomElement *e, const vector<PwMCategoryItem> &dta) { unsigned int numCat = dta.size(), i; QString curId, curName; QDomElement curCat; for (i = 0; i < numCat; ++i) { curId = CAT_PREFIX_WR; curId += tostr(i).c_str(); curName = dta[i].name.c_str(); curCat = domDoc->createElement(curId); curCat.setAttribute(CAT_NAME_WR, curName); if (!addEntries(&curCat, dta[i].d)) { return false; } e->appendChild(curCat); } return true; } bool Serializer::addEntries(QDomElement *e, const vector<PwMDataItem> &dta) { unsigned int numEntr = dta.size(), i; QString curId; QDomElement curEntr; for (i = 0; i < numEntr; ++i) { curId = ENTRY_PREFIX_WR; curId += tostr(i).c_str(); curEntr = domDoc->createElement(curId); if (!writeEntry(&curEntr, dta[i])) { return false; } e->appendChild(curEntr); } return true; } bool Serializer::writeEntry(QDomElement *e, const PwMDataItem &_dta) { #if WRITE_CDATA_SEC != 0 # define new_text(x) domDoc->createCDATASection(x) QDomCDATASection curText; #else # define new_text(x) domDoc->createTextNode(x) QDomText curText; #endif QDomText plainText; QDomElement tag; // begin -- This is for compatibility with the old serializer PwMDataItem dta = _dta; if (!dta.desc.size()) dta.desc = " "; if (!dta.name.size()) dta.name = " "; if (!dta.pw.size()) dta.pw = " "; if (!dta.comment.size()) dta.comment = " "; if (!dta.url.size()) dta.url = " "; if (!dta.launcher.size()) dta.launcher = " "; // end -- This is for compatibility with the old serializer tag = domDoc->createElement(ENTRY_DESC_WR); curText = new_text(escapeEntryData(dta.desc.c_str())); tag.appendChild(curText); e->appendChild(tag); tag = domDoc->createElement(ENTRY_NAME_WR); curText = new_text(escapeEntryData(dta.name.c_str())); tag.appendChild(curText); e->appendChild(tag); tag = domDoc->createElement(ENTRY_PW_WR); curText = new_text(escapeEntryData(dta.pw.c_str())); tag.appendChild(curText); e->appendChild(tag); tag = domDoc->createElement(ENTRY_COMMENT_WR); curText = new_text(escapeEntryData(dta.comment.c_str())); tag.appendChild(curText); e->appendChild(tag); tag = domDoc->createElement(ENTRY_URL_WR); curText = new_text(escapeEntryData(dta.url.c_str())); tag.appendChild(curText); e->appendChild(tag); tag = domDoc->createElement(ENTRY_LAUNCHER_WR); curText = new_text(escapeEntryData(dta.launcher.c_str())); tag.appendChild(curText); e->appendChild(tag); tag = domDoc->createElement(ENTRY_LVP_WR); plainText = domDoc->createTextNode(tostr(dta.listViewPos).c_str()); tag.appendChild(plainText); e->appendChild(tag); tag = domDoc->createElement(ENTRY_BIN_WR); if (dta.binary) plainText = domDoc->createTextNode("1"); else plainText = domDoc->createTextNode("0"); tag.appendChild(plainText); e->appendChild(tag); tag = domDoc->createElement(ENTRY_META_WR); if (!writeMeta(&tag, dta.meta)) return false; e->appendChild(tag); #undef new_text return true; } bool Serializer::writeMeta(QDomElement *e, const PwMMetaData &dta) { QDomText text; QDomElement tag; tag = domDoc->createElement(META_CREATE_DATE); #ifndef PWM_EMBEDDED text = domDoc->createTextNode(dta.create.toString(Qt::ISODate)); #else text = domDoc->createTextNode(KGlobal::locale()->formatDateTime(dta.create, KLocale::ISODate)); #endif tag.appendChild(text); e->appendChild(tag); tag = domDoc->createElement(META_VALID_DATE); #ifndef PWM_EMBEDDED text = domDoc->createTextNode(dta.valid.toString(Qt::ISODate)); #else text = domDoc->createTextNode(KGlobal::locale()->formatDateTime(dta.valid, KLocale::ISODate)); #endif tag.appendChild(text); e->appendChild(tag); tag = domDoc->createElement(META_EXPIRE_DATE); #ifndef PWM_EMBEDDED text = domDoc->createTextNode(dta.expire.toString(Qt::ISODate)); #else text = domDoc->createTextNode(KGlobal::locale()->formatDateTime(dta.expire, KLocale::ISODate)); #endif tag.appendChild(text); e->appendChild(tag); tag = domDoc->createElement(META_UPDATE_DATE); #ifndef PWM_EMBEDDED text = domDoc->createTextNode(dta.update.toString(Qt::ISODate)); #else text = domDoc->createTextNode(KGlobal::locale()->formatDateTime(dta.update, KLocale::ISODate)); #endif tag.appendChild(text); e->appendChild(tag); tag = domDoc->createElement(META_UPDATE_INT); text = domDoc->createTextNode(tostr(dta.updateInt).c_str()); tag.appendChild(text); e->appendChild(tag); tag = domDoc->createElement(META_UNIQUEID); text = domDoc->createTextNode(escapeEntryData(dta.uniqueid)); tag.appendChild(text); e->appendChild(tag); #undef new_text return true; } QString Serializer::escapeEntryData(QString dta) { #ifndef PWM_EMBEDDED dta.replace('\n', "$>--endl--<$"); dta.replace("]]>", "||>"); #else dta.replace(QRegExp("\n"), "$>--endl--<$"); dta.replace(QRegExp("]]>"), "||>"); #endif return dta; } QString Serializer::unescapeEntryData(QString dta) { #ifndef PWM_EMBEDDED dta.replace("$>--endl--<$", "\n"); dta.replace("||>", "]]>"); #else dta.replace(QRegExp("$>--endl--<$"), "\n"); dta.replace(QRegExp("||>"), "]]>"); #endif return dta; } |