-rw-r--r-- | pwmanager/pwmanager/pwmanagerE.pro | 2 | ||||
-rw-r--r-- | pwmanager/pwmanager/pwmdoc.cpp | 568 | ||||
-rw-r--r-- | pwmanager/pwmanager/pwmdoc.h | 70 | ||||
-rw-r--r-- | pwmanager/pwmanager/pwmdocui.cpp | 2 | ||||
-rw-r--r-- | pwmanager/pwmanager/pwmexception.h | 1 | ||||
-rw-r--r-- | pwmanager/pwmanager/pwmview.cpp | 64 | ||||
-rw-r--r-- | pwmanager/pwmanager/pwmview.h | 22 | ||||
-rw-r--r-- | pwmanager/pwmanager/serializer.cpp | 109 | ||||
-rw-r--r-- | pwmanager/pwmanager/serializer.h | 17 |
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,34 +1,34 @@ 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 \ 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 @@ -14,48 +14,52 @@ * 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; @@ -986,271 +990,271 @@ PwMerror PwMDoc::addEntry(const QString &category, PwMDataItem *d, 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(); } } @@ -1469,74 +1473,74 @@ PwMerror PwMDoc::checkDataHash(char dataHashType, const string *dataHash, 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) { @@ -1550,50 +1554,50 @@ bool PwMDoc::lockAll(bool lock) 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) @@ -1624,50 +1628,50 @@ bool PwMDoc::unlockAll_tempoary(bool revert) 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; } } @@ -1708,96 +1712,96 @@ bool PwMDoc::unlockAll_tempoary(bool revert) */ 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; } @@ -1839,448 +1843,448 @@ PwMerror PwMDoc::deepLock(bool lock, bool saveToFile) 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(¤tPw, &useChipcard); if (pw == "") return; if (useChipcard) setDocStatFlag(DOC_STAT_USE_CHIPCARD); else unsetDocStatFlag(DOC_STAT_USE_CHIPCARD); setCurrentPw(pw); } void PwMDoc::setListViewPos(const QString &category, unsigned int index, int pos) { unsigned int cat = 0; if (!findCategory(category, &cat)) { BUG(); return; } setListViewPos(cat, index, pos); } void PwMDoc::setListViewPos(unsigned int category, unsigned int index, int pos) { - dta[category].d[index].listViewPos = pos; + 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)) @@ -2329,119 +2333,119 @@ PwMerror PwMDoc::exportToText(const QString *file) 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; @@ -2593,60 +2597,60 @@ PwMerror PwMDoc::exportToGpasman(const QString *file) 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) @@ -2684,50 +2688,50 @@ PwMerror PwMDoc::importFromGpasman(const QString *file) 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) { @@ -2764,73 +2768,347 @@ bool PwMDoc::tryDelete() 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) @@ -2840,39 +3118,151 @@ bool PwMDoc::sync(KSyncManager* manager, QString filename, int mode) 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 @@ -185,64 +185,90 @@ struct PwMDataItem /** 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() {} @@ -419,81 +445,82 @@ public: 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? */ @@ -553,89 +580,91 @@ public: /** 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; @@ -686,39 +715,64 @@ protected: { 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 @@ -255,49 +255,49 @@ bool PwMDocUi::saveDocUi(PwMDoc *doc) 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, 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 @@ -138,48 +138,49 @@ enum PwMerror { 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; 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 @@ -14,48 +14,49 @@ * 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; @@ -434,27 +435,90 @@ void PwMView::copyUrlToClip() 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 @@ -15,48 +15,49 @@ * 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, @@ -126,25 +127,46 @@ protected slots: /** 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 @@ -20,48 +20,52 @@ #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" @@ -185,83 +189,95 @@ QCString Serializer::getXml() 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); @@ -640,24 +656,101 @@ bool Serializer::writeMeta(QDomElement *e, 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 @@ -30,73 +30,86 @@ 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 |