summaryrefslogtreecommitdiffabout
path: root/pwmanager
Side-by-side diff
Diffstat (limited to 'pwmanager') (more/less context) (ignore whitespace changes)
-rw-r--r--pwmanager/pwmanager/pwmdoc.cpp65
-rw-r--r--pwmanager/pwmanager/pwmdoc.h2
-rw-r--r--pwmanager/pwmanager/pwmdocui.cpp12
3 files changed, 67 insertions, 12 deletions
diff --git a/pwmanager/pwmanager/pwmdoc.cpp b/pwmanager/pwmanager/pwmdoc.cpp
index e9906a4..f4a1636 100644
--- a/pwmanager/pwmanager/pwmdoc.cpp
+++ b/pwmanager/pwmanager/pwmdoc.cpp
@@ -1,736 +1,778 @@
/***************************************************************************
* *
* copyright (C) 2003, 2004 by Michael Buesch *
* email: mbuesch@freenet.de *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 *
* as published by the Free Software Foundation. *
* *
***************************************************************************/
/***************************************************************************
* copyright (C) 2004 by Ulf Schenk
- * This file is originaly based on version 2.0 of pwmanager
+ * This file is originaly based on version 1.1 of pwmanager
* and was modified to run on embedded devices that run microkde
*
* $Id$
**************************************************************************/
#include "pwmdoc.h"
#include "pwmview.h"
#include "blowfish.h"
#include "sha1.h"
#include "globalstuff.h"
#include "gpasmanfile.h"
#include "serializer.h"
#include "compressgzip.h"
//US#include "compressbzip2.h"
#include "randomizer.h"
#include "pwminit.h"
#include "libgcryptif.h"
#ifdef PWM_EMBEDDED
#include "pwmprefs.h"
#include "kglobal.h"
#endif
#include <kmessagebox.h>
#include <libkcal/syncdefines.h>
#ifdef CONFIG_KWALLETIF
# include "kwalletemu.h"
#endif // CONFIG_KWALLETIF
#include <qdatetime.h>
#include <qsize.h>
#include <qfileinfo.h>
#include <qfile.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
//US#include <iostream>
#include <algorithm>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdint.h>
#ifdef PWM_EMBEDDED
#ifndef Q_LONG
#define Q_LONG long
#endif
#ifndef Q_ULONG
#define Q_ULONG unsigned long
#endif
#endif //PWM_EMBEDDED
//TODO: reset to its normal value.
#define META_CHECK_TIMER_INTERVAL 10/*300*/ /* sek */
using namespace std;
void PwMDocList::add(PwMDoc *doc, const string &id)
{
#ifdef PWM_DEBUG
// check for existance of object in debug mode only.
vector<listItem>::iterator begin = docList.begin(),
end = docList.end(),
i = begin;
while (i != end) {
if (i->doc == doc) {
BUG();
return;
}
++i;
}
#endif
listItem newItem;
newItem.doc = doc;
newItem.docId = id;
docList.push_back(newItem);
}
void PwMDocList::edit(PwMDoc *doc, const string &newId)
{
vector<listItem>::iterator begin = docList.begin(),
end = docList.end(),
i = begin;
while (i != end) {
if (i->doc == doc) {
i->docId = newId;
return;
}
++i;
}
}
void PwMDocList::del(PwMDoc *doc)
{
vector<listItem>::iterator begin = docList.begin(),
end = docList.end(),
i = begin;
while (i != end) {
if (i->doc == doc) {
docList.erase(i);
return;
}
++i;
}
}
bool PwMDocList::find(const string &id, listItem *ret)
{
vector<listItem>::iterator begin = docList.begin(),
end = docList.end(),
i = begin;
while (i != end) {
if (i->docId == id) {
if (ret)
*ret = *i;
return true;
}
++i;
}
return false;
}
DocTimer::DocTimer(PwMDoc *_doc)
: doc (_doc)
, mpwLock (0)
, autoLockLock (0)
, metaCheckLock (0)
{
mpwTimer = new QTimer;
autoLockTimer = new QTimer;
metaCheckTimer = new QTimer;
connect(mpwTimer, SIGNAL(timeout()),
this, SLOT(mpwTimeout()));
connect(autoLockTimer, SIGNAL(timeout()),
this, SLOT(autoLockTimeout()));
connect(metaCheckTimer, SIGNAL(timeout()),
this, SLOT(metaCheckTimeout()));
}
DocTimer::~DocTimer()
{
delete mpwTimer;
delete autoLockTimer;
delete metaCheckTimer;
}
void DocTimer::start(TimerIDs timer)
{
switch (timer) {
case id_mpwTimer:
if (mpwTimer->isActive())
mpwTimer->stop();
doc->setDocStatFlag(DOC_STAT_UNLOCK_WITHOUT_PW);
mpwTimer->start(conf()->confGlobPwTimeout() * 1000, true);
break;
case id_autoLockTimer:
if (autoLockTimer->isActive())
autoLockTimer->stop();
if (conf()->confGlobLockTimeout() > 0)
autoLockTimer->start(conf()->confGlobLockTimeout() * 1000, true);
break;
case id_metaCheckTimer:
if (metaCheckTimer->isActive())
metaCheckTimer->stop();
metaCheckTimer->start(META_CHECK_TIMER_INTERVAL * 1000, true);
break;
}
}
void DocTimer::stop(TimerIDs timer)
{
switch (timer) {
case id_mpwTimer:
mpwTimer->stop();
break;
case id_autoLockTimer:
autoLockTimer->stop();
break;
case id_metaCheckTimer:
metaCheckTimer->stop();
break;
}
}
void DocTimer::getLock(TimerIDs timer)
{
switch (timer) {
case id_mpwTimer:
++mpwLock;
break;
case id_autoLockTimer:
++autoLockLock;
break;
case id_metaCheckTimer:
++metaCheckLock;
break;
}
}
void DocTimer::putLock(TimerIDs timer)
{
switch (timer) {
case id_mpwTimer:
if (mpwLock)
--mpwLock;
break;
case id_autoLockTimer:
if (autoLockLock)
--autoLockLock;
break;
case id_metaCheckTimer:
if (metaCheckLock)
--metaCheckLock;
break;
}
}
void DocTimer::mpwTimeout()
{
if (mpwLock) {
mpwTimer->start(1000, true);
return;
}
doc->unsetDocStatFlag(DOC_STAT_UNLOCK_WITHOUT_PW);
}
void DocTimer::autoLockTimeout()
{
if (autoLockLock) {
autoLockTimer->start(1000, true);
return;
}
if (conf()->confGlobAutoDeepLock() &&
doc->filename != QString::null &&
doc->filename != "") {
doc->deepLock(true);
} else {
doc->lockAll(true);
}
}
void DocTimer::metaCheckTimeout()
{
if (metaCheckLock) {
// check again in one second.
metaCheckTimer->start(1000, true);
return;
}
if (doc->isDeepLocked()) {
metaCheckTimer->start(META_CHECK_TIMER_INTERVAL * 1000, true);
return;
}
if (doc->isDocEmpty()) {
metaCheckTimer->start(META_CHECK_TIMER_INTERVAL * 1000, true);
return;
}
#ifdef CONFIG_KWALLETIF
KWalletEmu *kwlEmu = doc->init->kwalletEmu();
if (kwlEmu)
kwlEmu->suspendDocSignals();
#endif // CONFIG_KWALLETIF
/* We simply trigger all views to update their
* displayed values. This way they have a chance
* to get notified when some meta changes over time.
* (for example an entry expired).
* The _view_ is responsive for not updating its
* contents if nothing really changed!
*/
emit doc->dataChanged(doc);
#ifdef CONFIG_KWALLETIF
if (kwlEmu)
kwlEmu->resumeDocSignals();
#endif // CONFIG_KWALLETIF
metaCheckTimer->start(META_CHECK_TIMER_INTERVAL * 1000, true);
}
PwMDocList PwMDoc::openDocList;
unsigned int PwMDocList::unnamedDocCnt = 1;
PwMDoc::PwMDoc(QObject *parent, const char *name)
: PwMDocUi(parent, name)
, dataChangedLock (0)
{
deleted = false;
unnamedNum = 0;
getOpenDocList()->add(this, getTitle().latin1());
curDocStat = 0;
setMaxNumEntries();
_timer = new DocTimer(this);
timer()->start(DocTimer::id_mpwTimer);
timer()->start(DocTimer::id_autoLockTimer);
timer()->start(DocTimer::id_metaCheckTimer);
addCategory(DEFAULT_CATEGORY, 0, false);
listView = 0;
emit docCreated(this);
}
PwMDoc::~PwMDoc()
{
emit docClosed(this);
getOpenDocList()->del(this);
delete _timer;
}
PwMerror PwMDoc::saveDoc(char compress, const QString *file)
{
PwMerror ret, e;
+ string serialized;
+ QFile f;
+ QString tmpFileMoved(QString::null);
+ bool wasDeepLocked;
+ QString savedFilename(filename);
+
if (!file) {
if (filename == "")
return e_filename;
- } else {
+ if (isDeepLocked()) {
+ /* We don't need to save any data.
+ * It's already all on disk, because
+ * we are deeplocked.
+ */
+ unsetDocStatFlag(DOC_STAT_DISK_DIRTY);
+ ret = e_success;
+ goto out;
+ }
+ } else {
if (*file == "" && filename == "")
return e_filename;
if (*file != "")
filename = *file;
}
- bool wasDeepLocked = isDeepLocked();
+ wasDeepLocked = isDeepLocked();
if (wasDeepLocked) {
- if (deepLock(false) != e_success)
- return e_noPw;
+ /* We are deeplocked. That means all data is already
+ * on disk. BUT we need to do saving procedure,
+ * because *file != savedFilename.
+ * Additionally we need to tempoarly restore
+ * the old "filename", because deepLock() references it.
+ */
+ QString newFilename(filename);
+ filename = savedFilename;
+ getDataChangedLock();
+ e = deepLock(false);
+ putDataChangedLock();
+ filename = newFilename;
+ switch (e) {
+ case e_success:
+ break;
+ case e_wrongPw:
+ case e_noPw:
+ emitDataChanged(this);
+ return e;
+ default:
+ emitDataChanged(this);
+ return e_openFile;
+ }
}
if (!isPwAvailable()) {
/* password is not available. This means, the
* document wasn't saved, yet.
*/
bool useChipcard = getDocStatFlag(DOC_STAT_USE_CHIPCARD);
QString pw(requestNewMpw(&useChipcard));
if (pw != "") {
currentPw = pw;
} else {
return e_noPw;
}
if (useChipcard) {
setDocStatFlag(DOC_STAT_USE_CHIPCARD);
} else {
unsetDocStatFlag(DOC_STAT_USE_CHIPCARD);
}
}
int _cryptAlgo = conf()->confGlobCryptAlgo();
int _hashAlgo = conf()->confGlobHashAlgo();
// sanity check for the selected algorithms
if (_cryptAlgo < PWM_CRYPT_BLOWFISH ||
_cryptAlgo > PWM_CRYPT_TWOFISH128) {
printWarn("Invalid Crypto-Algorithm selected! "
"Config-file seems to be corrupt. "
"Falling back to Blowfish.");
_cryptAlgo = PWM_CRYPT_BLOWFISH;
}
if (_hashAlgo < PWM_HASH_SHA1 ||
_hashAlgo > PWM_HASH_TIGER) {
printWarn("Invalid Hash-Algorithm selected! "
"Config-file seems to be corrupt. "
"Falling back to SHA1.");
_hashAlgo = PWM_HASH_SHA1;
}
char cryptAlgo = static_cast<char>(_cryptAlgo);
char hashAlgo = static_cast<char>(_hashAlgo);
if (conf()->confGlobMakeFileBackup()) {
if (!backupFile(filename))
return e_fileBackup;
}
- QString tmpFileMoved(QString::null);
if (QFile::exists(filename)) {
/* Move the existing file to some tmp file.
* When saving file succeeds, delete tmp file. Otherwise
* move tmp file back. See below.
*/
Randomizer *rnd = Randomizer::obj();
char rnd_buf[5];
sprintf(rnd_buf, "%X%X%X%X", rnd->genRndChar() & 0xFF, rnd->genRndChar() & 0xFF,
rnd->genRndChar() & 0xFF, rnd->genRndChar() & 0xFF);
tmpFileMoved = filename + "." + rnd_buf + ".mv";
if (!copyFile(filename, tmpFileMoved))
return e_openFile;
if (!QFile::remove(filename)) {
printWarn(string("removing orig file ")
+ filename.latin1()
+ " failed!");
}
}
- QFile f(filename);
- string serialized;
+ f.setName(filename);
if (!f.open(IO_ReadWrite)) {
ret = e_openFile;
goto out_moveback;
}
e = writeFileHeader(hashAlgo, hashAlgo,
cryptAlgo, compress,
&currentPw, &f);
if (e == e_hashNotImpl) {
printDebug("PwMDoc::saveDoc(): writeFileHeader() failed: e_hashNotImpl");
f.close();
ret = e_hashNotImpl;
goto out_moveback;
} else if (e != e_success) {
printDebug("PwMDoc::saveDoc(): writeFileHeader() failed");
f.close();
ret = e_writeHeader;
goto out_moveback;
}
if (!serializeDta(&serialized)) {
printDebug("PwMDoc::saveDoc(): serializeDta() failed");
f.close();
ret = e_serializeDta;
goto out_moveback;
}
e = writeDataHash(hashAlgo, &serialized, &f);
if (e == e_hashNotImpl) {
printDebug("PwMDoc::saveDoc(): writeDataHash() failed: e_hashNotImpl");
f.close();
ret = e_hashNotImpl;
goto out_moveback;
} else if (e != e_success) {
printDebug("PwMDoc::saveDoc(): writeDataHash() failed");
f.close();
ret = e_writeHeader;
goto out_moveback;
}
if (!compressDta(&serialized, compress)) {
printDebug("PwMDoc::saveDoc(): compressDta() failed");
f.close();
ret = e_enc;
goto out_moveback;
}
e = encrypt(&serialized, &currentPw, &f, cryptAlgo);
if (e == e_weakPw) {
printDebug("PwMDoc::saveDoc(): encrypt() failed: e_weakPw");
f.close();
ret = e_weakPw;
goto out_moveback;
} else if (e == e_cryptNotImpl) {
printDebug("PwMDoc::saveDoc(): encrypt() failed: e_cryptNotImpl");
f.close();
ret = e_cryptNotImpl;
goto out_moveback;
} else if (e != e_success) {
printDebug("PwMDoc::saveDoc(): encrypt() failed");
f.close();
ret = e_enc;
goto out_moveback;
}
unsetDocStatFlag(DOC_STAT_DISK_DIRTY);
f.close();
if (chmod(filename.latin1(),
conf()->confGlobFilePermissions())) {
printWarn(string("chmod failed: ") + strerror(errno));
}
openDocList.edit(this, getTitle().latin1());
- if (wasDeepLocked)
- deepLock(true);
+ if (wasDeepLocked) {
+ /* Do _not_ save the data with the deepLock()
+ * call, because this will recurse
+ * into saveDoc()
+ */
+ deepLock(true, false);
+ /* We don't check return value here, because
+ * it won't fail. See NOTE in deepLock()
+ */
+ }
if (tmpFileMoved != QString::null) {
// now remove the moved file.
if (!QFile::remove(tmpFileMoved)) {
printWarn(string("removing file ")
+ tmpFileMoved.latin1()
+ " failed!");
}
}
ret = e_success;
printDebug(string("writing file { name: ")
+ filename.latin1() + " compress: "
+ tostr(static_cast<int>(compress)) + " cryptAlgo: "
+ tostr(static_cast<int>(cryptAlgo)) + " hashAlgo: "
+ tostr(static_cast<int>(hashAlgo))
+ " }");
goto out;
out_moveback:
if (tmpFileMoved != QString::null) {
if (copyFile(tmpFileMoved, filename)) {
if (!QFile::remove(tmpFileMoved)) {
printWarn(string("removing tmp file ")
+ filename.latin1()
+ " failed!");
}
} else {
printWarn(string("couldn't copy file ")
+ tmpFileMoved.latin1()
+ " back to "
+ filename.latin1());
}
}
out:
return ret;
}
PwMerror PwMDoc::openDoc(const QString *file, int openLocked)
{
PWM_ASSERT(file);
PWM_ASSERT(openLocked == 0 || openLocked == 1 || openLocked == 2);
string decrypted, dataHash;
PwMerror ret;
char cryptAlgo, dataHashType, compress;
unsigned int headerLen;
if (*file == "")
return e_readFile;
filename = *file;
/* check if this file is already open.
* This does not catch symlinks!
*/
if (!isDeepLocked()) {
if (getOpenDocList()->find(filename.latin1()))
return e_alreadyOpen;
}
QFile f(filename);
if (openLocked == 2) {
// open deep-locked
if (!QFile::exists(filename))
return e_openFile;
if (deepLock(true, false) != e_success)
return e_openFile;
goto out_success;
}
if (!f.open(IO_ReadOnly))
return e_openFile;
ret = checkHeader(&cryptAlgo, &currentPw, &compress, &headerLen,
&dataHashType, &dataHash, &f);
if (ret != e_success) {
printDebug("PwMDoc::openDoc(): checkHeader() failed");
f.close();
if (ret == e_wrongPw) {
wrongMpwMsgBox(getDocStatFlag(DOC_STAT_USE_CHIPCARD));
return ret;
} else if (ret == e_noPw ||
ret == e_fileVer ||
ret == e_fileFormat ||
ret == e_hashNotImpl) {
return ret;
} else
return e_readFile;
}
ret = decrypt(&decrypted, headerLen, &currentPw, cryptAlgo, &f);
if (ret == e_cryptNotImpl) {
printDebug("PwMDoc::openDoc(): decrypt() failed: e_cryptNotImpl");
f.close();
return e_cryptNotImpl;
} else if (ret != e_success) {
printDebug("PwMDoc::openDoc(): decrypt() failed");
f.close();
return e_readFile;
}
if (!decompressDta(&decrypted, compress)) {
printDebug("PwMDoc::openDoc(): decompressDta() failed");
f.close();
return e_fileCorrupt;
}
ret = checkDataHash(dataHashType, &dataHash, &decrypted);
if (ret == e_hashNotImpl) {
printDebug("PwMDoc::openDoc(): checkDataHash() failed: e_hashNotImpl");
f.close();
return e_hashNotImpl;
} else if (ret != e_success) {
printDebug("PwMDoc::openDoc(): checkDataHash() failed");
f.close();
return e_fileCorrupt;
}
if (!deSerializeDta(&decrypted, openLocked == 1)) {
printDebug("PwMDoc::openDoc(): deSerializeDta() failed");
f.close();
return e_readFile;
}
f.close();
timer()->start(DocTimer::id_mpwTimer);
timer()->start(DocTimer::id_autoLockTimer);
out_success:
openDocList.edit(this, getTitle().latin1());
emit docOpened(this);
return e_success;
}
PwMerror PwMDoc::writeFileHeader(char keyHash, char dataHash, char crypt, char compress,
QString *pw, QFile *f)
{
PWM_ASSERT(pw);
PWM_ASSERT(f);
//US ENH: or maybe a bug: checking here for listView does not make sense because we do not check anywhere else
//Wenn I sync, I open a doc without a view => listView is 0 => Assertion
//US PWM_ASSERT(listView);
if (f->writeBlock(FILE_ID_HEADER, strlen(FILE_ID_HEADER)) !=
static_cast<Q_LONG>(strlen(FILE_ID_HEADER))) {
return e_writeFile;
}
if (f->putch(PWM_FILE_VER) == -1 ||
f->putch(keyHash) == -1 ||
f->putch(dataHash) == -1 ||
f->putch(crypt) == -1 ||
f->putch(compress) == -1 ||
f->putch((getDocStatFlag(DOC_STAT_USE_CHIPCARD)) ?
(static_cast<char>(0x01)) : (static_cast<char>(0x00))) == -1) {
return e_writeFile;
}
// write bytes of NUL-data. These bytes are reserved for future-use.
const int bufSize = 64;
char tmp_buf[bufSize];
memset(tmp_buf, 0x00, bufSize);
if (f->writeBlock(tmp_buf, bufSize) != bufSize)
return e_writeFile;
switch (keyHash) {
case PWM_HASH_SHA1: {
const int hashlen = SHA1_HASH_LEN_BYTE;
Sha1 hash;
hash.sha1_write(reinterpret_cast<const byte *>(pw->latin1()), pw->length());
string ret = hash.sha1_read();
if (f->writeBlock(ret.c_str(), hashlen) != hashlen)
return e_writeFile;
break;
}
case PWM_HASH_SHA256:
/*... fall through */
case PWM_HASH_SHA384:
case PWM_HASH_SHA512:
case PWM_HASH_MD5:
case PWM_HASH_RMD160:
case PWM_HASH_TIGER:
{
if (!LibGCryptIf::available())
return e_hashNotImpl;
LibGCryptIf gc;
PwMerror err;
unsigned char *buf;
size_t hashLen;
err = gc.hash(&buf,
&hashLen,
reinterpret_cast<const unsigned char *>(pw->latin1()),
pw->length(),
keyHash);
if (err != e_success)
return e_hashNotImpl;
if (f->writeBlock(reinterpret_cast<const char *>(buf), hashLen)
!= static_cast<Q_LONG>(hashLen)) {
delete [] buf;
return e_hashNotImpl;
}
delete [] buf;
break;
}
default: {
return e_hashNotImpl;
} }
return e_success;
}
PwMerror PwMDoc::checkHeader(char *cryptAlgo, QString *pw, char *compress,
unsigned int *headerLength, char *dataHashType,
string *dataHash, QFile *f)
{
PWM_ASSERT(cryptAlgo);
PWM_ASSERT(pw);
PWM_ASSERT(headerLength);
PWM_ASSERT(dataHashType);
PWM_ASSERT(dataHash);
PWM_ASSERT(f);
int tmpRet;
// check "magic" header
const char magicHdr[] = FILE_ID_HEADER;
const int hdrLen = array_size(magicHdr) - 1;
char tmp[hdrLen];
if (f->readBlock(tmp, hdrLen) != hdrLen)
return e_readFile;
if (memcmp(tmp, magicHdr, hdrLen) != 0)
return e_fileFormat;
// read and check file ver
int fileV = f->getch();
if (fileV == -1)
return e_fileFormat;
if (fileV != PWM_FILE_VER)
return e_fileVer;
// read hash hash type
int keyHash = f->getch();
if (keyHash == -1)
return e_fileFormat;
// read data hash type
tmpRet = f->getch();
if (tmpRet == -1)
return e_fileFormat;
*dataHashType = tmpRet;
// read crypt algo
tmpRet = f->getch();
if (tmpRet == -1)
return e_fileFormat;
*cryptAlgo = tmpRet;
// get compression-algo
tmpRet = f->getch();
if (tmpRet == -1)
return e_fileFormat;
*compress = tmpRet;
// get the MPW-flag
int mpw_flag = f->getch();
if (mpw_flag == -1)
return e_fileFormat;
if (mpw_flag == 0x01)
setDocStatFlag(DOC_STAT_USE_CHIPCARD);
else
unsetDocStatFlag(DOC_STAT_USE_CHIPCARD);
// skip the "RESERVED"-bytes
if (!(f->at(f->at() + 64)))
return e_fileFormat;
*pw = requestMpw(getDocStatFlag(DOC_STAT_USE_CHIPCARD));
if (*pw == "") {
/* the user didn't give a master-password
@@ -1516,512 +1558,515 @@ bool PwMDoc::lockAll(bool lock)
}
if (!lock && currentPw != "") {
// unlocking and password is already set
if (!getDocStatFlag(DOC_STAT_UNLOCK_WITHOUT_PW)) {
// unlocking without pw not allowed
QString pw;
pw = requestMpw(getDocStatFlag(DOC_STAT_USE_CHIPCARD));
if (pw != "") {
if (pw != currentPw) {
wrongMpwMsgBox(getDocStatFlag(DOC_STAT_USE_CHIPCARD));
return false;
} else {
timer()->start(DocTimer::id_mpwTimer);
}
} else {
return false;
}
} else {
timer()->start(DocTimer::id_mpwTimer);
}
}
vector<PwMCategoryItem>::iterator catBegin = 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) {
entrI->lockStat = lock;
entrI->rev++; // increment revision counter.
++entrI;
}
++catI;
}
emitDataChanged(this);
if (lock)
timer()->stop(DocTimer::id_autoLockTimer);
else
timer()->start(DocTimer::id_autoLockTimer);
return true;
}
bool PwMDoc::isLocked(const QString &category, unsigned int index)
{
unsigned int cat = 0;
if (!findCategory(category, &cat)) {
BUG();
return false;
}
return isLocked(cat, index);
}
bool PwMDoc::unlockAll_tempoary(bool revert)
{
static vector< vector<bool> > *oldLockStates = 0;
static bool wasDeepLocked;
if (revert) { // revert the unlocking
if (oldLockStates) {
/* we actually _have_ unlocked something, because
* we have allocated space for the oldLockStates.
* So, go on and revert them!
*/
if (wasDeepLocked) {
PwMerror ret = deepLock(true);
if (ret == e_success) {
/* deep-lock succeed. We are save.
* (but if it failed, just go on
* lock them normally)
*/
delete_and_null(oldLockStates);
timer()->start(DocTimer::id_autoLockTimer);
printDebug("tempoary unlocking of dta "
"reverted by deep-locking.");
return true;
}
printDebug("deep-lock failed while reverting! "
"Falling back to normal-lock.");
}
if (unlikely(!wasDeepLocked &&
numCategories() != oldLockStates->size())) {
/* DOH! We have modified "dta" while
* it was unlocked tempoary. DON'T DO THIS!
*/
BUG();
delete_and_null(oldLockStates);
timer()->start(DocTimer::id_autoLockTimer);
return false;
}
vector<PwMCategoryItem>::iterator catBegin = dti.dta.begin(),
catEnd = dti.dta.end(),
catI = catBegin;
vector<PwMDataItem>::iterator entrBegin, entrEnd, entrI;
vector< vector<bool> >::iterator oldCatStatI = oldLockStates->begin();
vector<bool>::iterator oldEntrStatBegin,
oldEntrStatEnd,
oldEntrStatI;
while (catI != catEnd) {
entrBegin = catI->d.begin();
entrEnd = catI->d.end();
entrI = entrBegin;
if (likely(!wasDeepLocked)) {
oldEntrStatBegin = oldCatStatI->begin();
oldEntrStatEnd = oldCatStatI->end();
oldEntrStatI = oldEntrStatBegin;
if (unlikely(catI->d.size() != oldCatStatI->size())) {
/* DOH! We have modified "dta" while
* it was unlocked tempoary. DON'T DO THIS!
*/
BUG();
delete_and_null(oldLockStates);
timer()->start(DocTimer::id_autoLockTimer);
return false;
}
}
while (entrI != entrEnd) {
if (wasDeepLocked) {
/* this is an error-fallback if
* deeplock didn't succeed
*/
entrI->lockStat = true;
} else {
entrI->lockStat = *oldEntrStatI;
}
++entrI;
if (likely(!wasDeepLocked))
++oldEntrStatI;
}
++catI;
if (likely(!wasDeepLocked))
++oldCatStatI;
}
delete_and_null(oldLockStates);
if (unlikely(wasDeepLocked)) {
/* error fallback... */
unsetDocStatFlag(DOC_STAT_DEEPLOCKED);
emitDataChanged(this);
printDebug("WARNING: unlockAll_tempoary(true) "
"deeplock fallback!");
}
printDebug("tempoary unlocking of dta reverted.");
} else {
printDebug("unlockAll_tempoary(true): nothing to do.");
}
timer()->start(DocTimer::id_autoLockTimer);
} else { // unlock all data tempoary
if (unlikely(oldLockStates != 0)) {
/* DOH! We have already unlocked the data tempoarly.
* No need to do it twice. ;)
*/
BUG();
return false;
}
wasDeepLocked = false;
bool mustUnlock = false;
if (isDeepLocked()) {
PwMerror ret;
while (1) {
ret = deepLock(false);
if (ret == e_success) {
break;
} else if (ret == e_wrongPw) {
wrongMpwMsgBox(getDocStatFlag(DOC_STAT_USE_CHIPCARD));
} else {
printDebug("deep-unlocking failed while "
"tempoary unlocking!");
return false;
}
}
wasDeepLocked = true;
mustUnlock = true;
} else {
// first check if it's needed to unlock some entries
vector<PwMCategoryItem>::iterator catBegin = 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 (entrI->lockStat == true) {
mustUnlock = true;
break;
}
++entrI;
}
if (mustUnlock)
break;
++catI;
}
}
if (!mustUnlock) {
// nothing to do.
timer()->stop(DocTimer::id_autoLockTimer);
printDebug("unlockAll_tempoary(): nothing to do.");
return true;
} else if (!wasDeepLocked) {
if (!getDocStatFlag(DOC_STAT_UNLOCK_WITHOUT_PW) &&
currentPw != "") {
/* we can't unlock without mpw, so
* we need to ask for it.
*/
QString pw;
while (1) {
pw = requestMpw(getDocStatFlag(DOC_STAT_USE_CHIPCARD));
if (pw == "") {
return false;
} else if (pw == currentPw) {
break;
}
wrongMpwMsgBox(getDocStatFlag(DOC_STAT_USE_CHIPCARD));
}
}
}
timer()->stop(DocTimer::id_autoLockTimer);
oldLockStates = new vector< vector<bool> >;
vector<bool> tmp_vec;
vector<PwMCategoryItem>::iterator catBegin = 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;
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(&currentPw, &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,
caseSensitive, exactWordMatch)) {
continue;
}
}
if (searchIn & SEARCH_IN_URL) {
if (!compareString(find.url, dti.dta[category].d[i].url,
caseSensitive, exactWordMatch)) {
continue;
}
}
if (searchIn & SEARCH_IN_LAUNCHER) {
if (!compareString(find.launcher, dti.dta[category].d[i].launcher,
caseSensitive, exactWordMatch)) {
continue;
}
}
// all selected "searchIn" matched.
foundPositions->push_back(i);
if (breakAfterFound)
break;
}
if (sortByLvp && foundPositions->size() > 1) {
vector< pair<unsigned int /* foundPosition (real doc pos) */,
unsigned int /* lvp-pos */> > tmp_vec;
unsigned int i, items = foundPositions->size();
pair<unsigned int, unsigned int> tmp_pair;
for (i = 0; i < items; ++i) {
tmp_pair.first = (*foundPositions)[i];
tmp_pair.second = dti.dta[category].d[(*foundPositions)[i]].listViewPos;
tmp_vec.push_back(tmp_pair);
}
sort(tmp_vec.begin(), tmp_vec.end(), dta_lvp_greater());
foundPositions->clear();
for (i = 0; i < items; ++i) {
foundPositions->push_back(tmp_vec[i].first);
}
}
}
void PwMDoc::findEntry(const QString &category, PwMDataItem find, unsigned int searchIn,
vector<unsigned int> *foundPositions, bool breakAfterFound,
bool caseSensitive, bool exactWordMatch, bool sortByLvp)
{
PWM_ASSERT(foundPositions);
unsigned int cat = 0;
if (!findCategory(category, &cat)) {
foundPositions->clear();
return;
}
findEntry(cat, find, searchIn, foundPositions, breakAfterFound,
caseSensitive, exactWordMatch, sortByLvp);
}
bool PwMDoc::compareString(const string &s1, const string &s2, bool caseSensitive,
bool exactWordMatch)
{
QString _s1(s1.c_str());
QString _s2(s2.c_str());
if (!caseSensitive) {
_s1 = _s1.lower();
_s2 = _s2.lower();
}
if (exactWordMatch ? (_s1 == _s2) : (_s2.find(_s1) != -1))
return true;
return false;
}
bool PwMDoc::findCategory(const QString &name, unsigned int *index)
{
vector<PwMCategoryItem>::iterator i = dti.dta.begin(),
end = dti.dta.end();
while (i != end) {
if ((*i).name == name.latin1()) {
if (index) {
*index = i - dti.dta.begin();
}
return true;
}
++i;
}
return false;
}
bool PwMDoc::renameCategory(const QString &category, const QString &newName)
{
unsigned int cat = 0;
if (!findCategory(category, &cat))
return false;
return renameCategory(cat, newName);
}
bool PwMDoc::renameCategory(unsigned int category, const QString &newName,
bool dontFlagDirty)
{
if (category > numCategories() - 1)
return false;
diff --git a/pwmanager/pwmanager/pwmdoc.h b/pwmanager/pwmanager/pwmdoc.h
index 535fb92..a6e5f58 100644
--- a/pwmanager/pwmanager/pwmdoc.h
+++ b/pwmanager/pwmanager/pwmdoc.h
@@ -1,270 +1,270 @@
/***************************************************************************
* *
* copyright (C) 2003, 2004 by Michael Buesch *
* email: mbuesch@freenet.de *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 *
* as published by the Free Software Foundation. *
* *
***************************************************************************/
/***************************************************************************
* copyright (C) 2004 by Ulf Schenk
- * This file is originaly based on version 2.0 of pwmanager
+ * This file is originaly based on version 1.1 of pwmanager
* and was modified to run on embedded devices that run microkde
*
* $Id$
**************************************************************************/
#ifndef __PWMDOC_H
#define __PWMDOC_H
#define PWM_FILE_VER (static_cast<char>(0x05))
#define PWM_HASH_SHA1 (static_cast<char>(0x01))
#define PWM_HASH_SHA256 (static_cast<char>(0x02))
#define PWM_HASH_SHA384 (static_cast<char>(0x03))
#define PWM_HASH_SHA512 (static_cast<char>(0x04))
#define PWM_HASH_MD5 (static_cast<char>(0x05))
#define PWM_HASH_RMD160 (static_cast<char>(0x06))
#define PWM_HASH_TIGER (static_cast<char>(0x07))
#define PWM_CRYPT_BLOWFISH (static_cast<char>(0x01))
#define PWM_CRYPT_AES128 (static_cast<char>(0x02))
#define PWM_CRYPT_AES192 (static_cast<char>(0x03))
#define PWM_CRYPT_AES256 (static_cast<char>(0x04))
#define PWM_CRYPT_3DES (static_cast<char>(0x05))
#define PWM_CRYPT_TWOFISH (static_cast<char>(0x06))
#define PWM_CRYPT_TWOFISH128 (static_cast<char>(0x07))
#define PWM_COMPRESS_NONE (static_cast<char>(0x00))
#define PWM_COMPRESS_GZIP (static_cast<char>(0x01))
#define PWM_COMPRESS_BZIP2 (static_cast<char>(0x02))
#define DEFAULT_MAX_ENTRIES (~(static_cast<unsigned int>(0)))
#define FILE_ID_HEADER "PWM_PASSWORD_FILE"
#include "pwmexception.h"
#include "pwmdocui.h"
#include <qobject.h>
#include <qtimer.h>
#include <qdatetime.h>
#include <kprocess.h>
#ifndef PWM_EMBEDDED
#include "configuration.h"
#else
#include <kapplication.h>
#include <ksyncmanager.h>
#endif
#include <string>
#include <vector>
#include <utility>
using std::vector;
using std::string;
using std::pair;
/* used in findEntry() function */
#define SEARCH_IN_DESC (1)
#define SEARCH_IN_NAME (1 << 1)
#define SEARCH_IN_PW (1 << 2)
#define SEARCH_IN_COMMENT (1 << 3)
#define SEARCH_IN_URL (1 << 4)
#define SEARCH_IN_LAUNCHER (1 << 5)
#define SEARCH_IN_ALL (SEARCH_IN_DESC | SEARCH_IN_NAME | \
SEARCH_IN_PW | SEARCH_IN_COMMENT | \
SEARCH_IN_URL | SEARCH_IN_LAUNCHER)
/** document deeplocked. Data is out for lunch to disk */
#define DOC_STAT_DEEPLOCKED (1)
/** encrypted document on disk is dirty. data has to go to disk. */
#define DOC_STAT_DISK_DIRTY (1 << 1)
/** we are using a chipcard to encrypt the data */
#define DOC_STAT_USE_CHIPCARD (1 << 2)
/** use "currentPw" to unlock. (This flag is set/unset by a timer) */
#define DOC_STAT_UNLOCK_WITHOUT_PW (1 << 3)
class PwMDoc;
class PwMView;
class QFile;
/* meta data for a PwMDataItem */
struct PwMMetaData
{
PwMMetaData()
: updateInt (0)
{ }
/** creation date of the PwMDataItem to which
* this meta data belongs.
*/
QDateTime create;
/** becomes valid on this date */
QDateTime valid;
/** expire date */
QDateTime expire;
/** update date (last updated at this date) */
QDateTime update;
/** update interval (in minutes). Time since the
* last update to remind the user to update the item.
* 0 disables.
*/
unsigned long updateInt;
//US ENH: enhancements of the filestructure
/* each entry gets a unique id assigned */
string uniqueid;
void clear()
{
create = QDateTime();
expire = QDateTime();
update = QDateTime();
updateInt = 0;
uniqueid = KApplication::randomString(8);
}
inline bool isValid() const
{
if (valid.isNull())
return true;
return (valid < QDateTime::currentDateTime());
}
inline bool isExpired() const
{
if (expire.isNull())
return false;
return (expire < QDateTime::currentDateTime());
}
inline bool isUpdateIntOver() const
{
if (updateInt == 0 ||
update.isNull())
return false;
QDateTime d(update);
return (d.addSecs(updateInt * 60) < QDateTime::currentDateTime());
}
};
struct PwMDataItem
{
PwMDataItem()
: lockStat (true)
, listViewPos (-1)
, binary (false)
, rev (0)
{ }
/** password description */
string desc;
/** user-name */
string name;
/** the password itself */
string pw;
/** some comment */
string comment;
/** an URL string */
string url;
/** launcher. Can be executed as a system() command */
string launcher;
/** locking status. If locked (true), pw is not emitted through getEntry() */
bool lockStat;
/** position of this item in main "list-view"
* If -1, the position is not yet specified and should be appended to the list
*/
int listViewPos;
/** does this entry contain binary data? */
bool binary;
/** meta data for this data item. */
PwMMetaData meta;
/** data revision counter. This counter can be used
* to easily, efficiently determine if this data item
* has changed since some time.
* This counter is incremented on every update.
*/
unsigned int rev;
void clear(bool clearMeta = true)
{
/* NOTE: Don't use .clear() here to be
* backward compatible with gcc-2 (Debian Woody)
*/
desc = "";
name = "";
pw = "";
comment = "";
url = "";
launcher = "";
lockStat = true;
listViewPos = -1;
binary = false;
if (clearMeta)
meta.clear();
}
//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;
}
};
struct PwMCategoryItem
{
/** all PwMDataItems (all passwords) within this category */
vector<PwMDataItem> d;
/** category name/description */
string name;
void clear()
{
d.clear();
name = "";
}
};
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,
diff --git a/pwmanager/pwmanager/pwmdocui.cpp b/pwmanager/pwmanager/pwmdocui.cpp
index 7b8e0ee..6ddb6f5 100644
--- a/pwmanager/pwmanager/pwmdocui.cpp
+++ b/pwmanager/pwmanager/pwmdocui.cpp
@@ -20,438 +20,448 @@
#include "pwmdocui.h"
#include "setmasterpwwndimpl.h"
#include "getmasterpwwndimpl.h"
#include "pwmexception.h"
#include "getkeycardwnd.h"
#include "pwm.h"
#include "globalstuff.h"
#include "spinforsignal.h"
#include <qlineedit.h>
#include <qtabwidget.h>
#include <kmessagebox.h>
#include <kfiledialog.h>
#ifndef PWM_EMBEDDED
#include <kwin.h>
#else
#include <qdir.h>
#include "pwmprefs.h"
#endif
#ifdef CONFIG_KEYCARD
# include "pwmkeycard.h"
#endif
PwMDocUi::PwMDocUi(QObject *parent, const char *name)
: QObject(parent, name)
{
currentView = 0;
keyCard = 0;
}
PwMDocUi::~PwMDocUi()
{
}
QString PwMDocUi::requestMpw(bool chipcard)
{
QString pw;
if (chipcard) {
#ifdef CONFIG_KEYCARD
PWM_ASSERT(keyCard);
uint32_t id;
string ret;
SpinForSignal *spinner = keyCard->getSpinner();
connect(keyCard, SIGNAL(keyAvailable(uint32_t, const string &)),
spinner, SLOT(u32_str_slot(uint32_t, const string &)));
keyCard->getKey();
spinner->spin(&id, &ret);
disconnect(keyCard, SIGNAL(keyAvailable(uint32_t, const string &)),
spinner, SLOT(u32_str_slot(uint32_t, const string &)));
if (ret == "")
return "";
pw = ret.c_str();
#else // CONFIG_KEYCARD
no_keycard_support_msg_box(currentView);
#endif // CONFIG_KEYCARD
} else {
#ifndef PWM_EMBEDDED
GetMasterPwWndImpl pwWnd;
KWin::setState(pwWnd.winId(), NET::StaysOnTop);
#else
GetMasterPwWndImpl pwWnd;
#endif
if (pwWnd.exec() != 1)
return "";
pw = pwWnd.pwLineEdit->text();
}
return pw;
}
QString PwMDocUi::requestNewMpw(bool *chipcard)
{
QString pw;
SetMasterPwWndImpl pwWnd(currentView);
pwWnd.setPwMKeyCard(keyCard);
if (!chipcard) {
#ifndef PWM_EMBEDDED
pwWnd.mainTab->removePage(pwWnd.mainTab->page(1));
#else
pwWnd.mainTab->removePage(pwWnd.tab_2);
#endif
}
if (pwWnd.exec() != 1)
return "";
pw = pwWnd.getPw(chipcard).c_str();
return pw;
}
QString PwMDocUi::requestMpwChange(const QString *currentPw, bool *chipcard)
{
QString pw(requestMpw(*chipcard));
if (pw == "")
return "";
if (pw != *currentPw) {
wrongMpwMsgBox(*chipcard);
return "";
}
pw = requestNewMpw(chipcard);
if (pw == "")
return "";
return pw;
}
void PwMDocUi::wrongMpwMsgBox(bool chipcard, QString prefix, QString postfix)
{
QString msg;
if (prefix != "") {
msg += prefix;
msg += "\n";
}
if (chipcard) {
msg += i18n("Wrong key-card!\n"
"Please try again with the\n"
"correct key-card.");
} else {
msg += i18n("Wrong master-password!\n"
"Please try again.");
}
if (postfix != "") {
msg += "\n";
msg += postfix;
}
KMessageBox::error(currentView, msg,
(chipcard) ? (i18n("wrong chipcard"))
: (i18n("password error")));
}
void PwMDocUi::noMpwMsgBox(bool chipcard, QString prefix, QString postfix)
{
QString msg;
if (prefix != "") {
msg += prefix;
msg += "\n";
}
if (chipcard) {
msg += i18n("No key-card found!\n"
"Please insert the\n"
"correct key-card.");
} else {
msg += i18n("No master-password given!");
}
if (postfix != "") {
msg += "\n";
msg += postfix;
}
KMessageBox::error(currentView, msg,
(chipcard) ? (i18n("no chipcard"))
: (i18n("password error")));
}
void PwMDocUi::rootAlertMsgBox()
{
KMessageBox::error(currentView,
i18n("This feature is not available,n"
"if you execute PwM with \"root\" \n"
"UID 0 privileges, for security reasons!"),
i18n("not allowed as root!"));
}
void PwMDocUi::cantDeeplock_notSavedMsgBox()
{
KMessageBox::error(currentView,
i18n("Can't deep-lock, because the document\n"
"hasn't been saved, yet. Please save\n"
"to a file and try again."),
i18n("not saved, yet"));
}
void PwMDocUi::gpmPwLenErrMsgBox()
{
KMessageBox::error(currentView,
i18n("GPasman does not support passwords\n"
"shorter than 4 characters! Please try\n"
"again with a longer password."),
i18n("password too short"));
}
int PwMDocUi::dirtyAskSave(const QString &docTitle)
{
int ret;
#ifndef PWM_EMBEDDED
ret = KMessageBox::questionYesNoCancel(currentView,
i18n("The list \"") +
docTitle +
i18n
("\" has been modified.\n"
"Do you want to save it?"),
i18n("save?"));
if (ret == KMessageBox::Yes) {
return 0;
} else if (ret == KMessageBox::No) {
return 1;
}
#else
ret = KMessageBox::warningYesNoCancel(currentView,
i18n("The list \"") +
docTitle +
i18n
("\"\nhas been modified.\n"
"Do you want to save it?"),
i18n("save?"));
if (ret == KMessageBox::Yes) {
return 0;
} else if (ret == KMessageBox::No) {
return 1;
}
#endif
// cancel
return -1;
}
bool PwMDocUi::saveDocUi(PwMDoc *doc)
{
PWM_ASSERT(doc);
doc->timer()->getLock(DocTimer::id_autoLockTimer);
if (doc->isDocEmpty()) {
KMessageBox::information(currentView,
i18n
("Sorry, there's nothing to save.\n"
"Please first add some passwords."),
i18n("nothing to do"));
doc->timer()->putLock(DocTimer::id_autoLockTimer);
return true;
}
PwMerror ret = doc->saveDoc(conf()->confGlobCompression());
if (ret == e_filename) {
doc->timer()->putLock(DocTimer::id_autoLockTimer);
return saveAsDocUi(doc);
} else if (ret == e_weakPw) {
KMessageBox::error(currentView,
i18n("Error: This is a weak password.\n"
"Please select another password."),
i18n("weak password"));
doc->timer()->putLock(DocTimer::id_autoLockTimer);
return false;
} else if (ret == e_fileBackup) {
KMessageBox::error(currentView,
i18n("Error: Couldn't make backup-file!"),
i18n("backup failed"));
doc->timer()->putLock(DocTimer::id_autoLockTimer);
return false;
+ } else if (ret == e_noPw ||
+ ret == e_wrongPw ||
+ ret == e_openFile) {
+ doc->timer()->putLock(DocTimer::id_autoLockTimer);
+ return false;
} else if (ret != e_success) {
KMessageBox::error(currentView,
i18n("Error: Couldn't write to file.\n"
"Please check if you have permission to\n"
"write to the file in that directory."),
i18n("error while writing"));
doc->timer()->putLock(DocTimer::id_autoLockTimer);
return false;
}
doc->timer()->putLock(DocTimer::id_autoLockTimer);
return true;
}
bool PwMDocUi::saveAsDocUi(PwMDoc *doc)
{
PWM_ASSERT(doc);
doc->timer()->getLock(DocTimer::id_autoLockTimer);
if (doc->isDocEmpty()) {
KMessageBox::information(currentView,
i18n
("Sorry, there's nothing to save.\n"
"Please first add some passwords."),
i18n("nothing to do"));
doc->timer()->putLock(DocTimer::id_autoLockTimer);
return true;
}
#ifndef PWM_EMBEDDED
QString fn(KFileDialog::getSaveFileName(QString::null,
i18n("*.pwm|PwManager Password file"),
currentView));
#else
QString fn = locateLocal( "data", KGlobal::getAppName() + "/*.pwm" );
fn = KFileDialog::getSaveFileName(fn,
i18n("password filename(*.pwm)"),
currentView);
#endif
if (fn == "") {
doc->timer()->putLock(DocTimer::id_autoLockTimer);
return false;
}
if (fn.right(4) != ".pwm")
fn += ".pwm";
PwMerror ret = doc->saveDoc(conf()->confGlobCompression(), &fn);
- if (ret != e_success) {
+ if (ret == e_noPw ||
+ ret == e_wrongPw ||
+ ret == e_openFile) {
+ doc->timer()->putLock(DocTimer::id_autoLockTimer);
+ return false;
+ } else if (ret != e_success) {
KMessageBox::error(currentView,
i18n("Error: Couldn't write to file.\n"
"Please check if you have permission to\n"
"write to the file in that directory."),
i18n("error while writing"));
doc->timer()->putLock(DocTimer::id_autoLockTimer);
return false;
}
doc->timer()->putLock(DocTimer::id_autoLockTimer);
return true;
}
bool PwMDocUi::openDocUi(PwMDoc *doc,
QString filename,
bool openDeepLocked)
{
if (filename.isEmpty())
{
#ifndef PWM_EMBEDDED
filename = KFileDialog::getOpenFileName(QString::null,
i18n("*.pwm|PwManager Password file\n"
"*|All files"), getCurrentView());
#else
filename = locateLocal( "data", KGlobal::getAppName() + "/*.pwm");
filename = KFileDialog::getOpenFileName(filename,
i18n("password filename(*.pwm)"), getCurrentView());
#endif
}
if (filename.isEmpty())
goto cancelOpen;
PwMerror ret;
while (true) {
int lockStat = -1;
if (openDeepLocked) {
lockStat = 2;
} else {
if (conf()->confGlobUnlockOnOpen()) {
lockStat = 0;
} else {
lockStat = 1;
}
}
ret = doc->openDoc(&filename, lockStat);
//qDebug("pwmdocui::OpenDocui %i", ret);
if (ret != e_success) {
if (ret == e_readFile || ret == e_openFile) {
KMessageBox::error(getCurrentView(),
i18n("Could not read file!")
+ "\n"
+ filename,
i18n("file error"));
goto cancelOpen;
}
if (ret == e_alreadyOpen) {
KMessageBox::error(getCurrentView(),
i18n("This file is already open."),
i18n("already open"));
goto cancelOpen;
}
if (ret == e_fileVer) {
KMessageBox::error(getCurrentView(),
i18n
("File-version is not supported!\n"
"Did you create this file with an\nolder or newer version of PwM?"),
i18n
("incompatible version"));
goto cancelOpen;
}
if (ret == e_wrongPw) {
continue;
}
if (ret == e_noPw) {
goto cancelOpen;
}
if (ret == e_fileFormat) {
KMessageBox::error(getCurrentView(),
i18n
("Sorry, this file has not been recognized\n"
"as a PwM Password file.\n"
"Probably you have selected the wrong file."),
i18n
("no PwM password-file"));
goto cancelOpen;
}
if (ret == e_fileCorrupt) {
KMessageBox::error(getCurrentView(),
i18n
("File corrupt!\n"
"Maybe the media, you stored this file on,\n"
"had bad sectors?"),
i18n
("checksum error"));
goto cancelOpen;
}
}
break;
}
return true;
cancelOpen:
return false;
}
QString PwMDocUi::string_defaultCategory()
{
return i18n("Default");
}
QString PwMDocUi::string_locked()
{
return i18n("<LOCKED>");
}
QString PwMDocUi::string_deepLockedShort()
{
return i18n("DEEP-LOCKED");
}
QString PwMDocUi::string_deepLockedLong()
{
return i18n("This file is DEEP-LOCKED!\n"
"That means all data has been encrypted\n"
"and written out to the file. If you want\n"
"to see the entries, please UNLOCK the file.\n"
"While unlocking, you will be prompted for the\n"
"master-password or the key-card.");
}
QString PwMDocUi::string_defaultTitle()
{
return i18n("Untitled");
}
#ifndef PWM_EMBEDDED
#include "pwmdocui.moc"
#endif