author | ulf69 <ulf69> | 2004-10-22 18:48:35 (UTC) |
---|---|---|
committer | ulf69 <ulf69> | 2004-10-22 18:48:35 (UTC) |
commit | a5274f27dc71e1a0ffae73f32f84f4dd013b4b76 (patch) (side-by-side diff) | |
tree | 5c2e3e105fa9df8999752a314455d0f424bf474b | |
parent | 163b74a23d102074fc0adefddba5b4fa9d4dd2a5 (diff) | |
download | kdepimpi-a5274f27dc71e1a0ffae73f32f84f4dd013b4b76.zip kdepimpi-a5274f27dc71e1a0ffae73f32f84f4dd013b4b76.tar.gz kdepimpi-a5274f27dc71e1a0ffae73f32f84f4dd013b4b76.tar.bz2 |
added csv import/export
-rw-r--r-- | pwmanager/pwmanager/csv.cpp | 428 | ||||
-rw-r--r-- | pwmanager/pwmanager/csv.h | 91 | ||||
-rw-r--r-- | pwmanager/pwmanager/pwm.cpp | 85 | ||||
-rw-r--r-- | pwmanager/pwmanager/pwm.h | 4 | ||||
-rw-r--r-- | pwmanager/pwmanager/pwmanagerE.pro | 2 |
5 files changed, 608 insertions, 2 deletions
diff --git a/pwmanager/pwmanager/csv.cpp b/pwmanager/pwmanager/csv.cpp new file mode 100644 index 0000000..194edf2 --- a/dev/null +++ b/pwmanager/pwmanager/csv.cpp @@ -0,0 +1,428 @@ +/*************************************************************************** + * * + * 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 + * The original file version was 1.2 + * $Id$ + **************************************************************************/ + +#include "csv.h" +#include "pwmdoc.h" +#include "pwmexception.h" + +#include <kmessagebox.h> +#include <klocale.h> + +#define MAX_CSV_FILE_SIZE (50 * 1024 * 1024) // bytes + + +Csv::Csv(QWidget *_parent) + : parent (_parent) +{ +} + +Csv::~Csv() +{ +} + +bool Csv::importData(const QString &filepath, + PwMDoc *doc) +{ + bool ret = true; + QByteArray d; + QFile f(filepath); + if (!f.open(IO_ReadOnly)) { + KMessageBox::error(parent, + i18n("Could not open file.\n" + "Does the file exist?"), + i18n("Open error.")); + ret = false; + goto out; + } + if (f.size() > MAX_CSV_FILE_SIZE) { + KMessageBox::error(parent, + i18n("File too big.\nMaximum file size is 1 Byte.", "File too big.\nMaximum file size is %n Bytes.", MAX_CSV_FILE_SIZE), + i18n("File too big.")); + ret = false; + goto out_close; + } + d = f.readAll(); + if (d.isEmpty()) { + KMessageBox::error(parent, + i18n("Could not read file or file empty."), + i18n("Reading failed.")); + ret = false; + goto out_close; + } + if (!doImport(d, doc)) { + KMessageBox::error(parent, + i18n("Import failed.\n" + "Corrupt CSV data format."), + i18n("File corrupt.")); + ret = false; + goto out_close; + } + +out_close: + f.close(); +out: + return ret; +} + +bool Csv::doImport(const QByteArray &d, + PwMDoc *doc) +{ + PwMDataItem di; + //US ENH: initialize all members: + di.clear(); + + int refIndex = 0; + int ret; + QCString s, curCat; + int fieldIndex = 0; + bool inRecord = false; + /* fieldIndex is a reference count to see which + * value we are attaching to di. + * Valid counts are: + * 0 -> category + * 1 -> desc + * 2 -> name + * 3 -> pw + * 4 -> url + * 5 -> launcher + * 6 -> comment + */ + + while (1) { + ret = nextField(&s, d, inRecord, &refIndex); + switch (ret) { + case 0: + // successfully got next field. + inRecord = true; + switch (fieldIndex) { + case 0: // category + if (s.isEmpty()) { + /* This is special case. It's the category + * list terminating empty field. + */ + ++fieldIndex; + } else + curCat = s; + break; + case 1: // desc + di.desc = s; + ++fieldIndex; + break; + case 2: // name + di.name = s; + ++fieldIndex; + break; + case 3: // pw + di.pw = s; + ++fieldIndex; + break; + case 4: // url + di.url = s; + ++fieldIndex; + break; + case 5: // launcher + di.launcher = s; + ++fieldIndex; + break; + case 6: // comment + di.comment = s; + ++fieldIndex; + break; + default: + /* Too many fields in a record. + * We simply throw it away. + */ + break; + } + break; + case 1: + // record complete. + if (fieldIndex == 6) + di.comment = s; + inRecord = false; + fieldIndex = 0; + doc->addEntry(curCat, &di, true); + //US ENH: clear di for the next row + di.clear(); + break; + case 2: + // data completely parsed. + doc->flagDirty(); + return true; + case -1: + // parse error + doc->flagDirty(); + return false; + } + } + BUG(); + return false; +} + +int Csv::nextField(QCString *ret, + const QByteArray &in, + bool inRecord, + int *_refIndex) +{ + int rv = -2; + char c; + bool inField = false; + bool isQuoted = false; + bool searchingTerminator = false; + int refIndex; + int inSize = static_cast<int>(in.size()); + ret->truncate(0); + + for (refIndex = *_refIndex; refIndex < inSize; ++refIndex) { + c = in.at(refIndex); + if (!inField) { + // we have to search the field beginning, now. + switch (c) { + case ' ': // space + case ' ': // tab + // hm, still not the beginning. Go on.. + break; + case '\r': + case '\n': + if (inRecord) { + /* This is the end of the last field in + * the record. + */ + PWM_ASSERT(ret->isEmpty()); + rv = 1; // record end + goto out; + } else { + // hm, still not the beginning. Go on.. + break; + } + case ',': + // Oh, an empty field. How sad. + PWM_ASSERT(ret->isEmpty()); + rv = 0; // field end + goto out; + case '\"': + // this is the quoted beginning. + inField = true; + isQuoted = true; + if (refIndex + 1 >= inSize) + goto unexp_eof; + break; + default: + // this is the unquoted beginning. + inField = true; + isQuoted = false; + *ret += c; + break; + } + } else { + // we are in the field now. Search the end. + if (isQuoted) { + if (searchingTerminator) { + switch (c) { + case '\r': + case '\n': + rv = 1; // record end + goto out; + case ',': + // found it. + rv = 0; // field end + goto out; + default: + // go on. + continue; + } + } + switch (c) { + case '\"': + /* check if this is the end of the + * entry, or just an inline escaped quote. + */ + char next; + if (refIndex + 1 >= inSize) { + // This is the last char, so it's the end. + rv = 2; // data end + goto out; + } + next = in.at(refIndex + 1); + switch (next) { + case '\"': + // This is an escaped double quote. + // So skip next iteration. + refIndex += 1; + *ret += c; + break; + default: + /* end of field. + * We have to search the comma (or newline...), + * which officially terminates the entry. + */ + searchingTerminator = true; + break; + } + break; + default: + // nothing special about the char. Go on! + *ret += c; + break; + } + } else { + switch (c) { + case '\"': + // This is not allowed here. + return -1; // parser error + case '\r': + case '\n': + rv = 1; // record end + goto out; + case ',': + rv = 0; // field end + goto out; + default: + // nothing special about the char. Go on! + *ret += c; + break; + } + } + } + } + // we are at the end of the stream, now! + if (searchingTerminator) { + /* Ok, there's no terminating comma (or newline...), + * because we are at the end. That's perfectly fine. + */ + PWM_ASSERT(inField); + rv = 2; // data end + goto out; + } + if (!isQuoted && inField) { + // That's the end of the last unquoted field. + rv = 2; // data end + goto out; + } + if (!inField) { + // This is expected EOF + rv = 2; // data end + goto out; + } + +unexp_eof: + printDebug("unexpected EOF :("); + return -1; // parser error + +out: + if (!isQuoted) + *ret = ret->stripWhiteSpace(); + *_refIndex = refIndex + 1; + return rv; +} + +bool Csv::exportData(const QString &filepath, + PwMDoc *doc) +{ + PWM_ASSERT(!doc->isDocEmpty()); + bool ret = true; + if (QFile::exists(filepath)) { + int ret; + ret = KMessageBox::questionYesNo(parent, + i18n("This file does already exist.\n" + "Do you want to overwrite it?"), + i18n("Overwrite file?")); + if (ret == KMessageBox::No) + return false; + if (!QFile::remove(filepath)) { + KMessageBox::error(parent, + i18n("Could not delete the old file."), + i18n("Delete error.")); + return false; + } + } + QFile f(filepath); + if (!f.open(IO_ReadWrite)) { + KMessageBox::error(parent, + i18n("Could not open file for writing."), + i18n("Open error.")); + ret = false; + goto out; + } + doc->unlockAll_tempoary(); + if (!doExport(f, doc)) + ret = false; + doc->unlockAll_tempoary(true); + f.close(); +out: + return ret; +} + +bool Csv::doExport(QFile &f, + PwMDoc *doc) +{ + unsigned int numCat = doc->numCategories(); + unsigned int numEntr; + unsigned int i, j; + PwMDataItem d; + QCString s, catName; + QByteArray b; + + for (i = 0; i < numCat; ++i) { + numEntr = doc->numEntries(i); + catName = newField(doc->getCategory(i)->c_str()); + for (j = 0; j < numEntr; ++j) { + doc->getEntry(i, j, &d); + s = catName; + s += ",,"; + s += newField(d.desc.c_str()); + s += ","; + s += newField(d.name.c_str()); + s += ","; + s += newField(d.pw.c_str()); + s += ","; + s += newField(d.url.c_str()); + s += ","; + s += newField(d.launcher.c_str()); + s += ","; + s += newField(d.comment.c_str()); + s += "\r\n"; + b = s; + // remove \0 termination +#ifndef PWM_EMBEDDED + b.resize(b.size() - 1, QGArray::SpeedOptim); +#else + b.resize(b.size() - 1); +#endif + if (!f.writeBlock(b)) + return false; + } + } + return true; +} + +QCString Csv::newField(QCString s) +{ + if (s.isEmpty()) + return QCString(); + QCString ret("\""); +#ifndef PWM_EMBEDDED + s.replace('\"', "\"\""); +#else + s.replace(QRegExp("\""), "\"\""); +#endif + ret += s; + ret += "\""; + return ret; +} diff --git a/pwmanager/pwmanager/csv.h b/pwmanager/pwmanager/csv.h new file mode 100644 index 0000000..6f3c1e1 --- a/dev/null +++ b/pwmanager/pwmanager/csv.h @@ -0,0 +1,91 @@ +/*************************************************************************** + * * + * 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 + * The original file version was 1.2 + * $Id$ + **************************************************************************/ + + +#ifndef __PWMANAGER_CSV_H +#define __PWMANAGER_CSV_H + +#include <qcstring.h> +#include <qfile.h> + + +class PwMDoc; +class QString; +class QWidget; + +/** class for CSV (Comma Separated Value) export and import. + * + * http://www.creativyst.com/Doc/Articles/CSV/CSV01.htm + * http://en.wikipedia.org/wiki/Comma-separated_values + * + * There are two types of CSV output we can produce. + * One with Category support (recommended): + * "Category 1",, "Desc 1", "Username 1", "Password 1", "URL 1", "Launcher 1", "Comment 1" + * "Category 1",, "Desc 2", "Username 2", "Password 2", "URL 2", "Launcher 2", "Comment 2" + * ... + * The empty "" is neccessary, because in future versions we will + * support nested Categories. We want to be future compatible, now. + * + * And one without Category support: + *FIXME: it's not implemented, yet. ;) + * "Desc 1", "Username 1", "Password 1", "URL 1", "Launcher 1", "Comment 1" + * "Desc 2", "Username 2", "Password 2", "URL 2", "Launcher 2", "Comment 2" + * ... + * + */ +class Csv +{ +public: + Csv(QWidget *_parent); + ~Csv(); + + /** import data from "filepath" into "doc" */ + bool importData(const QString &filepath, + PwMDoc *doc); + /** export data from "doc" to "filepath" */ + bool exportData(const QString &filepath, + PwMDoc *doc); + +protected: + /** do the import process. */ + bool doImport(const QByteArray &d, + PwMDoc *doc); + /** parse for the next field. + * @return Return values are: + * 0 -> successfully got the next field. + * 1 -> record end. + * 2 -> data end. + * -1 -> parser error. + */ + int nextField(QCString *ret, + const QByteArray &in, + bool inRecord, + int *_refIndex); + /** do the export process. */ + bool doExport(QFile &f, + PwMDoc *doc); + /** generate a new data field string. */ + QCString newField(QCString s); + +protected: + /** current parent widget. */ + QWidget *parent; +}; + +#endif // __PWMANAGER_CSV_H diff --git a/pwmanager/pwmanager/pwm.cpp b/pwmanager/pwmanager/pwm.cpp index 66d26d6..ac0c978 100644 --- a/pwmanager/pwmanager/pwm.cpp +++ b/pwmanager/pwmanager/pwm.cpp @@ -1,319 +1,328 @@ /*************************************************************************** * * * 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 "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 }; // Button IDs for "export" popup menu (in "file" popup menu) enum { BUTTON_POPUP_EXPORT_TEXT = 0, - BUTTON_POPUP_EXPORT_GPASMAN + 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_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) { 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()"); disconnect(curDoc(), SIGNAL(docClosed(PwMDoc *)), this, SLOT(docClosed(PwMDoc *))); conf()->confWndMainWndSize(size()); emit closed(this); + //qDebug("PwM::~PwM() emited closed(this)"); delete view; } void PwM::initMenubar() { KIconLoader* picons; #ifndef PWM_EMBEDDED KIconLoader icons; picons = &icons; #else picons = KGlobal::iconLoader(); syncPopup = new KPopupMenu(this); syncManager = new KSyncManager((QWidget*)this, (KSyncInterface*)this, KSyncManager::PWMPI, PWMPrefs::instance(), syncPopup); syncManager->setBlockSave(false); connect ( syncPopup, SIGNAL( activated ( int ) ), syncManager, SLOT (slotSyncMenu( int ) ) ); syncManager->fillSyncMenu(); #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); + exportPopup->insertItem(i18n("&CSV (Comma Separated Value) ..."), this, + SLOT(exportToCsv()), 0, BUTTON_POPUP_EXPORT_CSV); #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); + 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)), @@ -955,128 +964,200 @@ bool PwM::importFromText() 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\n" "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?\n" "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::exportToCsv() +{ + PWM_ASSERT(curDoc()); + if (curDoc()->isDocEmpty()) { + KMessageBox::information(this, + i18n + ("Sorry, there is nothing to export;\n" + "please add some passwords first."), + i18n("Nothing to Do")); + return; + } + + curDoc()->timer()->getLock(DocTimer::id_autoLockTimer); + QString fn(KFileDialog::getSaveFileName("*.csv", i18n("*|CSV Text File"), this)); + if (fn.isEmpty()) { + curDoc()->timer()->putLock(DocTimer::id_autoLockTimer); + return; + } + + Csv csv(this); + if (!csv.exportData(fn, curDoc())) { + curDoc()->timer()->putLock(DocTimer::id_autoLockTimer); + showStatMsg(i18n("CSV file export failed.")); + return; + } + showStatMsg(i18n("Successfully exported data.")); + curDoc()->timer()->putLock(DocTimer::id_autoLockTimer); +} + +bool PwM::importCsv() +{ + Csv csv(this); + if (!isVirgin()) { + if (KMessageBox::questionYesNo(this, + i18n("Do you want to import the data\n" + "into the current document? (If you\n" + "select \"no\", a new document will be\n" + "opened.)"), + i18n("Import into This Document?")) + == KMessageBox::No) { + // import the data to a new window. + PwM *newInstance = init->createMainWnd(); + bool ok = newInstance->importCsv(); + if (!ok) { + newInstance->setForceQuit(true); + delete_and_null(newInstance); + } + return ok; + } + } + + QString filename = KFileDialog::getOpenFileName("*.csv", i18n("*|CSV Text File"), this); + if (filename.isEmpty()) + return false; + curDoc()->timer()->getLock(DocTimer::id_autoLockTimer); + if (!csv.importData(filename, curDoc())) { + curDoc()->timer()->putLock(DocTimer::id_autoLockTimer); + showStatMsg(i18n("CSV file import failed.")); + return false; + } + curDoc()->timer()->putLock(DocTimer::id_autoLockTimer); + KMessageBox::information(this, + i18n("Successfully imported the CSV data\n" + "into the current document."), i18n("Successfully Imported")); + showStatMsg(i18n("Successfully imported")); + setVirgin(false); + return true; +} + + 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\n" "into the current document? (If you\n" "select \"no\", a new document will be\n" "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\n" "you have typed in.\n" "There is no real way to determine the\n" "correctness of the password in the Gpasman\n" diff --git a/pwmanager/pwmanager/pwm.h b/pwmanager/pwmanager/pwm.h index 6ab9d6b..5822d59 100644 --- a/pwmanager/pwmanager/pwm.h +++ b/pwmanager/pwmanager/pwm.h @@ -63,134 +63,138 @@ public: /** construtor */ PwM(PwMInit *_init, PwMDoc *doc, bool virginity = true, QWidget* parent = 0, const char *name = 0); /** destructor */ ~PwM(); /** copy some text to the global clipboard */ static void copyToClipboard(const QString &s); /** returns pointer to the view */ PwMView * curView() { return view; } /** returns pointer to the currently using document. */ PwMDoc * curDoc() { return curView()->document(); } /** open a new doc with the given filename */ PwMDoc * openDoc(QString filename, bool openDeepLocked = false); /** show a message on the global status bar. * The message times out after some seconds. */ void showStatMsg(const QString &msg); /** ask the user where to save the doc (if it has not been saved, yet) * 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 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(); diff --git a/pwmanager/pwmanager/pwmanagerE.pro b/pwmanager/pwmanager/pwmanagerE.pro index 1445bcf..c46e937 100644 --- a/pwmanager/pwmanager/pwmanagerE.pro +++ b/pwmanager/pwmanager/pwmanagerE.pro @@ -1,169 +1,171 @@ 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++ #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 \ 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 \ 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 |