-rw-r--r-- | pwmanager/pwmanager/editcategory.cpp | 188 | ||||
-rw-r--r-- | pwmanager/pwmanager/editcategory.h | 77 | ||||
-rw-r--r-- | pwmanager/pwmanager/pwm.cpp | 69 | ||||
-rw-r--r-- | pwmanager/pwmanager/pwm.h | 1 | ||||
-rw-r--r-- | pwmanager/pwmanager/pwmanager.pro | 2 | ||||
-rw-r--r-- | pwmanager/pwmanager/pwmanagerE.pro | 2 | ||||
-rw-r--r-- | pwmanager/pwmanager/pwmdoc.cpp | 5 | ||||
-rw-r--r-- | pwmanager/pwmanager/pwmdoc.h | 14 | ||||
-rw-r--r-- | pwmanager/pwmanager/pwmview.cpp | 10 | ||||
-rw-r--r-- | pwmanager/pwmanager/serializer.cpp | 44 |
10 files changed, 411 insertions, 1 deletions
diff --git a/pwmanager/pwmanager/editcategory.cpp b/pwmanager/pwmanager/editcategory.cpp new file mode 100644 index 0000000..4e55de8 --- a/dev/null +++ b/pwmanager/pwmanager/editcategory.cpp @@ -0,0 +1,188 @@ +/* + This file is part of PwManager/Platform independent. + Copyright (c) 2004 Ulf Schenk + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. + +$Id$ +*/ + +#include "editcategory.h" +#include "pwmdoc.h" + +#include <qlayout.h> +#include <qlabel.h> +#include <qgroupbox.h> +#include <klocale.h> +#include <kcombobox.h> +#include <klineedit.h> +#include <qpushbutton.h> + + +/* + * Constructs a addEntryWnd 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. + */ +editCategoryWnd::editCategoryWnd( PwMDoc* d, QWidget* parent, const char* name) + : KDialogBase( KDialogBase::Plain, i18n( "edit category descriptions" ), + Apply | User2 | Ok, + Ok, parent, name, true ), + doc(d) +{ + findButton( Ok )->setText (i18n("Close" )) ; + findButton( User2 )->setText (i18n("Cancel" )) ; + connect(this,SIGNAL(user2Clicked()), SLOT(cancel_slot())); + enableButton( KDialogBase::Apply, false ); + + + QWidget *page = plainPage(); + QGridLayout *layout = new QGridLayout( page, 3, 1 ); + layout->setMargin( KDialogBase::marginHint() ); + layout->setSpacing( KDialogBase::spacingHint() ); + + int i = 0; + categoryComboBox = new KComboBox( page ); + QLabel* label = new QLabel( categoryComboBox, i18n("Category:"), page ); + layout->addWidget( label, i, 0 ); + layout->addWidget( categoryComboBox, i, 1 ); + i++; + categoryComboBox->setEditable( FALSE ); + categoryComboBox->setSizeLimit( 100 ); + connect(categoryComboBox,SIGNAL(activated(const QString&)), SLOT(categorySelected(const QString&))); + + + descLineEdit = new KLineEdit( page, "descLineEdit" ); + label = new QLabel( descLineEdit, i18n("Text1 (Description):"), page ); + layout->addWidget( label, i, 0 ); + layout->addWidget( descLineEdit, i, 1 ); + connect( descLineEdit, SIGNAL( textChanged ( const QString & ) ), SLOT( widgetModified(const QString &) ) ); + i++; + + usernameLineEdit = new KLineEdit( page, "usernameLineEdit" ); + label = new QLabel( usernameLineEdit, i18n("Text2 (Username):"), page ); + layout->addWidget( label, i, 0 ); + layout->addWidget( usernameLineEdit, i, 1 ); + connect( usernameLineEdit, SIGNAL( textChanged ( const QString & ) ), SLOT( widgetModified(const QString &) ) ); + i++; + + pwLineEdit = new KLineEdit( page, "pwLineEdit" ); + label = new QLabel( pwLineEdit, i18n("Text3 (Password):"), page ); + layout->addWidget( label, i, 0 ); + layout->addWidget( pwLineEdit, i, 1 ); + connect( pwLineEdit, SIGNAL( textChanged ( const QString & ) ), SLOT( widgetModified(const QString &) ) ); + i++; + + unsigned int count = doc->numCategories(); + + for (unsigned int i = 0; i < count; ++i) { + categoryComboBox->insertItem(doc->getCategory(i)->c_str()); + } + + // PwMCategoryItem* getCategoryEntry(unsigned int index) + // { return &(dti.dta[index]); } + + + +} + +/* + * Destroys the object and frees any allocated resources + */ +editCategoryWnd::~editCategoryWnd() +{ + // no need to delete child widgets, Qt does it all for us +} + +void editCategoryWnd::slotOk() +{ + // qDebug( "addEntryWnd::slotOk(): Not implemented yet" ); + slotApply(); + accept(); +} + +void editCategoryWnd::slotApply() +{ + QString cat = categoryComboBox->currentText(); + + unsigned int idx; + bool found = doc->findCategory(cat, &idx); + + if (found == true) + { + PwMCategoryItem* catitem = doc->getCategoryEntry(idx); + + catitem->desc_text = descLineEdit->text().latin1(); + catitem->name_text = usernameLineEdit->text().latin1(); + catitem->pw_text = pwLineEdit->text().latin1(); + enableButton( KDialogBase::Apply, false ); + return; + } + + BUG(); + +} + +void editCategoryWnd::cancel_slot() +{ + QString cat = categoryComboBox->currentText(); + categorySelected ( cat ); +} + +void editCategoryWnd::setCurrCategory(const QString &cat) +{ + int i, count = categoryComboBox->count(); + + for (i = 0; i < count; ++i) { + if (categoryComboBox->text(i) == cat) { + categoryComboBox->setCurrentItem(i); + categorySelected ( cat ); + return; + } + } + BUG(); +} + +void editCategoryWnd::categorySelected ( const QString & string ) +{ + unsigned int idx; + bool found = doc->findCategory(string, &idx); + + if (found == true) + { + PwMCategoryItem* catitem = doc->getCategoryEntry(idx); + + descLineEdit->setText(catitem->desc_text.c_str()); + usernameLineEdit->setText(catitem->name_text.c_str()); + pwLineEdit->setText(catitem->pw_text.c_str()); + enableButton( KDialogBase::Apply, false ); + return; + } + + BUG(); + +} + +void editCategoryWnd::widgetModified(const QString &) +{ + enableButton( KDialogBase::Apply, true ); +} + diff --git a/pwmanager/pwmanager/editcategory.h b/pwmanager/pwmanager/editcategory.h new file mode 100644 index 0000000..90b685b --- a/dev/null +++ b/pwmanager/pwmanager/editcategory.h @@ -0,0 +1,77 @@ +/* + This file is part of PwManager/Platform independent. + Copyright (c) 2004 Ulf Schenk + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. + +$Id$ +*/ + +#ifndef EDITCATEGORY_H +#define EDITCATEGORY_H + +#include <qvariant.h> +#include <kdialogbase.h> + +class QVBoxLayout; +class QHBoxLayout; +class QGridLayout; +class QSpacerItem; +class KLineEdit; +class QPushButton; +class KComboBox; +class QLabel; +class QGroupBox; +class QMultiLineEdit; +class PwMDoc; + +class editCategoryWnd : public KDialogBase +{ + Q_OBJECT + +public: + editCategoryWnd( PwMDoc* doc, QWidget* parent = 0, const char* name = 0); + ~editCategoryWnd(); + + void setCurrCategory(const QString &cat); + + KComboBox* categoryComboBox; + KLineEdit* descLineEdit; + KLineEdit* usernameLineEdit; + KLineEdit* pwLineEdit; + + //public slots: + // virtual void revealButton_slot(); + // virtual void generateButton_slot(); + // virtual void advancedCommentButton_slot(bool on); + + protected slots: + virtual void slotOk(); + virtual void slotApply(); + virtual void cancel_slot(); + + virtual void categorySelected ( const QString & string ); + virtual void widgetModified(const QString &); + + private: + PwMDoc* doc; + +}; + +#endif // EDITCATEGORY_H diff --git a/pwmanager/pwmanager/pwm.cpp b/pwmanager/pwmanager/pwm.cpp index 6ae6e28..bd98d72 100644 --- a/pwmanager/pwmanager/pwm.cpp +++ b/pwmanager/pwmanager/pwm.cpp @@ -1,215 +1,219 @@ /*************************************************************************** * * * 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> #include <qstatusbar.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> +#include "editcategory.h" #endif #ifndef DESKTOP_VERSION #include <qpe/global.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 "pwmprint.h" #include "addentrywndimpl.h" #include "globalstuff.h" #include "findwndimpl.h" #include "csv.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 +#ifdef PWM_EMBEDDED + ,BUTTON_POPUP_OPTIONS_CATEGORY +#endif }; // Button IDs for "export" popup menu (in "file" popup menu) enum { BUTTON_POPUP_EXPORT_TEXT = 0, BUTTON_POPUP_EXPORT_GPASMAN, BUTTON_POPUP_EXPORT_CSV #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, BUTTON_POPUP_IMPORT_CSV #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, BUTTON_POPUP_HELP_SYNC, BUTTON_POPUP_HELP_WHATSNEW }; #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, "HALLO") , forceQuit (false) , forceMinimizeToTray (false) { syncManager = 0; virgin = !virginity; 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() { qDebug("PwM::~PwM() %x", this); disconnect(curDoc(), SIGNAL(docClosed(PwMDoc *)), this, SLOT(docClosed(PwMDoc *))); conf()->confWndMainWndSize(size()); //LR closing of windows changed //needed for fastload option on PDA //emit closed(this); //qDebug("PwM::~PwM() emited closed(this)"); delete view; delete syncManager; } void PwM::initMenubar() { KIconLoader* picons; #ifndef PWM_EMBEDDED KIconLoader icons; picons = &icons; #else picons = KGlobal::iconLoader(); @@ -267,192 +271,198 @@ void PwM::initMenubar() 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); importPopup->insertItem(i18n("&CSV (Comma Separated Value) ..."), this, SLOT(importCsv()), 0, BUTTON_POPUP_IMPORT_CSV); #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 + optionsPopup->insertItem(QIconSet(picons->loadIcon("configure", KIcon::Small)), + i18n("C&ategories..."), this, + SLOT(category_slot()), + BUTTON_POPUP_OPTIONS_CATEGORY); + + menuBar()->insertItem(i18n("&Sync"), syncPopup); 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); helpPopup->insertItem(i18n("&Sync HowTo"), this, SLOT(syncHowTo_slot()), 0, BUTTON_POPUP_HELP_SYNC); helpPopup->insertItem(i18n("&What's New"), this, SLOT(whatsnew_slot()), 0, BUTTON_POPUP_HELP_WHATSNEW); #endif menuBar()->insertItem(i18n("&Help"), helpPopup); } void PwM::initToolbar() { KIconLoader* picons; #ifndef PWM_EMBEDDED KIconLoader icons; picons = &icons; #else picons = KGlobal::iconLoader(); #endif #ifdef PWM_EMBEDDED if ( QApplication::desktop()->width() > 320 ) #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")); } @@ -1298,181 +1308,240 @@ 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) { #ifdef DESKTOP_VERSION statusBar()->message(msg, STATUSBAR_MSG_TIMEOUT * 1000); #else qDebug("Statusbar : %s",msg.latin1()); Global::statusMessage(msg); #endif } void PwM::focusInEvent(QFocusEvent *e) { if (e->gotFocus()) { emit gotFocus(this); } else if (e->lostFocus()) { emit lostFocus(this); } } #ifdef PWM_EMBEDDED +void PwM::category_slot() +{ + PwMDoc *doc = curDoc(); + PWM_ASSERT(doc); + doc->timer()->getLock(DocTimer::id_autoLockTimer); + + editCategoryWnd w(doc, this, "editcategory"); +/* + 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); +*/ + w.setCurrCategory(view->getCurrentCategory()); + + tryAgain: + if (w.exec() == 1) + { + PwMDataItem d; + + //US BUG: to initialize all values of curEntr with meaningfulldata, + // we call clear on it. Reason: Metadata will be uninitialized otherwise. + // another option would be to create a constructor for PwMDataItem + d.clear(true); + /* + 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\",\n" + "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\nentries" + "has been reached.\nYou 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); +} + + void PwM::whatsnew_slot() { KApplication::showFile( "KDE-Pim/Pi Version Info", "kdepim/WhatsNew.txt" ); } void PwM::showLicense_slot() { KApplication::showLicence(); } void PwM::faq_slot() { KApplication::showFile( "PWM/Pi FAQ", "kdepim/pwmanager/pwmanagerFAQ.txt" ); } void PwM::syncHowTo_slot() { KApplication::showFile( "KDE-Pim/Pi Synchronization HowTo", "kdepim/SyncHowto.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-2004, The KDE PIM Team\n" "(c) Michael Buesch - main programming\nand current maintainer\nmbuesch@freenet.de\n" "Matt Scifo - mscifo@o1.com\n" "Elias Probst - elias.probst@gmx.de\n" "George Staikos - staikos@kde.org\n" "Matthew Palmer - mjp16@uow.edu.au\n" "Olivier Sessink - gpasman@nl.linux.org\n" "The libgcrypt developers -\nBlowfish and SHA1 algorithms\nftp://ftp.gnupg.org/gcrypt/alpha/libgcrypt/\n" "Troy Engel - tengel@sonic.net\n" "Wickey - wickey@gmx.at\n" "Ian MacGregor - original documentation author.\n" ); } //this are the overwritten callbackmethods from the syncinterface bool PwM::sync(KSyncManager* manager, QString filename, int mode) { PWM_ASSERT(curDoc()); bool ret = curDoc()->sync(manager, filename, mode); qDebug("PwM::sync save now: ret=%i", ret); if (ret == true) { //US BUG: what can we call here to update the view of the current doc? //mViewManager->refreshView(); //US curDoc()->sync sets the dirtyFlag in case the sync was successfull. save(); } return ret; } void PwM::removeSyncInfo( QString syncProfile) { qDebug("PWM::not implemented: removeSyncInfo for profile %s ", syncProfile.latin1()); } #endif #ifndef PWM_EMBEDDED #include "pwm.moc" #endif diff --git a/pwmanager/pwmanager/pwm.h b/pwmanager/pwmanager/pwm.h index fb34bca..9fa9edc 100644 --- a/pwmanager/pwmanager/pwm.h +++ b/pwmanager/pwmanager/pwm.h @@ -86,192 +86,193 @@ public: * and write the data to disk. */ bool save(); /** ask the user where to save the doc * and write the data to disk. */ bool saveAs(); /** force quit. Quit this window, always! Don't minimize it */ bool isForceQuit() { return forceQuit; } /** set forceQuit */ void setForceQuit(bool force) { forceQuit = force; } /** force minimize this window */ bool isForceMinimizeToTray() { return forceMinimizeToTray; } /** set forceMinimizeToTray */ void setForceMinimizeToTray(bool force) { forceMinimizeToTray = force; } public slots: /** file/new triggered */ void new_slot(); /** file/open triggered */ //US ENH void open_slot(); void open_slot(QString fn); /** file/close triggered */ void close_slot(); /** file/quit triggered */ void quitButton_slot(); /** file/save triggered */ void save_slot(); /** file/saveAs triggered */ void saveAs_slot(); /** file/export/text triggered */ void exportToText(); /** file/export/gpasman triggered */ void exportToGpasman(); /** file/export/kwallet triggered */ void exportToKWallet(); /** file/export/csv triggered */ void exportToCsv(); /** file/import/text triggered */ bool importFromText(); /** file/import/gpasman triggered */ bool importFromGpasman(); /** file/import/kwallet triggered */ bool importKWallet(); /** file/import/csv triggered */ bool importCsv(); /** file/print triggered */ void print_slot(); /** manage/add triggered */ //US ENH : changed code to run with older MOC void addPwd_slot(); void addPwd_slot1(QString *pw, PwMDoc *_doc); /** manage/edit triggered */ //US ENH : changed code to run with older MOC void editPwd_slot(); void editPwd_slot1(const QString *category); void editPwd_slot3(const QString *category, const int *index ,PwMDoc *_doc ); /** manage/delete triggered */ void deletePwd_slot(); /** execute the "Launcher" entry */ void execLauncher_slot(); /** open browser with URL entry */ void goToURL_slot(); /** manage/changeMasterPwd triggered */ void changeMasterPwd_slot(); /** lock current document */ void lockWnd_slot(); /** deeplock current document */ void deepLockWnd_slot(); /** window/unlock triggered */ void unlockWnd_slot(); /** find item */ void find_slot(); /** configure clicked */ void config_slot(); /** (de)activate the "change master pw" button in the menu-bar */ void activateMpButton(bool activate = true); /** generate a new chipcard */ void genNewCard_slot(); /** completely erase the current card */ void eraseCard_slot(); /** returns the ID number of the current card */ void readCardId_slot(); /** make backup image of the current card */ void makeCardBackup_slot(); /** write backup image to current card */ void replayCardBackup_slot(); #ifdef PWM_EMBEDDED + void category_slot(); void whatsnew_slot(); void showLicense_slot(); void faq_slot(); void createAboutData_slot(); void syncHowTo_slot(); #endif protected: /** is this window virgin? */ bool isVirgin() { return virgin; } /** add/remove virginity */ void setVirgin(bool v); /** initialize the menubar */ void initMenubar(); /** initialize the toolbar */ void initToolbar(); /** initialize the window-metrics */ void initMetrics(); /** close-event */ void closeEvent(QCloseEvent *e); /** creates a new PwM-ListView and returns it */ PwMView * makeNewListView(PwMDoc *doc); /** Window hide-event */ void hideEvent(QHideEvent *); /** is this window minimized? */ bool isMinimized() { #ifndef PWM_EMBEDDED #if KDE_VERSION >= KDE_MAKE_VERSION(3, 2, 0) return KWin::windowInfo(winId()).isMinimized(); #else // KDE_VERSION return KWin::info(winId()).isIconified(); #endif // KDE_VERSION #else return false; #endif } /** window got the focus */ void focusInEvent(QFocusEvent *e); /** update the caption string */ void updateCaption(); #ifdef CONFIG_KWALLETIF /** check if kwalletemu is enabled and ask the user what to do */ bool checkAndAskForKWalletEmu(); #endif // CONFIG_KWALLETIF protected slots: /** doc got closed */ void docClosed(PwMDoc *doc); signals: /** window got closed (by user or someone else) */ void closed(PwM *wnd); /** window got the focus (was brought to foreground) */ void gotFocus(PwM *wnd); /** window lost the focus */ void lostFocus(PwM *wnd); protected: /** pointer to the view active in this KMainWindow */ PwMView *view; /** pointer to the init class */ PwMInit *init; /** has this window already lost its virginity? * Means is there an open working document */ bool virgin; /** "file" popup-menu */ KPopupMenu *filePopup; /** "manage" popup-menu */ KPopupMenu *managePopup; #ifdef CONFIG_KEYCARD /** "chipcard" popup-menu */ KPopupMenu *chipcardPopup; #endif // CONFIG_KEYCARD /** "view" popup-menu */ KPopupMenu *viewPopup; /** "options" popup-menu */ KPopupMenu *optionsPopup; /** "help" popup-menu */ KPopupMenu *helpPopup; /** "export" popup-menu */ KPopupMenu *exportPopup; /** "import" popup-menu */ KPopupMenu *importPopup; /** force quit this window? */ bool forceQuit; /** force minimize this window to the tray */ bool forceMinimizeToTray; private: diff --git a/pwmanager/pwmanager/pwmanager.pro b/pwmanager/pwmanager/pwmanager.pro index fbc0554..7efe45c 100644 --- a/pwmanager/pwmanager/pwmanager.pro +++ b/pwmanager/pwmanager/pwmanager.pro @@ -1,175 +1,177 @@ TEMPLATE = app CONFIG += qt warn_off DESTDIR= ../../bin TARGET = pwmpi include( ../../variables.pri ) INCLUDEPATH += . ../../ ../../libkdepim ../../microkde ../../microkde/kdecore ../../microkde/kdeui ../../microkde/kutils ../libcrypt/crypt ../libcrypt/error ../libcrypt/zlib DEFINES += PWM_EMBEDDED CONFIG_PWMANAGER_GCRY DESKTOP_VERSION #enable this setting if you want debugoutput for pwmanager #DEFINES += CONFIG_DEBUG LIBS += -L../libcrypt/ LIBS += -L../../bin/ LIBS += -lmicrokde LIBS += -lmicrokdepim LIBS += -lzlib LIBS += -lkpmicrocipher LIBS += -lkpmicroerror LIBS += -lkpmicrompi LIBS += -lstdc++ unix:{ OBJECTS_DIR = obj/unix MOC_DIR = moc/unix } win32:{ DEFINES += _WIN32_ OBJECTS_DIR = obj/win MOC_DIR = moc/win QMAKE_LINK += /NODEFAULTLIB:LIBC QMAKE_CXXFLAGS += /TP /GX /GR /Ehsc } #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 #subtbledit.h \ #subtbleditimpl.h \ #compressbzip2.h \ HEADERS = \ addentrywnd_emb.h \ addentrywndimpl.h \ base64.h \ binentrygen.h \ blowfish.h \ commentbox.h \ compiler.h \ compressgzip.h \ csv.h \ +editcategory.h \ findwnd_emb.h \ findwndimpl.h \ genpasswd.h \ getkeycardwnd.h \ getmasterpwwnd_emb.h \ getmasterpwwndimpl.h \ globalstuff.h \ gpasmanfile.h \ htmlgen.h \ htmlparse.h \ ipc.h \ libgcryptif.h \ listobjselectwnd.h \ listviewpwm.h \ printtext.h \ pwgenwnd_emb.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_emb.h \ setmasterpwwndimpl.h \ sha1.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 #subtbledit.cpp \ #subtbleditimpl.cpp \ #compressbzip2.cpp SOURCES = \ addentrywnd_emb.cpp \ addentrywndimpl.cpp \ base64.cpp \ binentrygen.cpp \ blowfish.cpp \ commentbox.cpp \ compressgzip.cpp \ csv.cpp \ +editcategory.cpp \ findwnd_emb.cpp \ findwndimpl.cpp \ genpasswd.cpp \ getkeycardwnd.cpp \ getmasterpwwnd_emb.cpp \ getmasterpwwndimpl.cpp \ globalstuff.cpp \ gpasmanfile.cpp \ htmlgen.cpp \ ipc.cpp \ libgcryptif.cpp \ listobjselectwnd.cpp \ listviewpwm.cpp \ main.cpp \ pwgenwnd_emb.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_emb.cpp \ setmasterpwwndimpl.cpp \ sha1.cpp \ waitwnd.cpp \ kcmconfigs/kcmpwmconfig.cpp \ kcmconfigs/pwmconfigwidget.cpp diff --git a/pwmanager/pwmanager/pwmanagerE.pro b/pwmanager/pwmanager/pwmanagerE.pro index e195178..6b68514 100644 --- a/pwmanager/pwmanager/pwmanagerE.pro +++ b/pwmanager/pwmanager/pwmanagerE.pro @@ -1,173 +1,175 @@ TEMPLATE = app CONFIG += qt warn_on TARGET = pwmpi OBJECTS_DIR = obj/$(PLATFORM) MOC_DIR = moc/$(PLATFORM) DESTDIR=$(QPEDIR)/bin INCLUDEPATH += . ../../ ../../qtcompat ../../qtcompat/xml ../../libkdepim ../../microkde ../../microkde/kdecore ../../microkde/kdeui ../../microkde/kutils ../libcrypt/crypt ../libcrypt/error $(QPEDIR)/include DEFINES += PWM_EMBEDDED CONFIG_PWMANAGER_GCRY #enable this setting if you want debugoutput for pwmanager #DEFINES += CONFIG_DEBUG LIBS += -L../libcrypt/$(PLATFORM) LIBS += -lmicrokde LIBS += -lmicroqtcompat LIBS += -lmicrokdepim LIBS += -L$(QPEDIR)/lib LIBS += -lqpe LIBS += -lzlib #LIBS += -lbz2 #LIBS += -lkpmicrogcrypt LIBS += -ljpeg LIBS += $(QTOPIALIB) LIBS += -lkpmicrocipher LIBS += -lkpmicroerror LIBS += -lkpmicrompi LIBS += -lstdc++ LIBS += $(GCC3EXTRALIB1) LIBS += $(GCC3EXTRALIB2) #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 #subtbledit.h \ #subtbleditimpl.h \ #compressbzip2.h \ HEADERS = \ addentrywnd_emb.h \ addentrywndimpl.h \ base64.h \ binentrygen.h \ blowfish.h \ commentbox.h \ compiler.h \ compressgzip.h \ csv.h \ +editcategory.h \ findwnd_emb.h \ findwndimpl.h \ genpasswd.h \ getkeycardwnd.h \ getmasterpwwnd_emb.h \ getmasterpwwndimpl.h \ globalstuff.h \ gpasmanfile.h \ htmlgen.h \ htmlparse.h \ ipc.h \ libgcryptif.h \ listobjselectwnd.h \ listviewpwm.h \ printtext.h \ pwgenwnd_emb.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_emb.h \ setmasterpwwndimpl.h \ sha1.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 #subtbledit.cpp \ #subtbleditimpl.cpp \ #compressbzip2.cpp SOURCES = \ addentrywnd_emb.cpp \ addentrywndimpl.cpp \ base64.cpp \ binentrygen.cpp \ blowfish.cpp \ commentbox.cpp \ compressgzip.cpp \ csv.cpp \ +editcategory.cpp \ findwnd_emb.cpp \ findwndimpl.cpp \ genpasswd.cpp \ getkeycardwnd.cpp \ getmasterpwwnd_emb.cpp \ getmasterpwwndimpl.cpp \ globalstuff.cpp \ gpasmanfile.cpp \ htmlgen.cpp \ ipc.cpp \ libgcryptif.cpp \ listobjselectwnd.cpp \ listviewpwm.cpp \ main.cpp \ pwgenwnd_emb.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_emb.cpp \ setmasterpwwndimpl.cpp \ sha1.cpp \ waitwnd.cpp \ kcmconfigs/kcmpwmconfig.cpp \ kcmconfigs/pwmconfigwidget.cpp diff --git a/pwmanager/pwmanager/pwmdoc.cpp b/pwmanager/pwmanager/pwmdoc.cpp index 9043acc..ddbf4f2 100644 --- a/pwmanager/pwmanager/pwmdoc.cpp +++ b/pwmanager/pwmanager/pwmdoc.cpp @@ -959,192 +959,195 @@ bool PwMDoc::copyFile(const QString &src, const QString &dst) 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]; Q_LONG bytesRead, bytesWritten; while (!srcFd.atEnd()) { bytesRead = srcFd.readBlock(tmpBuf, static_cast<Q_ULONG>(tmpBuf_size)); if (bytesRead == -1) { srcFd.close(); dstFd.close(); return false; } bytesWritten = dstFd.writeBlock(tmpBuf, static_cast<Q_ULONG>(bytesRead)); 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; } dti.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; + //US ENH: clear item to initialize with default values, or create a constructor + item.clear(); + item.name = category.latin1(); dti.dta.push_back(item); if (categoryIndex) *categoryIndex = dti.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 > dti.dta[category].d.size() - 1) return false; getDataChangedLock(); if (!lockAt(category, index, false)) { putDataChangedLock(); return false; } putDataChangedLock(); int lvPos = dti.dta[category].d[index].listViewPos; // delete entry dti.dta[category].d.erase(dti.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 (dti.dta[category].d[i].listViewPos > lvPos) --dti.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 (dti.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 = dti.dta[oldCategory].d[index].rev + 1; // increment revision counter. dti.dta[oldCategory].d[index] = *d; } flagDirty(); return true; } @@ -1787,192 +1790,194 @@ bool PwMDoc::unlockAll_tempoary(bool revert) } } } timer()->stop(DocTimer::id_autoLockTimer); oldLockStates = new vector< vector<bool> >; vector<bool> tmp_vec; vector<PwMCategoryItem>::iterator catBegin = dti.dta.begin(), catEnd = dti.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; /* NOTE: saveDoc() depends on this function to return * e_success if saveToFile == false */ 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() { dti.clear(); PwMCategoryItem d; + //US ENH: to initialize all members with meaningfull data. + d.clear(); d.name = DEFAULT_CATEGORY.latin1(); dti.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) { dti.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 dti.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, dti.dta[category].d[i].desc, caseSensitive, exactWordMatch)) { continue; } } if (searchIn & SEARCH_IN_NAME) { if (!compareString(find.name, dti.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, dti.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, dti.dta[category].d[i].comment, diff --git a/pwmanager/pwmanager/pwmdoc.h b/pwmanager/pwmanager/pwmdoc.h index 09923ab..ef81dfc 100644 --- a/pwmanager/pwmanager/pwmdoc.h +++ b/pwmanager/pwmanager/pwmdoc.h @@ -160,196 +160,205 @@ struct 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(); } //US ENH: we need this operator to compare two items if we have no unique ids //available. Generaly this happens before the first sync bool PwMDataItem::operator==( const PwMDataItem &a ) const { //qDebug("oper==%s", a.desc.c_str()); if ( desc != a.desc ) return false; if ( name != a.name ) return false; if ( pw != a.pw ) return false; if ( comment != a.comment ) return false; if ( url != a.url ) return false; if ( launcher != a.launcher ) return false; //all other field will not be checked. return true; } //US ENH: this sync method actually copies all values from the parameter like the =operator //does with two exceptions: listViewPos will not be changed, and the launcher only if required. bool PwMDataItem::syncItem(const PwMDataItem &a, bool syncLauncher=true ) { desc = a.desc; name = a.name; pw = a.pw; comment = a.comment; url = a.url; if (syncLauncher == true) launcher = a.launcher; meta = a.meta; binary = a.binary; lockStat = a.lockStat; rev = a.rev; return true; } }; struct PwMCategoryItem { /** all PwMDataItems (all passwords) within this category */ vector<PwMDataItem> d; /** category name/description */ string name; + //US ENH: enhancements of the filestructure + /* each category stores the text for description,name and password */ + string desc_text; + string name_text; + string pw_text; + void clear() { d.clear(); name = ""; + desc_text = "Description"; + name_text = "Username"; + pw_text = "Password"; } }; struct PwMSyncItem { string syncName; QDateTime lastSyncDate; void clear() { lastSyncDate = QDateTime(); syncName = ""; } }; struct PwMItem { vector<PwMCategoryItem> dta; vector<PwMSyncItem> syncDta; void clear() { dta.clear(); syncDta.clear(); } }; /** "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, @@ -692,118 +701,123 @@ protected: /** 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); public: #ifdef PWM_EMBEDDED //US ENH: this is the magic function that syncronizes the local doc with the remote doc. PwMerror syncronize(KSyncManager* manager, PwMDoc* syncLocal, PwMDoc* syncRemote, int mode ); //takePwMDataItem returns the following values // 0 equal // 1 take local // 2 take remote // 3 cancel int takePwMDataItem( PwMDataItem* local, PwMDataItem* remote, QDateTime lastSync, int mode , bool full ); //the following methods are the overwritten callbackmethods from the syncinterface virtual bool sync(KSyncManager* manager, QString filename, int mode); virtual void removeSyncInfo( QString syncProfile); #endif + //US ENH: helpermethods to return a whole category entry + /** returns a pointer to the categoryitem */ + PwMCategoryItem* getCategoryEntry(unsigned int index) + { return &(dti.dta[index]); } + private: //US ENH: helpermethods to access the sync data for a certain syncname. // It returns the syncdatas index bool findSyncData(const QString &syncname, unsigned int *index); /** add new syncdataentry */ PwMerror addSyncDataEntry(PwMSyncItem *d, bool dontFlagDirty = false); /** returns a pointer to the syncdata */ PwMSyncItem* getSyncDataEntry(unsigned int index) { return &(dti.syncDta[index]); } /** delete entry */ bool delSyncDataEntry(unsigned int index, bool dontFlagDirty = false); PwMDataItem* findEntryByID(const QString &uid, unsigned int *category, unsigned int *index); QStringList getIDEntryList(); }; #endif diff --git a/pwmanager/pwmanager/pwmview.cpp b/pwmanager/pwmanager/pwmview.cpp index 5aaf66e..7733028 100644 --- a/pwmanager/pwmanager/pwmview.cpp +++ b/pwmanager/pwmanager/pwmview.cpp @@ -167,192 +167,202 @@ 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); //qDebug("PwMView::shiftToView: %s, %i", currItem.desc.c_str(), currItem.listViewPos); tmpSorted[currItem.listViewPos] = currItem; } // shift tempoary data to ListView. tmpDisableSort(); lv->clear(); + + //US ENH: adjust the headers of the table according the category texts + { + PwMCategoryItem* catItem = doc->getCategoryEntry(catDocIndex); + // qDebug("PwMView::ShiftToView CAT: %i, %s", catDocIndex, catItem->name.c_str()); + lv->setColumnText(COLUMN_DESC, catItem->desc_text.c_str()); + lv->setColumnText(COLUMN_NAME, catItem->name_text.c_str()); + lv->setColumnText(COLUMN_PW, catItem->pw_text.c_str()); + } + 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 == "") diff --git a/pwmanager/pwmanager/serializer.cpp b/pwmanager/pwmanager/serializer.cpp index 5753c1d..507fa30 100644 --- a/pwmanager/pwmanager/serializer.cpp +++ b/pwmanager/pwmanager/serializer.cpp @@ -1,388 +1,420 @@ /*************************************************************************** * * * 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.1 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 +//US ENH : uniqueid and sync information #define META_UNIQUEID "n" #define SYNC_ROOT "s" #define SYNC_TARGET_PREFIX "t" #define SYNC_TARGET_NAME "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" +//US ENH : optional text for categories +#define CAT_TEXT_OLD "text" + #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" +//US ENH : optional text for categories +#define CAT_TEXT_NEW "t" + #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 + +//US ENH : optional text for categories +# define CAT_TEXT_WR CAT_TEXT_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 + +//US ENH : optional text for categories +# define CAT_TEXT_WR CAT_TEXT_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; //US BUG: I needed to specify a document name. Otherwise impl will not be created for serializing #ifndef PWM_EMBEDDED domDoc = new QDomDocument; #else domDoc = new QDomDocument("mydoc"); #endif } Serializer::Serializer(const QCString &buffer) { defaultLockStat = true; //US BUG: I needed to specify a document name. Otherwise impl will not be created for serializing #ifndef PWM_EMBEDDED domDoc = new QDomDocument; #else domDoc = new QDomDocument("mydoc"); #endif 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) { //abort(); //qDebug("parse %s ", buffer.data()); PWM_ASSERT(domDoc); #ifndef PWM_EMBEDDED if (!domDoc->setContent(buffer, true)) return false; #else #ifdef DESKTOP_VERSION if (!domDoc->setContent(buffer, true)) #else if (!domDoc->setContent(buffer)) #endif 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"); qDebug(tmp); cout << tmp << endl; printDebug("<END Serializer::getXml() dump>"); #endif // DEBUG QCString ret(domDoc->toCString()); ret.replace(QRegExp("\n"), ""); return ret; #endif } bool Serializer::serialize(PwMItem &dta) { PWM_ASSERT(domDoc); QDomElement root(genNewRoot()); QDomElement catNode(domDoc->createElement(CAT_ROOT_WR)); QDomElement syncNode(domDoc->createElement(SYNC_ROOT)); if (!addSyncData(&syncNode, dta.syncDta)) return false; root.appendChild(syncNode); if (!addCategories(&catNode, dta.dta)) return false; root.appendChild(catNode); return true; } bool Serializer::deSerialize(PwMItem *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->dta))) { return false; } continue; } else if (n.nodeName() == SYNC_ROOT) { if (!readSyncData(n, &(dta->syncDta))) { return false; } continue; } /* NOTE: We can stop processing here, as we * don't have more nodes in root, yet. */ return false; } return true; } bool Serializer::readCategories(const QDomNode &n, vector<PwMCategoryItem> *dta) { QDomNodeList nl(n.childNodes()); QDomNode cur; QString name; + QString text; 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(); + + //US ENH: new version might include text for description, name and pw + text = cur.toElement().attribute(CAT_TEXT_NEW); + if (text == QString::null) + text = cur.toElement().attribute(CAT_TEXT_OLD); + if (text != QString::null) + { + QStringList textlist = QStringList::split(";", text, true); + unsigned int num = textlist.count(); + if (num > 0) + curCat.desc_text = textlist[0].latin1(); + if (num > 1) + curCat.name_text = textlist[1].latin1(); + if (num > 2) + curCat.pw_text = textlist[2].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; //US BUG: to initialize all values of curEntr with meaningfulldata, // we call clear on it. Reason: Information in the file we will read might be incomplete. // e.g. the metadata is missing. curEntr.clear(true); 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. //qDebug("entry %s ",unescapeEntryData(text).latin1()); 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; @@ -408,192 +440,202 @@ bool Serializer::extractMeta(const QDomNode &n, while (!cur.isNull()) { name = cur.nodeName(); val = cur.toElement().text(); if (val == "") { cur = cur.nextSibling(); continue; } //US BUG: The transformation of an empty date into an ISO date and back is different on different systems/compilers. //because of that it is possible that here some values are not set, which means they are null. //US ENH: at the same moment we need backwardcompatibility. So older versions might have stored invalid dates. QDateTime dtval; //dtval should be invalid by definition. if ((name == META_CREATE_DATE) || (name == META_VALID_DATE) || (name == META_EXPIRE_DATE) || (name == META_UPDATE_DATE)) { //qDebug("Serializer::extractMeta:: val:%s, empty:%i, length:%i",val.utf8(), val.isEmpty(), val.length()); #ifndef PWM_EMBEDDED dtval = QDateTime::fromString(val, Qt::ISODate); #else bool ok; dtval = KGlobal::locale()->readDateTime(val, KLocale::ISODate, &ok); if (ok == false) qDebug("Serializer::extractMeta invalid date or time !!!!!!!!!!!!!"); #endif //if the parsed data is wrong, dtval should be invalid at this time. } if (name == META_CREATE_DATE) { dta->create = dtval; } else if (name == META_VALID_DATE) { dta->valid = dtval; } else if (name == META_EXPIRE_DATE) { dta->expire = dtval; } else if (name == META_UPDATE_DATE) { dta->update = dtval; } 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()); } 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); + + //US ENH: new version includes text for description, name and pw + QStringList curTextList; + curTextList << dta[i].desc_text.c_str(); + curTextList << dta[i].name_text.c_str(); + curTextList << dta[i].pw_text.c_str(); + QString text = curTextList.join(";"); + curCat.setAttribute(CAT_TEXT_WR, text); + + 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 |