summaryrefslogtreecommitdiffabout
Side-by-side diff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--pwmanager/pwmanager/pwmanagerE.pro2
-rw-r--r--pwmanager/pwmanager/pwmdoc.cpp568
-rw-r--r--pwmanager/pwmanager/pwmdoc.h70
-rw-r--r--pwmanager/pwmanager/pwmdocui.cpp2
-rw-r--r--pwmanager/pwmanager/pwmexception.h1
-rw-r--r--pwmanager/pwmanager/pwmview.cpp64
-rw-r--r--pwmanager/pwmanager/pwmview.h22
-rw-r--r--pwmanager/pwmanager/serializer.cpp109
-rw-r--r--pwmanager/pwmanager/serializer.h17
9 files changed, 746 insertions, 109 deletions
diff --git a/pwmanager/pwmanager/pwmanagerE.pro b/pwmanager/pwmanager/pwmanagerE.pro
index 2558aca..95f5bf3 100644
--- a/pwmanager/pwmanager/pwmanagerE.pro
+++ b/pwmanager/pwmanager/pwmanagerE.pro
@@ -1,58 +1,58 @@
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 $(QPEDIR)/include
+INCLUDEPATH += . ../../ ../../qtcompat ../../qtcompat/xml ../../libkdepim ../../microkde ../../microkde/kdecore ../../microkde/kdeui ../../microkde/kutils $(QPEDIR)/include
DEFINES += PWM_EMBEDDED
#enable this setting if you want debugoutput for pwmanager
#DEFINES += CONFIG_DEBUG
LIBS += -lmicrokde
LIBS += -lmicroqtcompat
LIBS += -lmicrokdepim
LIBS += -L$(QPEDIR)/lib
LIBS += -lqpe
LIBS += -lbz2
LIBS += $(QTOPIALIB)
#INTERFACES = \
#addentrywnd.ui \
#configwnd.ui \
#findwnd.ui \
#getmasterpwwnd.ui \
#pwgenwnd.ui \
#setmasterpwwnd.ui \
#subtbledit.ui
#INTERFACES = \
#subtbledit.ui \
#HEADERS = \
#configuration_31compat.h \
#configuration.h \
#configwnd.h \
#configwndimpl.h \
#selftest.h
#subtbledit.h \
#subtbleditimpl.h \
HEADERS = \
addentrywnd_emb.h \
addentrywndimpl.h \
base64.h \
binentrygen.h \
blowfish.h \
commentbox.h \
compiler.h \
compressbzip2.h \
compressgzip.h \
findwnd_emb.h \
findwndimpl.h \
genpasswd.h \
diff --git a/pwmanager/pwmanager/pwmdoc.cpp b/pwmanager/pwmanager/pwmdoc.cpp
index 82fc746..4e8a603 100644
--- a/pwmanager/pwmanager/pwmdoc.cpp
+++ b/pwmanager/pwmanager/pwmdoc.cpp
@@ -1,85 +1,89 @@
/***************************************************************************
* *
* copyright (C) 2003, 2004 by Michael Buesch *
* email: mbuesch@freenet.de *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 *
* as published by the Free Software Foundation. *
* *
***************************************************************************/
/***************************************************************************
* copyright (C) 2004 by Ulf Schenk
* This file is originaly based on version 2.0 of pwmanager
* and was modified to run on embedded devices that run microkde
*
* $Id$
**************************************************************************/
#include "pwmdoc.h"
#include "pwmview.h"
#include "blowfish.h"
#include "sha1.h"
#include "globalstuff.h"
#include "gpasmanfile.h"
#include "serializer.h"
#include "compressgzip.h"
#include "compressbzip2.h"
#include "randomizer.h"
#include "pwminit.h"
#ifndef PWM_EMBEDDED
//US #include "libgryptif.h"
#else
#include "pwmprefs.h"
#include "kglobal.h"
#endif
+#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>
//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)
@@ -962,319 +966,319 @@ bool PwMDoc::copyFile(const QString &src, const QString &dst)
return false;
}
}
srcFd.close();
dstFd.close();
return true;
}
PwMerror PwMDoc::addEntry(const QString &category, PwMDataItem *d,
bool dontFlagDirty, bool updateMeta)
{
PWM_ASSERT(d);
unsigned int cat = 0;
if (isDeepLocked()) {
PwMerror ret;
ret = deepLock(false);
if (ret != e_success)
return e_lock;
}
addCategory(category, &cat);
if (numEntries(category) >= maxEntries)
return e_maxAllowedEntr;
vector<unsigned int> foundPositions;
/* historically this was:
* const int searchIn = SEARCH_IN_DESC | SEARCH_IN_NAME |
* SEARCH_IN_URL | SEARCH_IN_LAUNCHER;
* But for now we only search in desc.
* That's a tweak to be KWallet compatible. But it should not add
* usability-drop onto PwManager, does it?
* (And yes, "int" was a bug. Correct is "unsigned int")
*/
const unsigned int searchIn = SEARCH_IN_DESC;
findEntry(cat, *d, searchIn, &foundPositions, true);
if (foundPositions.size()) {
// DOH! We found this entry.
return e_entryExists;
}
d->listViewPos = -1;
d->lockStat = conf()->confGlobNewEntrLockStat();
if (updateMeta) {
d->meta.create = QDateTime::currentDateTime();
d->meta.update = d->meta.create;
}
- dta[cat].d.push_back(*d);
+ 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;
item.name = category.latin1();
- dta.push_back(item);
+ dti.dta.push_back(item);
if (categoryIndex)
- *categoryIndex = dta.size() - 1;
+ *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 > dta[category].d.size() - 1)
+ if (index > dti.dta[category].d.size() - 1)
return false;
getDataChangedLock();
if (!lockAt(category, index, false)) {
putDataChangedLock();
return false;
}
putDataChangedLock();
- int lvPos = dta[category].d[index].listViewPos;
+ int lvPos = dti.dta[category].d[index].listViewPos;
// delete entry
- dta[category].d.erase(dta[category].d.begin() + index);
+ 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 (dta[category].d[i].listViewPos > lvPos)
- --dta[category].d[i].listViewPos;
+ 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 (dta[oldCategory].name != newCategory.latin1()) {
+ 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 = dta[oldCategory].d[index].rev + 1; // increment revision counter.
- dta[oldCategory].d[index] = *d;
+ d->rev = dti.dta[oldCategory].d[index].rev + 1; // increment revision counter.
+ dti.dta[oldCategory].d[index] = *d;
}
flagDirty();
return true;
}
unsigned int PwMDoc::numEntries(const QString &category)
{
unsigned int cat = 0;
if (!findCategory(category, &cat)) {
BUG();
return 0;
}
return numEntries(cat);
}
bool PwMDoc::serializeDta(string *d)
{
PWM_ASSERT(d);
Serializer ser;
- if (!ser.serialize(dta))
+ if (!ser.serialize(dti))
return false;
d->assign(ser.getXml());
if (!d->size())
return false;
return true;
}
bool PwMDoc::deSerializeDta(const string *d, bool entriesLocked)
{
PWM_ASSERT(d);
#ifndef PWM_EMBEDDED
try {
Serializer ser(d->c_str());
ser.setDefaultLockStat(entriesLocked);
- if (!ser.deSerialize(&dta))
+ if (!ser.deSerialize(&dti))
return false;
} catch (PwMException) {
return false;
}
#else
Serializer ser(d->c_str());
ser.setDefaultLockStat(entriesLocked);
- if (!ser.deSerialize(&dta))
+ if (!ser.deSerialize(&dti))
return false;
#endif
emitDataChanged(this);
return true;
}
bool PwMDoc::getEntry(const QString &category, unsigned int index,
PwMDataItem * d, bool unlockIfLocked)
{
PWM_ASSERT(d);
unsigned int cat = 0;
if (!findCategory(category, &cat)) {
BUG();
return false;
}
return getEntry(cat, index, d, unlockIfLocked);
}
bool PwMDoc::getEntry(unsigned int category, unsigned int index,
PwMDataItem *d, bool unlockIfLocked)
{
- if (index > dta[category].d.size() - 1)
+ if (index > dti.dta[category].d.size() - 1)
return false;
bool locked = isLocked(category, index);
if (locked) {
/* this entry is locked. We don't return a password,
* until it's unlocked by the user by inserting
* chipcard or entering the mpw
*/
if (unlockIfLocked) {
if (!lockAt(category, index, false)) {
return false;
}
locked = false;
}
}
- *d = dta[category].d[index];
+ *d = dti.dta[category].d[index];
if (locked)
d->pw = LOCKED_STRING.latin1();
return true;
}
PwMerror PwMDoc::getCommentByLvp(const QString &category, int listViewPos,
string *foundComment)
{
PWM_ASSERT(foundComment);
unsigned int cat = 0;
if (!findCategory(category, &cat))
return e_invalidArg;
unsigned int i, entries = numEntries(cat);
for (i = 0; i < entries; ++i) {
- if (dta[cat].d[i].listViewPos == listViewPos) {
- *foundComment = dta[cat].d[i].comment;
- if (dta[cat].d[i].binary)
+ if (dti.dta[cat].d[i].listViewPos == listViewPos) {
+ *foundComment = dti.dta[cat].d[i].comment;
+ if (dti.dta[cat].d[i].binary)
return e_binEntry;
return e_normalEntry;
}
}
BUG();
return e_generic;
}
bool PwMDoc::compressDta(string *d, char algo)
{
PWM_ASSERT(d);
switch (algo) {
case PWM_COMPRESS_GZIP: {
CompressGzip comp;
return comp.compress(d);
} case PWM_COMPRESS_BZIP2: {
CompressBzip2 comp;
return comp.compress(d);
} case PWM_COMPRESS_NONE: {
return true;
} default: {
BUG();
}
}
return false;
}
bool PwMDoc::decompressDta(string *d, char algo)
{
PWM_ASSERT(d);
switch (algo) {
case PWM_COMPRESS_GZIP: {
CompressGzip comp;
return comp.decompress(d);
} case PWM_COMPRESS_BZIP2: {
CompressBzip2 comp;
return comp.decompress(d);
} case PWM_COMPRESS_NONE: {
return true;
}
}
return false;
}
PwMerror PwMDoc::encrypt(string *d, const QString *pw, QFile *f, char algo)
{
PWM_ASSERT(d);
PWM_ASSERT(pw);
@@ -1445,1027 +1449,1027 @@ PwMerror PwMDoc::checkDataHash(char dataHashType, const string *dataHash,
hash.sha1_write((byte*)dataStream->c_str(), dataStream->length());
string ret = hash.sha1_read();
if (ret != *dataHash)
return e_fileCorrupt;
break;
}
#ifndef PWM_EMBEDDED
case PWM_HASH_SHA256:
/*... fall through */
case PWM_HASH_SHA384:
case PWM_HASH_SHA512:
case PWM_HASH_MD5:
case PWM_HASH_RMD160:
case PWM_HASH_TIGER: {
if (!LibGCryptIf::available())
return e_hashNotImpl;
LibGCryptIf gc;
PwMerror err;
unsigned char *buf;
size_t hashLen;
err = gc.hash(&buf,
&hashLen,
reinterpret_cast<const unsigned char *>(dataStream->c_str()),
dataStream->length(),
dataHashType);
if (err != e_success)
return e_hashNotImpl;
string calcHash(reinterpret_cast<const char *>(buf),
static_cast<string::size_type>(hashLen));
delete [] buf;
if (calcHash != *dataHash)
return e_fileCorrupt;
break;
}
#endif
default:
return e_hashNotImpl;
}
return e_success;
}
bool PwMDoc::lockAt(unsigned int category, unsigned int index,
bool lock)
{
if (index >= numEntries(category)) {
BUG();
return false;
}
- if (lock == dta[category].d[index].lockStat)
+ if (lock == dti.dta[category].d[index].lockStat)
return true;
if (!lock && currentPw != "") {
// "unlocking" and "password is already set"
if (!getDocStatFlag(DOC_STAT_UNLOCK_WITHOUT_PW)) {
// unlocking without pw not allowed
QString pw;
pw = requestMpw(getDocStatFlag(DOC_STAT_USE_CHIPCARD));
if (pw != "") {
if (pw != currentPw) {
wrongMpwMsgBox(getDocStatFlag(DOC_STAT_USE_CHIPCARD));
return false;
} else {
timer()->start(DocTimer::id_mpwTimer);
}
} else {
return false;
}
} else {
timer()->start(DocTimer::id_mpwTimer);
}
}
- dta[category].d[index].lockStat = lock;
- dta[category].d[index].rev++; // increment revision counter.
+ dti.dta[category].d[index].lockStat = lock;
+ dti.dta[category].d[index].rev++; // increment revision counter.
emitDataChanged(this);
if (!lock)
timer()->start(DocTimer::id_autoLockTimer);
return true;
}
bool PwMDoc::lockAt(const QString &category,unsigned int index,
bool lock)
{
unsigned int cat = 0;
if (!findCategory(category, &cat)) {
BUG();
return false;
}
return lockAt(cat, index, lock);
}
bool PwMDoc::lockAll(bool lock)
{
if (!lock && isDeepLocked()) {
PwMerror ret;
ret = deepLock(false);
if (ret != e_success)
return false;
return true;
}
if (isDocEmpty()) {
return true;
}
if (!lock && currentPw != "") {
// unlocking and password is already set
if (!getDocStatFlag(DOC_STAT_UNLOCK_WITHOUT_PW)) {
// unlocking without pw not allowed
QString pw;
pw = requestMpw(getDocStatFlag(DOC_STAT_USE_CHIPCARD));
if (pw != "") {
if (pw != currentPw) {
wrongMpwMsgBox(getDocStatFlag(DOC_STAT_USE_CHIPCARD));
return false;
} else {
timer()->start(DocTimer::id_mpwTimer);
}
} else {
return false;
}
} else {
timer()->start(DocTimer::id_mpwTimer);
}
}
- vector<PwMCategoryItem>::iterator catBegin = dta.begin(),
- catEnd = dta.end(),
+ 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 = dta.begin(),
- catEnd = dta.end(),
+ 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 = dta.begin(),
- catEnd = dta.end(),
+ 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 = dta.begin(),
- catEnd = dta.end(),
+ 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;
if (lock) {
if (isDeepLocked())
return e_lock;
if (saveToFile) {
if (isDocEmpty())
return e_docIsEmpty;
ret = saveDoc(conf()->confGlobCompression());
if (ret == e_filename) {
/* the doc wasn't saved to a file
* by the user, yet.
*/
cantDeeplock_notSavedMsgBox();
return e_docNotSaved;
} else if (ret != e_success) {
return e_lock;
}
}
timer()->stop(DocTimer::id_autoLockTimer);
clearDoc();
PwMDataItem d;
d.desc = IS_DEEPLOCKED_SHORTMSG.latin1();
d.comment = IS_DEEPLOCKED_MSG.latin1();
d.listViewPos = 0;
addEntry(DEFAULT_CATEGORY, &d, true);
lockAt(DEFAULT_CATEGORY, 0, true);
unsetDocStatFlag(DOC_STAT_DISK_DIRTY);
setDocStatFlag(DOC_STAT_DEEPLOCKED);
} else {
if (!isDeepLocked())
return e_lock;
ret = openDoc(&filename, (conf()->confGlobUnlockOnOpen())
? 0 : 1);
if (ret == e_wrongPw) {
return e_wrongPw;
} else if (ret != e_success) {
printDebug(string("PwMDoc::deepLock(false): ERR! openDoc() == ")
+ tostr(static_cast<int>(ret)));
return e_lock;
}
unsetDocStatFlag(DOC_STAT_DEEPLOCKED);
timer()->start(DocTimer::id_autoLockTimer);
}
emitDataChanged(this);
return e_success;
}
void PwMDoc::_deepUnlock()
{
deepLock(false);
}
void PwMDoc::clearDoc()
{
- dta.clear();
+ dti.clear();
PwMCategoryItem d;
d.name = DEFAULT_CATEGORY.latin1();
- dta.push_back(d);
+ 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)
{
- dta[category].d[index].listViewPos = 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 dta[cat].d[index].listViewPos;
+ 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, dta[category].d[i].desc,
+ if (!compareString(find.desc, dti.dta[category].d[i].desc,
caseSensitive, exactWordMatch)) {
continue;
}
}
if (searchIn & SEARCH_IN_NAME) {
- if (!compareString(find.name, dta[category].d[i].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, dta[category].d[i].pw,
+ 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, dta[category].d[i].comment,
+ if (!compareString(find.comment, dti.dta[category].d[i].comment,
caseSensitive, exactWordMatch)) {
continue;
}
}
if (searchIn & SEARCH_IN_URL) {
- if (!compareString(find.url, dta[category].d[i].url,
+ if (!compareString(find.url, dti.dta[category].d[i].url,
caseSensitive, exactWordMatch)) {
continue;
}
}
if (searchIn & SEARCH_IN_LAUNCHER) {
- if (!compareString(find.launcher, dta[category].d[i].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 = dta[category].d[(*foundPositions)[i]].listViewPos;
+ 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 = dta.begin(),
- end = dta.end();
+ vector<PwMCategoryItem>::iterator i = dti.dta.begin(),
+ end = dti.dta.end();
while (i != end) {
if ((*i).name == name.latin1()) {
if (index) {
- *index = i - dta.begin();
+ *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;
- dta[category].name = newName.latin1();
+ dti.dta[category].name = newName.latin1();
if (!dontFlagDirty)
flagDirty();
return true;
}
bool PwMDoc::delCategory(const QString &category)
{
unsigned int cat = 0;
if (!findCategory(category, &cat))
return false;
return delCategory(cat);
}
bool PwMDoc::delCategory(unsigned int category, bool dontFlagDirty)
{
if (category > numCategories() - 1)
return false;
// We don't delete it, if it is the last existing
// category! Instead we rename it to "Default".
if (numCategories() > 1) {
- dta.erase(dta.begin() + category);
+ dti.dta.erase(dti.dta.begin() + category);
} else {
renameCategory(category, DEFAULT_CATEGORY, dontFlagDirty);
return true;
}
if (!dontFlagDirty)
flagDirty();
return true;
}
void PwMDoc::delAllEmptyCat(bool dontFlagDirty)
{
- vector<PwMCategoryItem>::iterator begin = dta.begin(),
- end = dta.end(),
+ vector<PwMCategoryItem>::iterator begin = dti.dta.begin(),
+ end = dti.dta.end(),
i = begin;
while (i != end) {
if (i->d.empty()) {
delCategory(begin - i, dontFlagDirty);
}
++i;
}
}
void PwMDoc::getCategoryList(vector<string> *list)
{
PWM_ASSERT(list);
list->clear();
- vector<PwMCategoryItem>::iterator i = dta.begin(),
- end = dta.end();
+ vector<PwMCategoryItem>::iterator i = dti.dta.begin(),
+ end = dti.dta.end();
while (i != end) {
list->push_back(i->name);
++i;
}
}
void PwMDoc::getCategoryList(QStringList *list)
{
PWM_ASSERT(list);
list->clear();
- vector<PwMCategoryItem>::iterator i = dta.begin(),
- end = dta.end();
+ vector<PwMCategoryItem>::iterator i = dti.dta.begin(),
+ end = dti.dta.end();
while (i != end) {
#ifndef PWM_EMBEDDED
list->push_back(i->name.c_str());
#else
list->append(i->name.c_str());
#endif
++i;
}
}
void PwMDoc::getEntryList(const QString &category, QStringList *list)
{
PWM_ASSERT(list);
unsigned int cat = 0;
if (!findCategory(category, &cat)) {
list->clear();
return;
}
getEntryList(cat, list);
}
void PwMDoc::getEntryList(const QString &category, vector<string> *list)
{
PWM_ASSERT(list);
unsigned int cat = 0;
if (!findCategory(category, &cat)) {
list->clear();
return;
}
getEntryList(cat, list);
}
void PwMDoc::getEntryList(unsigned int category, vector<string> *list)
{
PWM_ASSERT(list);
list->clear();
- vector<PwMDataItem>::iterator begin = dta[category].d.begin(),
- end = dta[category].d.end(),
+ vector<PwMDataItem>::iterator begin = dti.dta[category].d.begin(),
+ end = dti.dta[category].d.end(),
i = begin;
while (i != end) {
list->push_back(i->desc);
++i;
}
}
void PwMDoc::getEntryList(unsigned int category, QStringList *list)
{
PWM_ASSERT(list);
list->clear();
- vector<PwMDataItem>::iterator begin = dta[category].d.begin(),
- end = dta[category].d.end(),
+ vector<PwMDataItem>::iterator begin = dti.dta[category].d.begin(),
+ end = dti.dta[category].d.end(),
i = begin;
while (i != end) {
#ifndef PWM_EMBEDDED
list->push_back(i->desc.c_str());
#else
list->append(i->desc.c_str());
#endif
++i;
}
}
bool PwMDoc::execLauncher(const QString &category, unsigned int entryIndex)
{
unsigned int cat = 0;
if (!findCategory(category, &cat))
return false;
return execLauncher(cat, entryIndex);
}
bool PwMDoc::execLauncher(unsigned int category, unsigned int entryIndex)
{
if (geteuid() == 0) {
rootAlertMsgBox();
return false;
}
- QString command(dta[category].d[entryIndex].launcher.c_str());
+ QString command(dti.dta[category].d[entryIndex].launcher.c_str());
bool wasLocked = isLocked(category, entryIndex);
if (command.find("$p") != -1) {
/* the user requested the password to be included
* into the command. We have to ask for the password,
* if it's locked. We do that by unlocking the entry
*/
if (!lockAt(category, entryIndex, false))
return false;
}
#ifndef PWM_EMBEDDED
- command.replace("$d", dta[category].d[entryIndex].desc.c_str());
- command.replace("$n", dta[category].d[entryIndex].name.c_str());
- command.replace("$p", dta[category].d[entryIndex].pw.c_str());
- command.replace("$u", dta[category].d[entryIndex].url.c_str());
- command.replace("$c", dta[category].d[entryIndex].comment.c_str());
+ command.replace("$d", dti.dta[category].d[entryIndex].desc.c_str());
+ command.replace("$n", dti.dta[category].d[entryIndex].name.c_str());
+ command.replace("$p", dti.dta[category].d[entryIndex].pw.c_str());
+ command.replace("$u", dti.dta[category].d[entryIndex].url.c_str());
+ command.replace("$c", dti.dta[category].d[entryIndex].comment.c_str());
#else
- command.replace(QRegExp("$d"), dta[category].d[entryIndex].desc.c_str());
- command.replace(QRegExp("$n"), dta[category].d[entryIndex].name.c_str());
- command.replace(QRegExp("$p"), dta[category].d[entryIndex].pw.c_str());
- command.replace(QRegExp("$u"), dta[category].d[entryIndex].url.c_str());
- command.replace(QRegExp("$c"), dta[category].d[entryIndex].comment.c_str());
+ command.replace(QRegExp("$d"), dti.dta[category].d[entryIndex].desc.c_str());
+ command.replace(QRegExp("$n"), dti.dta[category].d[entryIndex].name.c_str());
+ command.replace(QRegExp("$p"), dti.dta[category].d[entryIndex].pw.c_str());
+ command.replace(QRegExp("$u"), dti.dta[category].d[entryIndex].url.c_str());
+ command.replace(QRegExp("$c"), dti.dta[category].d[entryIndex].comment.c_str());
#endif
command.append(" &");
QString customXterm(conf()->confGlobXtermCommand());
if (!customXterm.isEmpty())
command = customXterm + " " + command;
system(command.latin1());
lockAt(category, entryIndex, wasLocked);
return true;
}
bool PwMDoc::goToURL(const QString &category, unsigned int entryIndex)
{
unsigned int cat = 0;
if (!findCategory(category, &cat))
return false;
return goToURL(cat, entryIndex);
}
bool PwMDoc::goToURL(unsigned int category, unsigned int entryIndex)
{
if (geteuid() == 0) {
rootAlertMsgBox();
return false;
}
- QString url(dta[category].d[entryIndex].url.c_str());
+ QString url(dti.dta[category].d[entryIndex].url.c_str());
if (url.isEmpty())
return false;
QString customBrowser(conf()->confGlobBrowserCommand());
if (!customBrowser.isEmpty()) {
browserProc.clearArguments();
browserProc << customBrowser << url;
if (browserProc.start(KProcess::DontCare))
return true;
}
browserProc.clearArguments();
browserProc << "konqueror" << url;
if (browserProc.start(KProcess::DontCare))
return true;
browserProc.clearArguments();
browserProc << "mozilla" << url;
if (browserProc.start(KProcess::DontCare))
return true;
browserProc.clearArguments();
browserProc << "opera" << url;
if (browserProc.start(KProcess::DontCare))
return true;
return false;
}
PwMerror PwMDoc::exportToText(const QString *file)
{
PWM_ASSERT(file);
if (QFile::exists(*file)) {
if (!QFile::remove(*file))
return e_accessFile;
}
QFile f(*file);
if (!f.open(IO_ReadWrite))
return e_openFile;
if (!unlockAll_tempoary()) {
f.close();
return e_lock;
}
// write header
string header = i18n("Password table generated by\nPwM v").latin1();
header += PACKAGE_VER;
header += i18n("\non ").latin1();
QDate currDate = QDate::currentDate();
QTime currTime = QTime::currentTime();
#ifndef PWM_EMBEDDED
header += currDate.toString("ddd MMMM d ").latin1();
header += currTime.toString("hh:mm:ss ").latin1();
#else
QString dfs = KGlobal::locale()->dateFormatShort();
bool ampm = KGlobal::locale()->use12Clock();
KGlobal::locale()->setDateFormatShort("%A %B %d");
KGlobal::locale()->setHore24Format(true);
header += KGlobal::locale()->formatDate(currDate, true, KLocale::Userdefined);
header += KGlobal::locale()->formatTime(currTime, true);
KGlobal::locale()->setDateFormatShort(dfs);
KGlobal::locale()->setHore24Format(!ampm);
#endif
header += tostr(currDate.year());
header += "\n==============================\n\n";
#ifndef PWM_EMBEDDED
if (f.writeBlock(header.c_str(), header.length()) != (Q_LONG)header.length()) {
unlockAll_tempoary(true);
f.close();
return e_writeFile;
}
#else
if (f.writeBlock(header.c_str(), header.length()) != (long)header.length()) {
unlockAll_tempoary(true);
f.close();
return e_writeFile;
}
#endif
unsigned int i, numCat = numCategories();
unsigned int j, numEnt;
string exp;
for (i = 0; i < numCat; ++i) {
numEnt = numEntries(i);
exp = "\n== Category: ";
- exp += dta[i].name;
+ exp += dti.dta[i].name;
exp += " ==\n";
#ifndef PWM_EMBEDDED
if (f.writeBlock(exp.c_str(), exp.length()) != (Q_LONG)exp.length()) {
unlockAll_tempoary(true);
f.close();
return e_writeFile;
}
#else
if (f.writeBlock(exp.c_str(), exp.length()) != (long)exp.length()) {
unlockAll_tempoary(true);
f.close();
return e_writeFile;
}
#endif
for (j = 0; j < numEnt; ++j) {
exp = "\n-- ";
- exp += dta[i].d[j].desc;
+ exp += dti.dta[i].d[j].desc;
exp += " --\n";
exp += i18n("Username: ").latin1();
- exp += dta[i].d[j].name;
+ exp += dti.dta[i].d[j].name;
exp += "\n";
exp += i18n("Password: ").latin1();
- exp += dta[i].d[j].pw;
+ exp += dti.dta[i].d[j].pw;
exp += "\n";
exp += i18n("Comment: ").latin1();
- exp += dta[i].d[j].comment;
+ exp += dti.dta[i].d[j].comment;
exp += "\n";
exp += i18n("URL: ").latin1();
- exp += dta[i].d[j].url;
+ exp += dti.dta[i].d[j].url;
exp += "\n";
exp += i18n("Launcher: ").latin1();
- exp += dta[i].d[j].launcher;
+ exp += dti.dta[i].d[j].launcher;
exp += "\n";
#ifndef PWM_EMBEDDED
if (f.writeBlock(exp.c_str(), exp.length()) != (Q_LONG)exp.length()) {
unlockAll_tempoary(true);
f.close();
return e_writeFile;
}
#else
if (f.writeBlock(exp.c_str(), exp.length()) != (long)exp.length()) {
unlockAll_tempoary(true);
f.close();
return e_writeFile;
}
#endif
}
}
unlockAll_tempoary(true);
f.close();
return e_success;
}
PwMerror PwMDoc::importFromText(const QString *file, int format)
{
PWM_ASSERT(file);
if (format == 0)
return importText_PwM(file);
else if (format == -1) {
// probe for all formats
if (importText_PwM(file) == e_success)
return e_success;
- dta.clear();
+ dti.clear();
emitDataChanged(this);
// add next format here...
return e_fileFormat;
}
return e_invalidArg;
}
PwMerror PwMDoc::importText_PwM(const QString *file)
{
PWM_ASSERT(file);
FILE *f;
int tmp;
ssize_t ret;
string curCat;
unsigned int entriesRead = 0;
PwMDataItem currItem;
f = fopen(file->latin1(), "r");
if (!f)
return e_openFile;
size_t ch_tmp_size = 1024;
char *ch_tmp = (char*)malloc(ch_tmp_size);
if (!ch_tmp) {
fclose(f);
return e_outOfMem;
}
// - check header
if (getline(&ch_tmp, &ch_tmp_size, f) == -1) // skip first line.
goto formatError;
// check version-string and return version in "ch_tmp".
if (fscanf(f, "PwM v%s", ch_tmp) != 1) {
// header not recognized as PwM generated header
goto formatError;
}
// set filepointer behind version-string-line previously checked
if (getline(&ch_tmp, &ch_tmp_size, f) == -1)
goto formatError;
// skip next line containing the build-date
if (getline(&ch_tmp, &ch_tmp_size, f) == -1)
goto formatError;
// read header termination line
if (getline(&ch_tmp, &ch_tmp_size, f) == -1)
goto formatError;
if (strcmp(ch_tmp, "==============================\n"))
goto formatError;
// - read entries
do {
@@ -2569,310 +2573,696 @@ bool PwMDoc::textExtractEntry_PwM(const char *in, ssize_t in_size, string *out)
ssize_t i = 0, len = in_size - 1;
while (i < len) {
if (in[i] == ':')
break;
++i;
}
i += 2;
*out = "";
out->append(in + i, in_size - i - 1);
return true;
}
PwMerror PwMDoc::exportToGpasman(const QString *file)
{
PWM_ASSERT(file);
GpasmanFile gp;
int ret;
if (!unlockAll_tempoary())
return e_lock;
QString gpmPassword;
while (1) {
gpmPassword = requestNewMpw(0);
if (gpmPassword == "") {
unlockAll_tempoary(true);
return e_noPw;
}
if (gpmPassword.length() < 4) {
gpmPwLenErrMsgBox();
} else {
break;
}
}
ret = gp.save_init(file->latin1(), gpmPassword.latin1());
if (ret != 1) {
unlockAll_tempoary(true);
return e_accessFile;
}
char *entry[4];
unsigned int numCat = numCategories(), i;
unsigned int numEntr, j;
int descLen, nameLen, pwLen, commentLen;
for (i = 0; i < numCat; ++i) {
numEntr = numEntries(i);
for (j = 0; j < numEntr; ++j) {
- descLen = dta[i].d[j].desc.length();
- nameLen = dta[i].d[j].name.length();
- pwLen = dta[i].d[j].pw.length();
- commentLen = dta[i].d[j].comment.length();
+ descLen = dti.dta[i].d[j].desc.length();
+ nameLen = dti.dta[i].d[j].name.length();
+ pwLen = dti.dta[i].d[j].pw.length();
+ commentLen = dti.dta[i].d[j].comment.length();
entry[0] = new char[descLen + 1];
entry[1] = new char[nameLen + 1];
entry[2] = new char[pwLen + 1];
entry[3] = new char[commentLen + 1];
- strcpy(entry[0], descLen == 0 ? " " : dta[i].d[j].desc.c_str());
- strcpy(entry[1], nameLen == 0 ? " " : dta[i].d[j].name.c_str());
- strcpy(entry[2], pwLen == 0 ? " " : dta[i].d[j].pw.c_str());
- strcpy(entry[3], commentLen == 0 ? " " : dta[i].d[j].comment.c_str());
+ strcpy(entry[0], descLen == 0 ? " " : dti.dta[i].d[j].desc.c_str());
+ strcpy(entry[1], nameLen == 0 ? " " : dti.dta[i].d[j].name.c_str());
+ strcpy(entry[2], pwLen == 0 ? " " : dti.dta[i].d[j].pw.c_str());
+ strcpy(entry[3], commentLen == 0 ? " " : dti.dta[i].d[j].comment.c_str());
entry[0][descLen == 0 ? descLen + 1 : descLen] = '\0';
entry[1][nameLen == 0 ? nameLen + 1 : nameLen] = '\0';
entry[2][pwLen == 0 ? pwLen + 1 : pwLen] = '\0';
entry[3][commentLen == 0 ? commentLen + 1 : commentLen] = '\0';
ret = gp.save_entry(entry);
if (ret == -1){
delete [] entry[0];
delete [] entry[1];
delete [] entry[2];
delete [] entry[3];
gp.save_finalize();
unlockAll_tempoary(true);
return e_writeFile;
}
delete [] entry[0];
delete [] entry[1];
delete [] entry[2];
delete [] entry[3];
}
}
unlockAll_tempoary(true);
if (gp.save_finalize() == -1)
return e_writeFile;
return e_success;
}
PwMerror PwMDoc::importFromGpasman(const QString *file)
{
PWM_ASSERT(file);
QString pw = requestMpw(false);
if (pw == "")
return e_noPw;
GpasmanFile gp;
int ret, i;
PwMerror ret2;
char *entry[4];
PwMDataItem tmpData;
ret = gp.load_init(file->latin1(), pw.latin1());
if (ret != 1)
return e_accessFile;
do {
ret = gp.load_entry(entry);
if(ret != 1)
break;
tmpData.desc = entry[0];
tmpData.name = entry[1];
tmpData.pw = entry[2];
tmpData.comment = entry[3];
tmpData.lockStat = true;
tmpData.listViewPos = -1;
ret2 = addEntry(DEFAULT_CATEGORY, &tmpData, true);
for (i = 0; i < 4; ++i)
free(entry[i]);
if (ret2 == e_maxAllowedEntr) {
gp.load_finalize();
return e_maxAllowedEntr;
}
} while (1);
gp.load_finalize();
if (isDocEmpty())
return e_wrongPw; // we assume this.
flagDirty();
return e_success;
}
void PwMDoc::ensureLvp()
{
if (isDocEmpty())
return;
vector< vector<PwMDataItem>::iterator > undefined;
vector< vector<PwMDataItem>::iterator >::iterator undefBegin,
undefEnd,
undefI;
- vector<PwMCategoryItem>::iterator catBegin = dta.begin(),
- catEnd = dta.end(),
+ vector<PwMCategoryItem>::iterator catBegin = dti.dta.begin(),
+ catEnd = dti.dta.end(),
catI = catBegin;
vector<PwMDataItem>::iterator entrBegin, entrEnd, entrI;
int lvpTop, tmpLvp;
while (catI != catEnd) {
lvpTop = -1;
undefined.clear();
entrBegin = catI->d.begin();
entrEnd = catI->d.end();
entrI = entrBegin;
while (entrI != entrEnd) {
tmpLvp = entrI->listViewPos;
if (tmpLvp == -1)
undefined.push_back(entrI);
else if (tmpLvp > lvpTop)
lvpTop = tmpLvp;
++entrI;
}
undefBegin = undefined.begin();
undefEnd = undefined.end();
undefI = undefBegin;
while (undefI != undefEnd) {
(*undefI)->listViewPos = ++lvpTop;
++undefI;
}
++catI;
}
}
QString PwMDoc::getTitle()
{
/* NOTE: We have to ensure, that the returned title
* is unique and not reused somewhere else while
* this document is valid (open).
*/
QString title(getFilename());
if (title.isEmpty()) {
if (unnamedNum == 0) {
unnamedNum = PwMDocList::getNewUnnamedNumber();
PWM_ASSERT(unnamedNum != 0);
}
title = DEFAULT_TITLE;
title += " ";
title += tostr(unnamedNum).c_str();
}
return title;
}
bool PwMDoc::tryDelete()
{
if (deleted)
return true;
int ret;
if (isDirty()) {
ret = dirtyAskSave(getTitle());
if (ret == 0) { // save to disk
if (!saveDocUi(this))
goto out_ignore;
} else if (ret == 1) { // don't save and delete
goto out_accept;
} else { // cancel operation
goto out_ignore;
}
}
out_accept:
deleted = true;
delete this;
return true;
out_ignore:
return false;
}
#ifdef PWM_EMBEDDED
//US ENH: this is the magic function that syncronizes the this doc with the remote doc
+//US it could have been defined as static, but I did not want to.
PwMerror PwMDoc::syncronize(KSyncManager* manager, PwMDoc* syncLocal , PwMDoc* syncRemote, int mode )
{
- bool syncOK = true;
int addedPasswordsLocal = 0;
int addedPasswordsRemote = 0;
int deletedPasswordsRemote = 0;
int deletedPasswordsLocal = 0;
int changedLocal = 0;
int changedRemote = 0;
+ PwMSyncItem* syncItemLocal;
+ PwMSyncItem* syncItemRemote;
+
QString mCurrentSyncName = manager->getCurrentSyncName();
QString mCurrentSyncDevice = manager->getCurrentSyncDevice();
+ bool fullDateRange = false;
+ int take;
+ // local->resetTempSyncStat();
+ QDateTime mLastSync = QDateTime::currentDateTime();
+ QDateTime modifiedSync = mLastSync;
+
+ unsigned int index;
+ //Step 1. Find syncinfo in Local file and create if not existent.
+ bool found = syncLocal->findSyncData(mCurrentSyncDevice, &index);
+ if (found == false)
+ {
+ PwMSyncItem newSyncItemLocal;
+ newSyncItemLocal.syncName = mCurrentSyncDevice;
+ newSyncItemLocal.lastSyncDate = mLastSync;
+ syncLocal->addSyncDataEntry(&newSyncItemLocal, true);
+ found = syncLocal->findSyncData(mCurrentSyncDevice, &index);
+ if (found == false) {
+ qDebug("PwMDoc::syncronize : newly created local sync data could not be found");
+ return e_syncError;
+ }
+ }
+
+ syncItemLocal = syncLocal->getSyncDataEntry(index);
+ qDebug("Last Sync %s ", syncItemLocal->lastSyncDate.toString().latin1());
+
+ //Step 2. Find syncinfo in remote file and create if not existent.
+ found = syncRemote->findSyncData(mCurrentSyncName, &index);
+ if (found == false)
+ {
+ qDebug("FULLDATE 1");
+ fullDateRange = true;
+ PwMSyncItem newSyncItemRemote;
+ newSyncItemRemote.syncName = mCurrentSyncName;
+ newSyncItemRemote.lastSyncDate = mLastSync;
+ syncRemote->addSyncDataEntry(&newSyncItemRemote, true);
+ found = syncRemote->findSyncData(mCurrentSyncName, &index);
+ if (found == false) {
+ qDebug("PwMDoc::syncronize : newly created remote sync data could not be found");
+ return e_syncError;
+ }
+ }
+
+ syncItemRemote = syncRemote->getSyncDataEntry(index);
+ //and remove the found entry here. We will reenter it later again.
+ syncRemote->delSyncDataEntry(index, true);
+ if ( syncItemLocal->lastSyncDate == mLastSync ) {
+ qDebug("FULLDATE 2");
+ fullDateRange = true;
+ }
+
+ if ( ! fullDateRange ) {
+ if ( syncItemLocal->lastSyncDate != syncItemRemote->lastSyncDate ) {
+
+ // qDebug("set fulldate to true %s %s" ,addresseeLSync->dtStart().toString().latin1(), addresseeRSync->dtStart().toString().latin1() );
+ //qDebug("%d %d %d %d ", addresseeLSync->dtStart().time().second(), addresseeLSync->dtStart().time().msec() , addresseeRSync->dtStart().time().second(), addresseeRSync->dtStart().time().msec());
+ fullDateRange = true;
+ qDebug("FULLDATE 3 %s %s", syncItemLocal->lastSyncDate.toString().latin1() , syncItemRemote->lastSyncDate.toString().latin1() );
+ }
+ }
+ // fullDateRange = true; // debug only!
+ if ( fullDateRange )
+ mLastSync = QDateTime::currentDateTime().addDays( -100*365);
+ else
+ mLastSync = syncItemLocal->lastSyncDate;
+
+
+ qDebug("*************************** ");
+ // qDebug("mLastAddressbookSync %s ",mLastAddressbookSync.toString().latin1() );
+ QStringList er = syncRemote->getIDEntryList();
+ PwMDataItem* inRemote ;//= er.first();
+ PwMDataItem* inLocal;
+ unsigned int catLocal, indexLocal;
+ unsigned int catRemote, indexRemote;
+
+ QString uid;
+ manager->showProgressBar(0, i18n("Syncing - close to abort!"), er.count());
+
+ int modulo = (er.count()/10)+1;
+ unsigned int incCounter = 0;
+ while ( incCounter < er.count()) {
+ if (manager->isProgressBarCanceled())
+ return e_syncError;
+ if ( incCounter % modulo == 0 )
+ manager->showProgressBar(incCounter);
+
+ uid = er[ incCounter ];
+ qApp->processEvents();
+
+ inLocal = syncLocal->findEntryByID( uid, &catLocal, &indexLocal );
+ inRemote = syncRemote->findEntryByID( uid, &catRemote, &indexRemote );
+ if ( inLocal != 0 ) { // maybe conflict - same uid in both files
+ if ( (take = takePwMDataItem( inLocal, inRemote, mLastSync, mode, fullDateRange) ) ) {
+ //qDebug("take %d %s ", take, inL.summary().latin1());
+ if ( take == 3 )
+ return e_syncError;
+ if ( take == 1 ) {// take local
+ //US syncRemote->removeAddressee( inRemote );
+ (*inRemote) = (*inLocal);
+ //US syncRemote->insertAddressee( inRemote , false);
+ ++changedRemote;
+ } else { // take == 2 take remote
+ //US syncLocal->removeAddressee( inLocal );
+ (*inLocal) = (*inRemote);
+ //US syncLocal->insertAddressee( inLocal , false );
+ ++changedLocal;
+ }
+ }
+ } else { // no conflict
+ if ( inRemote->meta.update > mLastSync || mode == 5 ) {
+ inRemote->meta.update = modifiedSync;
+ //US syncRemote->insertAddressee( inRemote, false );
+ //US syncLocal->insertAddressee( inRemote, false );
+ syncLocal->addEntry("newcategory", inRemote, true, false);
+
+ ++addedPasswordsLocal;
+ } else {
+ // pending checkExternSyncAddressee(addresseeRSyncSharp, inR);
+ syncRemote->delEntry(catRemote, indexRemote, true);
+ //USsyncRemote->removeAddressee( inRemote );
+ ++deletedPasswordsRemote;
+ }
+ }
+
+ ++incCounter;
+ }
+ er.clear();
+ QStringList el = syncLocal->getIDEntryList();
+ modulo = (el.count()/10)+1;
+
+ manager->showProgressBar(0, i18n("Add / remove addressees"), el.count());
+ incCounter = 0;
+ while ( incCounter < el.count()) {
+ qApp->processEvents();
+ if (manager->isProgressBarCanceled())
+ return e_syncError;
+ if ( incCounter % modulo == 0 )
+ manager->showProgressBar(incCounter);
+ uid = el[ incCounter ];
+
+ inLocal = syncLocal->findEntryByID( uid, &catLocal, &indexLocal );
+ inRemote = syncRemote->findEntryByID( uid, &catRemote, &indexRemote );
+ if ( inRemote == 0 ) {
+ if ( inLocal->meta.update < mLastSync && mode != 4 ) {
+ // pending checkExternSyncAddressee(addresseeLSyncSharp, inL);
+ syncLocal->delEntry(catLocal, indexLocal, true);
+ //USsyncLocal->removeAddressee( inLocal );
+ ++deletedPasswordsLocal;
+ } else {
+ if ( ! PWMPrefs::instance()->mWriteBackExistingOnly ) {
+ ++addedPasswordsRemote;
+ inLocal->meta.update = modifiedSync;
+ //USsyncLocal->insertAddressee( inLocal, false );
+ (*inRemote) = (*inLocal);
+ //USsyncRemote->insertAddressee( inRemote, false );
+ syncRemote->addEntry("newcategory", inRemote, true, false);
+
+ }
+ }
+
+ }
+ ++incCounter;
+ }
+ el.clear();
+ manager->hideProgressBar();
+
+ // Now write the info back into the sync data space of the files
+ mLastSync = QDateTime::currentDateTime().addSecs( 1 );
+ // get rid of micro seconds
+ QTime t = mLastSync.time();
+ mLastSync.setTime( QTime (t.hour (), t.minute (), t.second () ) );
+
+ syncItemLocal->lastSyncDate = mLastSync;
+ syncItemRemote->lastSyncDate = mLastSync;
+ // addresseeRSync.setRole( i18n("!Remote from: ")+mCurrentSyncName ) ;
+ // addresseeLSync.setRole(i18n("!Local from: ") + mCurrentSyncName );
+ syncRemote->addSyncDataEntry( syncItemRemote, false );
+ syncLocal->addSyncDataEntry( syncItemLocal, false );
+ QString mes;
+ mes .sprintf( i18n("Synchronization summary:\n\n %d items added to local\n %d items added to remote\n %d items updated on local\n %d items updated on remote\n %d items deleted on local\n %d items deleted on remote\n"),addedPasswordsLocal, addedPasswordsRemote, changedLocal, changedRemote, deletedPasswordsLocal, deletedPasswordsRemote );
+ if ( PWMPrefs::instance()->mShowSyncSummary ) {
+ KMessageBox::information(0, mes, i18n("PWM/Pi Synchronization") );
+ }
+ qDebug( mes );
return e_success;
}
+int PwMDoc::takePwMDataItem( PwMDataItem* local, PwMDataItem* remote, QDateTime lastSync, int mode , bool full )
+{
+ // 0 equal
+ // 1 take local
+ // 2 take remote
+ // 3 cancel
+ QDateTime localMod = local->meta.update;
+ QDateTime remoteMod = remote->meta.update;
+
+ //US QString mCurrentSyncDevice = syncManager->getCurrentSyncDevice();
+
+ if ( localMod == remoteMod )
+ return 0;
+
+ qDebug(" %d %d conflict on %s %s ", mode, full, local->desc.c_str(), remote->desc.c_str() );
+
+ //qDebug("%s %d %s %d", local->lastModified().toString().latin1() , localMod, remote->lastModified().toString().latin1(), remoteMod);
+ //qDebug("%d %d %d %d ", local->lastModified().time().second(), local->lastModified().time().msec(), remote->lastModified().time().second(), remote->lastModified().time().msec() );
+ //full = true; //debug only
+ if ( full ) {
+ bool equ = true;//US ( (*local) == (*remote) );
+ if ( equ ) {
+ //qDebug("equal ");
+ if ( mode < SYNC_PREF_FORCE_LOCAL )
+ return 0;
+
+ }//else //debug only
+ //qDebug("not equal %s %s ", local->summary().latin1(), remote->summary().latin1());
+ }
+
+ int result;
+ bool localIsNew;
+ //qDebug("%s -- %s mLastCalendarSync %s lastsync %s --- local %s remote %s ",local->summary().latin1(), remote->summary().latin1(),mLastCalendarSync.toString().latin1() ,lastSync.toString().latin1() , local->lastModified().toString().latin1() , remote->lastModified().toString().latin1() );
+
+ if ( full && mode < SYNC_PREF_NEWEST )
+ mode = SYNC_PREF_ASK;
+
+ switch( mode ) {
+ case SYNC_PREF_LOCAL:
+ if ( lastSync > remoteMod )
+ return 1;
+ if ( lastSync > localMod )
+ return 2;
+ return 1;
+ break;
+ case SYNC_PREF_REMOTE:
+ if ( lastSync > remoteMod )
+ return 1;
+ if ( lastSync > localMod )
+ return 2;
+ return 2;
+ break;
+ case SYNC_PREF_NEWEST:
+ if ( localMod > remoteMod )
+ return 1;
+ else
+ return 2;
+ break;
+ case SYNC_PREF_ASK:
+ //qDebug("lsy %s --- lo %s --- re %s ", lastSync.toString().latin1(), localMod.toString().latin1(), remoteMod.toString().latin1() );
+ if ( lastSync > remoteMod )
+ return 1;
+ if ( lastSync > localMod )
+ return 2;
+ localIsNew = localMod >= remoteMod;
+ //qDebug("conflict! ************************************** ");
+ {
+ PwMDataItemChooser acd ( *local,*remote, localIsNew , 0/*this*/ );
+ result = acd.executeD(localIsNew);
+ return result;
+ }
+ break;
+ case SYNC_PREF_FORCE_LOCAL:
+ return 1;
+ break;
+ case SYNC_PREF_FORCE_REMOTE:
+ return 2;
+ break;
+
+ default:
+ // SYNC_PREF_TAKE_BOTH not implemented
+ break;
+ }
+ return 0;
+}
+
+
+
//this are the overwritten callbackmethods from the syncinterface
bool PwMDoc::sync(KSyncManager* manager, QString filename, int mode)
{
QString mCurrentSyncDevice = manager->getCurrentSyncDevice();
// construct on the stack = automatic cleanup.
PwMDoc syncTarget(this, "synctarget");
PwMerror err = syncTarget.openDoc(&filename, 2 /*== deeplocked*/);
if (err != e_success)
return false;
qDebug("PWM file loaded %s,sync mode %d",filename.latin1(), mode );
err = syncronize(manager, this, &syncTarget, mode );
if (err == e_success) {
if ( PWMPrefs::instance()->mWriteBackFile ) {
qDebug("Saving remote PWManager file");
err = syncTarget.saveDoc(conf()->confGlobCompression());
if (err != e_success)
return false;
}
flagDirty();
return true;
}
else {
return false;
}
}
//called by the syncmanager to indicate that the work has to marked as dirty.
void PwMDoc::sync_setModified()
{
flagDirty();
}
//called by the syncmanager to ask if the dirty flag is set.
bool PwMDoc::sync_isModified()
{
return isDirty();
}
//called by the syncmanager to indicate that the work has to be saved.
void PwMDoc::sync_save()
{
- PwMerror ret = saveDoc(conf()->confGlobCompression());
+ saveDoc(conf()->confGlobCompression());
}
-
#endif
+bool PwMDoc::findSyncData(const QString &syncname, unsigned int *index)
+{
+ vector<PwMSyncItem>::iterator i = dti.syncDta.begin(),
+ end = dti.syncDta.end();
+
+ while (i != end) {
+ if ((*i).syncName == syncname.latin1()) {
+ if (index) {
+ *index = i - dti.syncDta.begin();
+ }
+ return true;
+ }
+ ++i;
+ }
+ return false;
+};
+
+/** add new syncdataentry */
+PwMerror PwMDoc::addSyncDataEntry(PwMSyncItem *d, bool dontFlagDirty)
+{
+ PWM_ASSERT(d);
+
+ if (isDeepLocked()) {
+ PwMerror ret;
+ ret = deepLock(false);
+ if (ret != e_success)
+ return e_lock;
+ }
+ unsigned int index;
+
+ const QString tmp = d->syncName.c_str();
+ bool exists = findSyncData(d->syncName.c_str(), &index);
+
+ if (exists == true) {
+ // DOH! We found this entry.
+ return e_entryExists;
+ }
+
+ dti.syncDta.push_back(*d);
+
+ if (!dontFlagDirty)
+ flagDirty();
+ return e_success;
+}
+
+
+/** delete syncdata entry */
+bool PwMDoc::delSyncDataEntry(unsigned int index, bool dontFlagDirty)
+{
+ if (isDeepLocked())
+ return false;
+ if (index > dti.syncDta.size() - 1)
+ return false;
+
+ // delete entry
+ dti.syncDta.erase(dti.syncDta.begin() + index);
+
+ if (!dontFlagDirty)
+ flagDirty();
+ return true;
+}
+
+
+PwMDataItem* PwMDoc::findEntryByID(const QString &uid, unsigned int *category, unsigned int *index)
+{
+ vector<PwMCategoryItem>::iterator catcounter = dti.dta.begin(),
+ catend = dti.dta.end();
+
+ vector<PwMDataItem>::iterator entrBegin, entrEnd, entrI;
+
+ while (catcounter != catend) {
+ entrBegin = catcounter->d.begin();
+ entrEnd = catcounter->d.end();
+ entrI = entrBegin;
+ while (entrI != entrEnd) {
+ if ((*entrI).meta.uniqueid == uid.latin1()) {
+ if (category)
+ *category = catcounter - dti.dta.begin();
+ if (index)
+ *index = entrI - entrBegin;
+
+ return &(*entrI);
+ }
+ ++entrI;
+ }
+ ++catcounter;
+ }
+
+ return 0;
+}
+
+QStringList PwMDoc::getIDEntryList()
+{
+ QStringList results;
+
+ vector<PwMCategoryItem>::iterator catcounter = dti.dta.begin(),
+ catend = dti.dta.end();
+
+ vector<PwMDataItem>::iterator entrBegin, entrEnd, entrI;
+
+ while (catcounter != catend) {
+ entrBegin = catcounter->d.begin();
+ entrEnd = catcounter->d.end();
+ entrI = entrBegin;
+ while (entrI != entrEnd) {
+ results.append( (*entrI).meta.uniqueid );
+ ++entrI;
+ }
+ ++catcounter;
+ }
+
+ return results;
+}
#ifndef PWM_EMBEDDED
#include "pwmdoc.moc"
#endif
diff --git a/pwmanager/pwmanager/pwmdoc.h b/pwmanager/pwmanager/pwmdoc.h
index ea4d687..91277f6 100644
--- a/pwmanager/pwmanager/pwmdoc.h
+++ b/pwmanager/pwmanager/pwmdoc.h
@@ -161,112 +161,138 @@ struct PwMDataItem
{ }
/** password description */
string desc;
/** user-name */
string name;
/** the password itself */
string pw;
/** some comment */
string comment;
/** an URL string */
string url;
/** launcher. Can be executed as a system() command */
string launcher;
/** locking status. If locked (true), pw is not emitted through getEntry() */
bool lockStat;
/** position of this item in main "list-view"
* If -1, the position is not yet specified and should be appended to the list
*/
int listViewPos;
/** does this entry contain binary data? */
bool binary;
/** meta data for this data item. */
PwMMetaData meta;
/** data revision counter. This counter can be used
* to easily, efficiently determine if this data item
* has changed since some time.
* This counter is incremented on every update.
*/
unsigned int rev;
void clear(bool clearMeta = true)
{
/* NOTE: Don't use .clear() here to be
* backward compatible with gcc-2 (Debian Woody)
*/
desc = "";
name = "";
pw = "";
comment = "";
url = "";
launcher = "";
lockStat = true;
listViewPos = -1;
binary = false;
if (clearMeta)
meta.clear();
}
+
};
struct PwMCategoryItem
{
/** all PwMDataItems (all passwords) within this category */
vector<PwMDataItem> d;
/** category name/description */
string name;
void clear()
{
d.clear();
name = "";
}
};
+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:
@@ -395,129 +421,130 @@ public:
bool delCategory(const QString &category);
/** delete an existing category */
bool delCategory(unsigned int category, bool dontFlagDirty = false);
/** returns a list of all category-names */
void getCategoryList(vector<string> *list);
/** returns a list of all category-names */
void getCategoryList(QStringList *list);
/** returns a list of all entry-descs in the given category */
void getEntryList(const QString &category, QStringList *list);
/** returns a list of all entry-descs in the given category */
void getEntryList(const QString &category, vector<string> *list);
/** returns a list of all entry-descs in the given category */
void getEntryList(unsigned int category, vector<string> *list);
/** returns a list of all entry-descs in the given category */
void getEntryList(unsigned int category, QStringList *list);
/** delete entry */
bool delEntry(const QString &category, unsigned int index, bool dontFlagDirty = false);
/** delete entry */
bool delEntry(unsigned int category, unsigned int index, bool dontFlagDirty = false);
/** edit entry */
bool editEntry(const QString &oldCategory, const QString &newCategory,
unsigned int index, PwMDataItem *d, bool updateMeta = true);
/** edit entry */
bool editEntry(unsigned int oldCategory, const QString &newCategory,
unsigned int index, PwMDataItem *d, bool updateMeta = true);
/** finds the category with the "name" and return it's index */
bool findCategory(const QString &name, unsigned int *index);
/** search for an entry "find" and check while searching only for
* the data-fields specified by "searchIn". To set the "searchIn"
* value, we may use one or more of the SEARCH_IN_* defines at
* the top of this header-file. It returns the positions of all
* matched entries in "foundPositions". If "breakAfterFound" is true,
* the function terminates after the first occurence of the entry
* and doesn't go on searching. So foundPositions->size() is never
* > 1 if breakAfterFound is true.
*/
void findEntry(unsigned int category, PwMDataItem find, unsigned int searchIn,
vector<unsigned int> *foundPositions, bool breakAfterFound = false,
bool caseSensitive = true, bool exactWordMatch = true,
bool sortByLvp = false);
/** see the above funtion. This function allows to set the category by name. */
void findEntry(const QString &category, PwMDataItem find, unsigned int searchIn,
vector<unsigned int> *foundPositions, bool breakAfterFound = false,
bool caseSensitive = true, bool exactWordMatch = true,
bool sortByLvp = false);
/** returns number of entries */
unsigned int numEntries(const QString &category);
unsigned int numEntries(unsigned int category)
- { return dta[category].d.size(); }
+ { return dti.dta[category].d.size(); }
/** returns number of categories */
unsigned int numCategories()
- { return dta.size(); }
+ { return dti.dta.size(); }
/** returns the name of the category at "index" */
const string* getCategory(unsigned int index)
- { return (&(dta[index].name)); }
+ { return (&(dti.dta[index].name)); }
+
/** returns the data of item at "index".
* It unlocks the entry if it's locked and unlockIfLocked is true.
* If the entry is locked, but unlockIfLocked is false, it'll not return
* the pw.
*/
bool getEntry(const QString &category, unsigned int index,
PwMDataItem *d, bool unlockIfLocked = false);
bool getEntry(unsigned int category, unsigned int index,
PwMDataItem *d, bool unlockIfLocked = false);
/** returns the comment-string by looking at the category
* and the listViewPos
*/
PwMerror getCommentByLvp(const QString &category, int listViewPos,
string *foundComment);
/** checks if a password is already available. (currentPw) */
bool isPwAvailable()
{ return (currentPw != ""); }
/** un/lock entry at "index". If needed, ask for password. */
bool lockAt(const QString &category, unsigned int index,
bool lock = true);
bool lockAt(unsigned int category, unsigned int index,
bool lock = true);
/** returns the lock-status at "index" */
bool isLocked(const QString &category, unsigned int index);
bool isLocked(unsigned int category, unsigned int index)
- { return dta[category].d[index].lockStat; }
+ { return dti.dta[category].d[index].lockStat; }
/** returns the deeplock status */
bool isDeepLocked()
{ return getDocStatFlag(DOC_STAT_DEEPLOCKED); }
/** (un)lock all entries */
bool lockAll(bool lock);
/** unlocks all entries tempoarly.
* 1st NOTE: Be very careful with this function! :)
* 2nd NOTE: After you have called unlockAll_Tempoary(); ,
* please DON'T forget to call unlockAll_Tempoary(true);
* _before_ the user (or someone else) is able to change
* the document!
* 3rd NOTE: Please DON'T change "dta" while the data is tempoary
* unlocked! This will cause corruption.
*/
bool unlockAll_tempoary(bool revert = false);
/** deep-(un)locks the document.
* deep-locking writes all data to the file, deletes all data
* in memory, but doesn't close the document.
* deep-locking is only available, if the user previously saved
* the doc to a file (with a password).
* If "saveToFile" is false, it does NOT write the data to the file!
*/
PwMerror deepLock(bool lock = true, bool saveToFile = true);
/** is unlockable without pw? */
bool unlockWoPw()
{ return getDocStatFlag(DOC_STAT_UNLOCK_WITHOUT_PW); }
/** get the "currentPassword" */
const QString& getCurrentPw()
{ return currentPw; }
/** open a window and request the user to change the mpw */
void changeCurrentPw();
/** set the "listViewPos" variable of "dta" */
void setListViewPos(const QString &category, unsigned int index,
int pos);
/** set the "listViewPos" variable of "dta" */
void setListViewPos(unsigned int category, unsigned int index,
int pos);
/** get the "listViewPos" variable of "dta" */
int getListViewPos(const QString &category, unsigned int index);
/** set the maximum number of entries allowed */
void setMaxNumEntries(unsigned int num = DEFAULT_MAX_ENTRIES)
{ maxEntries = num; }
/** get the maximum number of entries allowed */
unsigned int getMaxNumEntries()
{ return maxEntries; }
/** ensure all listViewPos of all dta items are set. (are ! -1).
* If there are some undefined entries, add them to the end of
* the listViewPos(itions). */
@@ -529,196 +556,223 @@ public:
/** open a browser with the URL-section of the given entry */
bool goToURL(const QString &category, unsigned int entryIndex);
/** see above */
bool goToURL(unsigned int category, unsigned int entryIndex);
/** returns true if there is no entry present in the document.
* Note: The "default" Category is present everytime, so
* it's checked for it's entries.
*/
bool isDocEmpty()
{
if (numCategories() > 1)
return false;
if (numEntries(0))
return false;
return true;
}
/** returns the filename of this doc */
const QString& getFilename()
{ return filename; }
/** returns the title of the doc */
QString getTitle();
/** sets the list-view-pointer hold in the doc */
void setListViewPointer(PwMView *_listView)
{ listView = _listView; }
/** returns the list-view-pointer */
PwMView * getListViewPointer()
{ return listView; }
/** try to delete the doc. The user may be asked to save
* the data. The user may cancel the whole operation.
* false is returned, then.
*/
bool tryDelete();
/** is the doc deleted? (with tryDelete() ) */
bool isDeleted()
{ return deleted; }
/** returns the document timer object */
DocTimer * timer()
{ return _timer; }
/** get a lock on the dataChanged signal.
* If someone is holding a lock, the signal is not emitted.
*/
void getDataChangedLock()
{ ++dataChangedLock; }
/** put the dataChanged lock */
void putDataChangedLock()
{ --dataChangedLock; }
/** returns the revision count of the item at cat/index */
unsigned int getEntryRevCnt(unsigned int category, unsigned int index)
- { return dta[category].d[index].rev; }
+ { return dti.dta[category].d[index].rev; }
/** returns a const pointer to the entries meta */
const PwMMetaData * getEntryMeta(unsigned int category, unsigned int index)
- { return &(dta[category].d[index].meta); }
+ { return &(dti.dta[category].d[index].meta); }
/** is the entry at "category" "index" a binary entry? */
bool isBinEntry(unsigned int category, unsigned int index)
- { return dta[category].d[index].binary; }
+ { return dti.dta[category].d[index].binary; }
public slots:
/** wrapper for PwMTray */
void _deepUnlock();
signals:
/** the data of the document has changed and must be updated
* in all views.
* NOTE: use emitDataChanged(PwMDoc *document) to emit this signal!
*/
void dataChanged(PwMDoc *document);
/** the document class is going to close. This signal may be
* used to nofify all views, that the user closed the document,
* so the views can go down, too.
*/
void docClosed(PwMDoc *document);
/** somebody just opened the document */
void docOpened(PwMDoc *document);
/** this document object just got created */
void docCreated(PwMDoc *document);
public:
/** emit the dataChanged signal after checking for a lock */
void emitDataChanged(PwMDoc *document)
{
if (!dataChangedLock)
emit dataChanged(document);
}
protected:
/** current file for this doc */
QString filename;
+//US ENH: we need a place where we keep the syncentries. So I invented
+// struct PwMItem, that has a vector of PwMCategoryItem and vector of PwMSyncItem
/** holds all data */
- vector<PwMCategoryItem> dta;
+ PwMItem dti;
/** maximum number of entries */
unsigned int maxEntries;
/** currently used password to encrypt data */
QString currentPw;
/** current global document status flags */
unsigned int curDocStat;
/** browser process for goToURL() */
KProcess browserProc;
/** pointer to the list-view, using this document.
* As there can only be one list-view per doc, we
* don't need a list here.
*/
PwMView *listView;
/** unnamedNum is used to store the "unnamed counter"
* for this document, while it's unnamed. If it's 0,
* we have to get a new unique one.
*/
unsigned int unnamedNum;
/** is this doc going to be deleted (executing in destructor context) */
bool deleted;
/** document timer */
DocTimer *_timer;
/** lock counter for the "dataChanged" signal */
unsigned int dataChangedLock;
/** list of all open documents */
static PwMDocList openDocList;
protected:
/** serialize "dta" and return it in "d". */
bool serializeDta(string *d);
/** de-serialize "d" and overwrite "dta" */
bool deSerializeDta(const string *d, bool entriesLocked);
/** write header to file */
PwMerror writeFileHeader(char keyHash, char dataHash, char crypt, char compress,
QString *pw, QFile *f);
/** write data-hash to file */
PwMerror writeDataHash(char dataHash, string *d, QFile *f);
/** check header. Read header info and verify key-hash and filever.
* returns length of header in "headerLength" */
PwMerror checkHeader(char *cryptAlgo, QString *pw, char *compress,
unsigned int *headerLength, char *dataHashType,
string *dataHash, QFile *f);
/** check the data-hash */
PwMerror checkDataHash(char dataHashType, const string *dataHash, const string *dataStream);
/** encrypt data "d" and write to "filename" */
PwMerror encrypt(string *d, const QString *pw, QFile *f, char algo);
/** read data from file beginning at "pos", decrypt and return it */
PwMerror decrypt(string *d, unsigned int pos, const QString *pw, char algo, QFile *f);
/** compress the data */
bool compressDta(string *d, char algo);
/** uncompress the data */
bool decompressDta(string *d, char algo);
/** internal import function for a text-file generated by PwM.
* If this is not a valid PwM-exported file, it returns e_fileFormat */
PwMerror importText_PwM(const QString *file);
/** PwM-text-import helper function to extract the name/pw/comment out
* of one entry-line */
bool textExtractEntry_PwM(const char *in, ssize_t in_size, string *out);
/** compare two strings */
bool compareString(const string &s1, const string &s2, bool caseSensitive,
bool exactWordMatch);
/** clears all document-data */
void clearDoc();
/** delete all empty categories */
void delAllEmptyCat(bool dontFlagDirty);
/** set a document status flag */
void setDocStatFlag(unsigned int statFlag)
{ curDocStat |= statFlag; }
/** unset a document status flag */
void unsetDocStatFlag(unsigned int statFlag)
{ curDocStat &= ~statFlag; }
/** get a document status flag */
bool getDocStatFlag(unsigned int statFlag) const
{ return (curDocStat & statFlag); }
/** set the "currentPassword" */
void setCurrentPw(const QString &pw)
{
currentPw = pw;
setDocStatFlag(DOC_STAT_DISK_DIRTY);
}
/** make a backup-copy of the given file */
bool backupFile(const QString &filePath);
/** copy a file from src to dst */
bool copyFile(const QString &src, const QString &dst);
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);
//called by the syncmanager to indicate that the work has to be marked as dirty.
virtual void sync_setModified();
//called by the syncmanager to ask if the dirty flag is set.
virtual bool sync_isModified();
//called by the syncmanager to indicate that the work has to be saved.
virtual void sync_save();
+
#endif
+ 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/pwmdocui.cpp b/pwmanager/pwmanager/pwmdocui.cpp
index 5e675fc..41afa6a 100644
--- a/pwmanager/pwmanager/pwmdocui.cpp
+++ b/pwmanager/pwmanager/pwmdocui.cpp
@@ -231,97 +231,97 @@ int PwMDocUi::dirtyAskSave(const QString &docTitle)
("\" has been modified.\n"
"Do you want to save it?"),
i18n("save?"));
if (ret == KMessageBox::Yes) {
return 0;
} else if (ret == KMessageBox::No) {
return 1;
}
#endif
// cancel
return -1;
}
bool PwMDocUi::saveDocUi(PwMDoc *doc)
{
PWM_ASSERT(doc);
doc->timer()->getLock(DocTimer::id_autoLockTimer);
if (doc->isDocEmpty()) {
KMessageBox::information(currentView,
i18n
("Sorry, there's nothing to save.\n"
"Please first add some passwords."),
i18n("nothing to do"));
doc->timer()->putLock(DocTimer::id_autoLockTimer);
return true;
}
PwMerror ret = doc->saveDoc(conf()->confGlobCompression());
if (ret == e_filename) {
doc->timer()->putLock(DocTimer::id_autoLockTimer);
return saveAsDocUi(doc);
} else if (ret == e_weakPw) {
KMessageBox::error(currentView,
i18n("Error: This is a weak password.\n"
"Please select another password."),
i18n("weak password"));
doc->timer()->putLock(DocTimer::id_autoLockTimer);
return false;
} else if (ret == e_fileBackup) {
KMessageBox::error(currentView,
i18n("Error: Couldn't make backup-file!"),
i18n("backup failed"));
doc->timer()->putLock(DocTimer::id_autoLockTimer);
return false;
} else if (ret != e_success) {
KMessageBox::error(currentView,
i18n("Error: Couldn't write to file.\n"
- "Please check if you have permission to "
+ "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) {
KMessageBox::error(currentView,
i18n("Error: Couldn't write to file.\n"
"Please check if you have permission to "
"write to the file in that directory."),
i18n("error while writing"));
doc->timer()->putLock(DocTimer::id_autoLockTimer);
diff --git a/pwmanager/pwmanager/pwmexception.h b/pwmanager/pwmanager/pwmexception.h
index c8a8c0f..301ebd7 100644
--- a/pwmanager/pwmanager/pwmexception.h
+++ b/pwmanager/pwmanager/pwmexception.h
@@ -114,96 +114,97 @@ void pwmFatal(const char *id,
enum PwMerror {
e_success = 0,
// file access errors
e_filename,
e_readFile,
e_writeFile,
e_openFile,
e_accessFile, // permission error, etc...
e_fileGeneric,
e_alreadyOpen,
// other file errors
e_fileVer,
e_fileFormat, // format error
e_unsupportedFormat, // completely unsupported format
e_setFilePointer,
e_fileBackup,
e_fileCorrupt, // file data has correct format,
// but is corrupt (checksum error, etc)
// password errors
e_wrongPw,
e_getPw,
e_weakPw,
e_noPw,
// action not implemented errors
e_hashNotImpl,
e_cryptNotImpl,
// argument/parameter errors
e_incompleteArg,
e_invalidArg,
// misc
e_writeHeader,
e_serializeDta,
e_enc,
e_entryExists,
e_categoryExists,
e_maxAllowedEntr, // no more entries can be added.
e_outOfMem,
e_lock, // error while (un)locking
e_docNotSaved, // doc wasn't saved to a file, yet.
e_docIsEmpty,
e_binEntry,
e_normalEntry,
+ e_syncError,
e_generic
};
/** can be used for general exception faults */
class PwMException
{
public:
enum exceptionId
{
EX_GENERIC = 0,
EX_OPEN,
EX_CLOSE,
EX_READ,
EX_WRITE,
EX_LOAD_MODULE,
EX_PARSE
};
public:
PwMException(exceptionId id = EX_GENERIC,
const char *message = "")
{
exId = id;
exMsg = message;
}
exceptionId getId()
{ return exId; }
const char* getMessage()
{ return exMsg; }
protected:
/** ID of this exception */
exceptionId exId;
/** additional error-message for this exception */
const char *exMsg;
};
void __printInfo(const string &msg);
void __printWarn(const string &msg);
void __printError(const string &msg);
#ifdef PWM_DEBUG
void __printDebug(const string &msg);
# define printDebug(x) __printDebug(x)
#else
# define printDebug(x) do { } while (0)
diff --git a/pwmanager/pwmanager/pwmview.cpp b/pwmanager/pwmanager/pwmview.cpp
index d192119..e23ce25 100644
--- a/pwmanager/pwmanager/pwmview.cpp
+++ b/pwmanager/pwmanager/pwmview.cpp
@@ -1,85 +1,86 @@
/***************************************************************************
* *
* copyright (C) 2003, 2004 by Michael Buesch *
* email: mbuesch@freenet.de *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 *
* as published by the Free Software Foundation. *
* *
***************************************************************************/
/***************************************************************************
* copyright (C) 2004 by Ulf Schenk
* This file is originaly based on version 1.0.1 of pwmanager
* and was modified to run on embedded devices that run microkde
*
* $Id$
**************************************************************************/
#include "pwmview.h"
#include "pwmexception.h"
#include "globalstuff.h"
#include "pwm.h"
#include "rencatwnd.h"
#ifndef PWM_EMBEDDED
#include "configuration.h"
#else
#include "pwmprefs.h"
#endif
#include "commentbox.h"
#include <kmessagebox.h>
#include <klocale.h>
#include <qlineedit.h>
#include <qpoint.h>
#include <qapplication.h>
+#include <qlayout.h>
//US ENH: wouldn't it be a good idea if we could use this consts everywhere else.
//US ENH: for examle in listviewpwm.cpp
//US ENH: Because of that I transfer them into the headerfile.
/*
#define COLUMN_DESC 0
#define COLUMN_NAME 1
#define COLUMN_PW 2
#define COLUMN_URL 3
#define COLUMN_LAUNCHER 4
*/
PwMView::PwMView(PwM *_mainClass,
QWidget *parent, PwMDoc *_doc,
const char *name)
: PwMViewStyle(parent, name)
{
PWM_ASSERT(_mainClass);
PWM_ASSERT(parent);
PWM_ASSERT(_doc);
setView(this);
doc = _doc;
doc->setListViewPointer(this);
mainClass = _mainClass;
resize(_mainClass->size());
initStyle(conf()->confWndMainViewStyle());
initCtxMenu();
doc->setCurrentView(this);
connect(doc, SIGNAL(dataChanged(PwMDoc *)), this, SLOT(updateView()));
}
PwMView::~PwMView()
{
}
void PwMView::initCtxMenu()
{
ctxMenu = new QPopupMenu(this);
ctxMenu->insertItem(i18n("&Add password"), mainClass, SLOT(addPwd_slot()));
ctxMenu->insertSeparator();
ctxMenu->insertItem(i18n("&Edit"), mainClass, SLOT(editPwd_slot()));
ctxMenu->insertItem(i18n("&Delete"), mainClass, SLOT(deletePwd_slot()));
ctxMenu->insertSeparator();
ctxMenu->insertItem(i18n("copy password to clipboard"),
this, SLOT(copyPwToClip()));
ctxMenu->insertItem(i18n("copy username to clipboard"),
this, SLOT(copyNameToClip()));
ctxMenu->insertItem(i18n("copy description to clipboard"),
@@ -410,51 +411,114 @@ void PwMView::copyNameToClip()
void PwMView::copyDescToClip()
{
if (doc->isDeepLocked())
return;
unsigned int curIndex = 0;
if (!getCurEntryIndex(&curIndex))
return;
PwMDataItem d;
document()->getEntry(getCurrentCategory(), curIndex, &d);
PwM::copyToClipboard(d.desc.c_str());
}
void PwMView::copyUrlToClip()
{
if (doc->isDeepLocked())
return;
unsigned int curIndex = 0;
if (!getCurEntryIndex(&curIndex))
return;
PwMDataItem d;
document()->getEntry(getCurrentCategory(), curIndex, &d);
PwM::copyToClipboard(d.url.c_str());
}
void PwMView::copyLauncherToClip()
{
if (doc->isDeepLocked())
return;
unsigned int curIndex = 0;
if (!getCurEntryIndex(&curIndex))
return;
PwMDataItem d;
document()->getEntry(getCurrentCategory(), curIndex, &d);
PwM::copyToClipboard(d.launcher.c_str());
}
void PwMView::copyCommentToClip()
{
if (doc->isDeepLocked())
return;
unsigned int curIndex = 0;
if (!getCurEntryIndex(&curIndex))
return;
PwMDataItem d;
document()->getEntry(getCurrentCategory(), curIndex, &d);
PwM::copyToClipboard(d.comment.c_str());
}
+
+
+
+PwMDataItemChooser::PwMDataItemChooser( PwMDataItem loc, PwMDataItem rem, bool takeloc, QWidget *parent, const char *name ) : KDialogBase(parent,name,
+ true ,i18n("Conflict! Please choose Entry!"),Ok|User1|Close,Close, false)
+{
+ findButton( Close )->setText( i18n("Cancel Sync"));
+ findButton( Ok )->setText( i18n("Remote"));
+ findButton( User1 )->setText( i18n("Local"));
+ QWidget* topframe = new QWidget( this );
+ setMainWidget( topframe );
+ QBoxLayout* bl;
+ if ( QApplication::desktop()->width() < 640 ) {
+ bl = new QVBoxLayout( topframe );
+ } else {
+ bl = new QHBoxLayout( topframe );
+ }
+ QVBox* subframe = new QVBox( topframe );
+ bl->addWidget(subframe );
+ QLabel* lab = new QLabel( i18n("Local Entry"), subframe );
+ if ( takeloc )
+ lab->setBackgroundColor(Qt::green.light() );
+ // AddresseeView * av = new AddresseeView( subframe );
+ // av->setAddressee( loc );
+ subframe = new QVBox( topframe );
+ bl->addWidget(subframe );
+ lab = new QLabel( i18n("Remote Entry"), subframe );
+ if ( !takeloc )
+ lab->setBackgroundColor(Qt::green.light() );
+ // av = new AddresseeView( subframe );
+ // av->setAddressee( rem );
+ QObject::connect(findButton( Ok ),SIGNAL(clicked()),this, SLOT(slot_remote()));
+ QObject::connect(this,SIGNAL(user1Clicked()),this, SLOT(slot_local()));
+#ifndef DESKTOP_VERSION
+ showMaximized();
+#else
+ resize ( 640, 400 );
+#endif
+}
+
+int PwMDataItemChooser::executeD( bool local )
+{
+ mSyncResult = 3;
+ if ( local )
+ findButton( User1 )->setFocus();
+ else
+ findButton( Ok )->setFocus();
+ exec();
+ return mSyncResult;
+}
+void PwMDataItemChooser::slot_remote()
+{
+ mSyncResult = 2;
+ accept();
+}
+void PwMDataItemChooser::slot_local()
+{
+ mSyncResult = 1;
+ accept();
+}
+
+
+
#ifndef PWM_EMBEDDED
#include "pwmview.moc"
#endif
diff --git a/pwmanager/pwmanager/pwmview.h b/pwmanager/pwmanager/pwmview.h
index 5a326d3..75cce51 100644
--- a/pwmanager/pwmanager/pwmview.h
+++ b/pwmanager/pwmanager/pwmview.h
@@ -1,86 +1,87 @@
/***************************************************************************
* *
* 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$
**************************************************************************/
#ifndef PWMVIEW_H
#define PWMVIEW_H
//US ENH: wouldn't it be a good idea if we could use this consts everywhere else.
//US ENH: for examle in listviewpwm.cpp
//US ENH: Because of that I transfer them into the headerfile.
#define COLUMN_DESC 0
#define COLUMN_NAME 1
#define COLUMN_PW 2
#define COLUMN_URL 3
#define COLUMN_LAUNCHER 4
#include "listviewpwm.h"
#include "pwmdoc.h"
#include "pwmviewstyle.h"
#include <kconfig.h>
#include <klocale.h>
+#include <kdialogbase.h>
#include <qevent.h>
#include <qfont.h>
#include <qobject.h>
#include <vector>
#include <string>
using std::string;
using std::vector;
class PwM;
class ConfFile;
class PwMStatusBar;
/** View class for PwM */
class PwMView : public PwMViewStyle
{
Q_OBJECT
friend class PwMViewStyle;
public:
/** construtor */
PwMView(PwM *_mainClass, QWidget* parent, PwMDoc *_doc,
const char *name = 0);
/** destructor */
~PwMView();
/** returns pointer to the document */
PwMDoc* document()
{ return doc; }
/** returns the index of the currently selected entry.
* (index as represented in PwMDoc !)
*/
bool getCurEntryIndex(unsigned int *index);
/** returns the position of the given item in the document
* Note: This func only serches in the current category.
*/
bool getDocEntryIndex(unsigned int *index,
const QListViewItem *item);
public slots:
/** update the view (call if dirty) */
void updateView()
{
updateCategories();
shiftToView();
}
@@ -102,49 +103,70 @@ protected:
QPopupMenu *ctxMenu;
protected:
/** update the categories from document */
void updateCategories();
/** widget resize event */
void resizeEvent(QResizeEvent *);
/** initialize context-menu */
void initCtxMenu();
/** tempoarly disable auto-sorting and user-sorting */
void tmpDisableSort()
{ lv->setSorting(-1); }
/** re-enable tempoarly disabled sorting */
void tmpReEnableSort()
{
lv->setSorting(lv->columns() + 1,
true/*lv->sortOrder() == Qt::Ascending*/);
}
/** The user pressed and released a key. */
void keyReleaseEvent(QKeyEvent *e);
protected slots:
/** changes the comment text-edit, because a new item has been selected */
void refreshCommentTextEdit(QListViewItem *curItem);
/** copy pw to clipboard */
void copyPwToClip();
/** copy name to clipboard */
void copyNameToClip();
/** copy desc to clipboard */
void copyDescToClip();
/** copy url to clipboard */
void copyUrlToClip();
/** copy launcher to clipboard */
void copyLauncherToClip();
/** copy comment to clipboard */
void copyCommentToClip();
/** reorganize the "listViewPos" positions in the document
* (for the current category only!)
*/
void reorgLp();
private:
/** document */
PwMDoc *doc;
/** pointer to the main class "PwM" */
PwM *mainClass;
};
+
+//US ENH we need this chooser when syncing results in a conflict
+class PwMDataItemChooser : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+ PwMDataItemChooser( PwMDataItem loc, PwMDataItem rem, bool takeloc, QWidget *parent = 0, const char *name = 0 );
+
+ int executeD( bool local );
+
+ private:
+ int mSyncResult;
+
+ private slots:
+ void slot_remote();
+ void slot_local();
+
+};
+
+
#endif
diff --git a/pwmanager/pwmanager/serializer.cpp b/pwmanager/pwmanager/serializer.cpp
index a54ba8a..f615082 100644
--- a/pwmanager/pwmanager/serializer.cpp
+++ b/pwmanager/pwmanager/serializer.cpp
@@ -1,91 +1,95 @@
/***************************************************************************
* *
* copyright (C) 2004 by Michael Buesch *
* email: mbuesch@freenet.de *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 *
* as published by the Free Software Foundation. *
* *
***************************************************************************/
/***************************************************************************
* copyright (C) 2004 by Ulf Schenk
* This file is originaly based on version 2.0 of pwmanager
* and was modified to run on embedded devices that run microkde
*
* $Id$
**************************************************************************/
#include "serializer.h"
#include "pwmexception.h"
#ifdef PWM_EMBEDDED
#include <kglobal.h>
#include <klocale.h>
#endif
/* enable/disable serializer debugging (0/1) */
#define SERIALIZER_DEBUG 1
/* use the old xml tags for writing (0/1) */
#define USE_OLD_TAGS 0
/* write a CDATA section (0/1) */
#define WRITE_CDATA_SEC 0
#define META_CREATE_DATE "c"
#define META_VALID_DATE "v"
#define META_EXPIRE_DATE "e"
#define META_UPDATE_DATE "u"
#define META_UPDATE_INT "i"
//US ENH : uniqueid
#define META_UNIQUEID "n"
+#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"
#define ENTRY_PREFIX_OLD "entry_"
#define ENTRY_DESC_OLD "desc"
#define ENTRY_NAME_OLD "name"
#define ENTRY_PW_OLD "pw"
#define ENTRY_COMMENT_OLD "comment"
#define ENTRY_URL_OLD "url"
#define ENTRY_LAUNCHER_OLD "launcher"
#define ENTRY_LVP_OLD "listViewPos"
#define ENTRY_BIN_OLD "b"
#define ENTRY_META_OLD "m"
#define ROOT_MAGIC_NEW "P"
#define VER_STR_NEW "v"
#define COMPAT_VER_NEW "2"
#define CAT_ROOT_NEW "c"
#define CAT_PREFIX_NEW "c"
#define CAT_NAME_NEW "n"
#define ENTRY_PREFIX_NEW "e"
#define ENTRY_DESC_NEW "d"
#define ENTRY_NAME_NEW "n"
#define ENTRY_PW_NEW "p"
#define ENTRY_COMMENT_NEW "c"
#define ENTRY_URL_NEW "u"
#define ENTRY_LAUNCHER_NEW "l"
#define ENTRY_LVP_NEW "v"
#define ENTRY_BIN_NEW ENTRY_BIN_OLD
#define ENTRY_META_NEW ENTRY_META_OLD
#if USE_OLD_TAGS != 0
# define ROOT_MAGIC_WR ROOT_MAGIC_OLD
# define VER_STR_WR VER_STR_OLD
# define COMPAT_VER_WR COMPAT_VER_OLD
# define CAT_ROOT_WR CAT_ROOT_OLD
# define CAT_PREFIX_WR CAT_PREFIX_OLD
# define CAT_NAME_WR CAT_NAME_OLD
# define ENTRY_PREFIX_WR ENTRY_PREFIX_OLD
# define ENTRY_DESC_WR ENTRY_DESC_OLD
@@ -161,131 +165,143 @@ void Serializer::clear()
bool Serializer::parseXml(const QCString &buffer)
{
PWM_ASSERT(domDoc);
#ifndef PWM_EMBEDDED
if (!domDoc->setContent(buffer, true))
return false;
#else
if (!domDoc->setContent(buffer))
return false;
#endif
if (!checkValid())
return false;
return true;
}
QCString Serializer::getXml()
{
PWM_ASSERT(domDoc);
#ifndef PWM_EMBEDDED
#if defined(PWM_DEBUG) && SERIALIZER_DEBUG != 0
QCString tmp(domDoc->toCString(8));
printDebug("<BEGIN Serializer::getXml() dump>\n");
cout << tmp << endl;
printDebug("<END Serializer::getXml() dump>");
#endif // DEBUG
QCString ret(domDoc->toCString(0));
ret.replace('\n', "");
return ret;
#else
#if defined(PWM_DEBUG) && SERIALIZER_DEBUG != 0
QCString tmp(" " + domDoc->toCString());
printDebug("<BEGIN Serializer::getXml() dump>\n");
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(const vector<PwMCategoryItem> &dta)
+bool Serializer::serialize(PwMItem &dta)
{
PWM_ASSERT(domDoc);
QDomElement root(genNewRoot());
QDomElement catNode(domDoc->createElement(CAT_ROOT_WR));
- root.appendChild(catNode);
- if (!addCategories(&catNode, dta))
+ 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(vector<PwMCategoryItem> *dta)
+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)) {
+ 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 true;
- }
+ return false;
+
}
- return false;
+ return true;
}
bool Serializer::readCategories(const QDomNode &n,
vector<PwMCategoryItem> *dta)
{
QDomNodeList nl(n.childNodes());
QDomNode cur;
QString name;
unsigned int numCat = nl.count(), i;
PwMCategoryItem curCat;
vector<PwMDataItem> curEntr;
if (!numCat) {
printDebug("Serializer::readCategories(): empty");
return false;
}
for (i = 0; i < numCat; ++i) {
cur = nl.item(i);
if (cur.nodeName().left(1) == CAT_PREFIX_NEW ||
cur.nodeName().left(4) == CAT_PREFIX_OLD) {
name = cur.toElement().attribute(CAT_NAME_NEW);
if (name == QString::null)
name = cur.toElement().attribute(CAT_NAME_OLD);
PWM_ASSERT(name != QString::null);
PWM_ASSERT(name != "");
curCat.clear();
curCat.name = name.latin1();
if (!readEntries(cur, &curEntr)) {
dta->clear();
return false;
}
curCat.d = curEntr;
dta->push_back(curCat);
} else {
printDebug("Serializer::readCategories(): uh? not a category?");
}
}
return true;
}
bool Serializer::readEntries(const QDomNode &n,
vector<PwMDataItem> *dta)
{
QDomNodeList nl(n.childNodes());
QDomNode cur;
unsigned int numEntr = nl.count(), i;
PwMDataItem curEntr;
@@ -616,48 +632,125 @@ bool Serializer::writeMeta(QDomElement *e,
e->appendChild(tag);
tag = domDoc->createElement(META_UPDATE_DATE);
#ifndef PWM_EMBEDDED
text = domDoc->createTextNode(dta.update.toString(Qt::ISODate));
#else
text = domDoc->createTextNode(KGlobal::locale()->formatDateTime(dta.update, KLocale::ISODate));
#endif
tag.appendChild(text);
e->appendChild(tag);
tag = domDoc->createElement(META_UPDATE_INT);
text = domDoc->createTextNode(tostr(dta.updateInt).c_str());
tag.appendChild(text);
e->appendChild(tag);
tag = domDoc->createElement(META_UNIQUEID);
text = domDoc->createTextNode(escapeEntryData(dta.uniqueid));
tag.appendChild(text);
e->appendChild(tag);
#undef new_text
return true;
}
QString Serializer::escapeEntryData(QString dta)
{
#ifndef PWM_EMBEDDED
dta.replace('\n', "$>--endl--<$");
dta.replace("]]>", "||>");
#else
dta.replace(QRegExp("\n"), "$>--endl--<$");
dta.replace(QRegExp("]]>"), "||>");
#endif
return dta;
}
QString Serializer::unescapeEntryData(QString dta)
{
#ifndef PWM_EMBEDDED
dta.replace("$>--endl--<$", "\n");
dta.replace("||>", "]]>");
#else
dta.replace(QRegExp("$>--endl--<$"), "\n");
dta.replace(QRegExp("||>"), "]]>");
#endif
return dta;
}
+
+
+//US ENH: the following methods are getting used to write/read sync entries
+/** read the syncentries in the node "n" */
+bool Serializer::readSyncData(const QDomNode &n, vector<PwMSyncItem> *dta)
+{
+ QDomNodeList nl(n.childNodes());
+ QDomNode cur;
+
+ QString devicename, val;
+ unsigned int numSync = nl.count(), i;
+ PwMSyncItem curSync;
+ bool ok = true;
+
+ if (!numSync) {
+ //no sync entries is a possible result
+ printDebug("Serializer::readSyncData(): empty");
+ return true;
+ }
+ for (i = 0; i < numSync; ++i) {
+ cur = nl.item(i);
+ if (cur.nodeName().left(1) == SYNC_TARGET_PREFIX) {
+ devicename = cur.toElement().attribute(SYNC_TARGET_NAME);
+ val = cur.toElement().text();
+
+ if ((val == "") || (devicename == QString::null)) {
+ printDebug("Serializer::readSyncData(): empty synctarget name or syncdate");
+ continue;
+ }
+
+ curSync.syncName = devicename;
+#ifndef PWM_EMBEDDED
+ curSync.lastSyncDate = QDateTime::fromString(val, Qt::ISODate);
+#else
+ curSync.lastSyncDate = KGlobal::locale()->readDateTime(val, KLocale::ISODate, &ok);
+ if (ok == false)
+ qDebug("Serializer::readSyncData(): could not parse syncdate:%s",val.latin1());
+
+#endif
+ dta->push_back(curSync);
+ }
+ }
+ return true;
+
+}
+
+
+
+bool Serializer::addSyncData(QDomElement *e,
+ const vector<PwMSyncItem> &dta)
+{
+ unsigned int numSync = dta.size(), i;
+ QString curId, curDeviceName;
+ QDomElement curSync, curSyncDate;
+ QDomText text;
+
+ for (i = 0; i < numSync; ++i) {
+ curId = SYNC_TARGET_PREFIX;
+ curId += tostr(i).c_str();
+ curDeviceName = dta[i].syncName.c_str();
+ curSync = domDoc->createElement(curId);
+ curSync.setAttribute(SYNC_TARGET_NAME, curDeviceName);
+
+#ifndef PWM_EMBEDDED
+ text = domDoc->createTextNode(dta[i].lastSyncDate.toString(Qt::ISODate));
+#else
+ text = domDoc->createTextNode(KGlobal::locale()->formatDateTime(dta[i].lastSyncDate, KLocale::ISODate));
+#endif
+ curSyncDate.appendChild(text);
+ curSync.appendChild(curSyncDate);
+
+ e->appendChild(curSync);
+
+ }
+ return true;
+}
+
diff --git a/pwmanager/pwmanager/serializer.h b/pwmanager/pwmanager/serializer.h
index 245fcee..ee61b94 100644
--- a/pwmanager/pwmanager/serializer.h
+++ b/pwmanager/pwmanager/serializer.h
@@ -6,97 +6,110 @@
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License version 2 *
* as published by the Free Software Foundation. *
* *
***************************************************************************/
/***************************************************************************
* copyright (C) 2004 by Ulf Schenk
* This file is originaly based on version 2.0 of pwmanager
* and was modified to run on embedded devices that run microkde
*
* $Id$
**************************************************************************/
#ifndef __SERIALIZER_H
#define __SERIALIZER_H
#include "pwmdoc.h"
#include <qcstring.h>
#include <qdom.h>
#include <vector>
using std::vector;
/** This serializes its input data into
* the PwManager-XML-datastream, that becomes
* encrypted and maybe compressed
*/
class Serializer
{
public:
/** construct an empty serializer document */
Serializer();
/** construct a serializer document and parse "buffer" */
Serializer(const QCString &buffer);
/** destructor */
virtual ~Serializer();
/** clears all data */
void clear();
/** parse the given data buffer */
bool parseXml(const QCString &buffer);
/** returns the current XML data */
QCString getXml();
/** serialize "dta" and store it as XML data */
- bool serialize(const vector<PwMCategoryItem> &dta);
+ //US ENH: we need to serialize and deserialize not only categories, but also synctargets
+ bool serialize(PwMItem &dta);
/** deserialize the (parsed) XML data and store it in "dta" */
- bool deSerialize(vector<PwMCategoryItem> *dta);
+ bool deSerialize(PwMItem *dta);
/** sets the initial default lockStat we should assign */
void setDefaultLockStat(bool stat)
{ defaultLockStat = stat; }
protected:
/** main data holder */
QDomDocument *domDoc;
/** default lockStat to assign */
bool defaultLockStat;
protected:
/** check if this is valid PwManager XML data */
bool checkValid();
/** read the categories in the node "n" */
bool readCategories(const QDomNode &n,
vector<PwMCategoryItem> *dta);
/** read the entries in the node "n" */
bool readEntries(const QDomNode &n,
vector<PwMDataItem> *dta);
/** extract the data out of the given item at "n" */
bool extractEntry(const QDomNode &n,
PwMDataItem *dta);
/** extract the meta-data */
bool extractMeta(const QDomNode &n,
PwMMetaData *dta);
/** generates a new root node and sets all initial parameters */
QDomElement genNewRoot();
/** add new categories to the XML data stream in e */
bool addCategories(QDomElement *e,
const vector<PwMCategoryItem> &dta);
/** add the given new entries to the XML data stream in e */
bool addEntries(QDomElement *e,
const vector<PwMDataItem> &dta);
/** do serialize and write the given entry to the XML stream */
bool writeEntry(QDomElement *e,
const PwMDataItem &_dta);
/** write the entry meta data to the xml stream */
bool writeMeta(QDomElement *e,
const PwMMetaData &dta);
/** escape illegal characters out of the given entry data string */
QString escapeEntryData(QString dta);
/** un-escape illegal characters out of the given entry data string */
QString unescapeEntryData(QString dta);
+
+
+
+ //US ENH: the following methods are getting used to write/read sync entries
+ /** read the syncentries in the node "n" */
+ bool readSyncData(const QDomNode &n,
+ vector<PwMSyncItem> *dta);
+
+ /** add new syncentries to the XML data stream in e */
+ bool addSyncData(QDomElement *e,
+ const vector<PwMSyncItem> &dta);
+
};
#endif // __SERIALIZER_H