-rw-r--r-- | pwmanager/pwmanager/pwmdoc.cpp | 102 | ||||
-rw-r--r-- | pwmanager/pwmanager/pwmdoc.h | 23 |
2 files changed, 60 insertions, 65 deletions
diff --git a/pwmanager/pwmanager/pwmdoc.cpp b/pwmanager/pwmanager/pwmdoc.cpp index 2a7b11d..e9906a4 100644 --- a/pwmanager/pwmanager/pwmdoc.cpp +++ b/pwmanager/pwmanager/pwmdoc.cpp @@ -2757,157 +2757,178 @@ PwMerror PwMDoc::exportToGpasman(const QString *file) 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; } + +//US: we use the stl sort algorythm to sort all elements in the order +//of its listViewPos (in the order 1,2,3,5,...,x,-1, -1, -1 +struct PwMDataItemListViewPosSort +{ + bool operator()(PwMDataItem* rpStart, PwMDataItem* rpEnd) + { + //qDebug("pwMDoc::PwMDataItemListViewPosSort()"); + if ((rpEnd)->listViewPos < 0) + return false; + else + return (rpStart)->listViewPos < (rpEnd)->listViewPos; + } +}; + void PwMDoc::ensureLvp() { if (isDocEmpty()) return; //US ENH BUG: when using syncronizing, this way of sorting //is not sufficient, because there might be empty spaces - // at the beginning. But this algorythm only can add elements - //to the end.The result are crashes because of listoverflows + // at the beginning. But the old algorythm only can add elements + //to the end.The result are crashes because of list overflows //we need something to fill all gaps. - vector< vector<PwMDataItem>::iterator > undefined; - vector< vector<PwMDataItem>::iterator > sorted; - vector< vector<PwMDataItem>::iterator >::iterator undefBegin, - undefEnd, - undefI; - vector< vector<PwMDataItem>::iterator >::iterator sortedBegin, - sortedEnd, - sortedI; + vector<PwMDataItem*> sorted; + vector< PwMDataItem*>::iterator sortedBegin, + sortedEnd, + sortedI; vector<PwMCategoryItem>::iterator catBegin = dti.dta.begin(), catEnd = dti.dta.end(), catI = catBegin; vector<PwMDataItem>::iterator entrBegin, entrEnd, entrI; int lvpTop, tmpLvp; + //qDebug("collect:"); + while (catI != catEnd) { lvpTop = -1; - undefined.clear(); + sorted.clear(); entrBegin = catI->d.begin(); entrEnd = catI->d.end(); entrI = entrBegin; + //US: we use the stl sort algorythm to sort all elements in the order + //of its listViewPos (in the order 1,2,2,3,5,...,x,-1, -1, -1 while (entrI != entrEnd) { - tmpLvp = entrI->listViewPos; - if (tmpLvp == -1) - undefined.push_back(entrI); - else - sorted[tmpLvp] = entrI; - //US else if (tmpLvp > lvpTop) - //US lvpTop = tmpLvp; - ++entrI; + //qDebug("found: %s, pos=%i", (*entrI).desc.c_str(), (*entrI).listViewPos); + sorted.push_back((PwMDataItem*)&(*entrI)); + ++entrI; } - //now we have all undefied in the collection. Now insert the existing + sortedBegin = sorted.begin(); + sortedEnd = sorted.end(); + + sort(sortedBegin, sortedEnd, PwMDataItemListViewPosSort()); + + // qDebug("resort:"); + //now we have all sorted in a collection + //Now start with the sorted and reset listviewpos. sortedBegin = sorted.begin(); sortedEnd = sorted.end(); sortedI = sortedBegin; while (sortedI != sortedEnd) { - tmpLvp = (*sortedI)->listViewPos; - undefined[tmpLvp] = *sortedI; - ++sortedI; + // qDebug("reset defined: %s, from pos=%i to pos=%i", (*sortedI)->desc.c_str(), (*sortedI)->listViewPos, lvpTop+1); + (*sortedI)->listViewPos = ++lvpTop; + ++sortedI; } - undefBegin = undefined.begin(); - undefEnd = undefined.end(); - undefI = undefBegin; - while (undefI != undefEnd) { - (*undefI)->listViewPos = ++lvpTop; - ++undefI; + /*/debug + entrBegin = catI->d.begin(); + entrEnd = catI->d.end(); + entrI = entrBegin; + + while (entrI != entrEnd) { + qDebug("check: %s, pos=%i", (*entrI).desc.c_str(), (*entrI).listViewPos); + ++entrI; } + */ + ++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()); //US ENH: The whole filename on PDAs is too long. So use only the last characters if (QApplication::desktop()->width() < 640) { if (title.length() > 30) title = "..." + title.right(30); } 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; } @@ -2951,280 +2972,273 @@ PwMerror PwMDoc::syncronize(KSyncManager* manager, PwMDoc* syncLocal , PwMDoc* s 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 Local %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); qDebug("Last Sync Remote %s ", syncItemRemote->lastSyncDate.toString().latin1()); //and remove the found entry here. We will reenter it later again. //US 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" ,syncItemLocal->lastSyncDate.toString().latin1(), syncItemRemote->lastSyncDate.toString().latin1() ); - // qDebug("%d %d %d %d ", syncItemLocal->lastSyncDate.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("mLastSync %s ",mLastSync.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 ]; qDebug("sync uid %s from remote file", uid.latin1()); qApp->processEvents(); inLocal = syncLocal->findEntryByID( uid, &catLocal, &indexLocal ); inRemote = syncRemote->findEntryByID( uid, &catRemote, &indexRemote ); PWM_ASSERT(inRemote); if ( inLocal != 0 ) { // maybe conflict - same uid in both files if ( (take = takePwMDataItem( inLocal, inRemote, mLastSync, mode, fullDateRange) ) ) { qDebug("take %d %s ", take, inLocal->desc.c_str()); if ( take == 3 ) return e_syncError; if ( take == 1 ) {// take local - //US syncRemote->removeAddressee( inRemote ); + int oldlistpos = inRemote->listViewPos; (*inRemote) = (*inLocal); - //US syncRemote->insertAddressee( inRemote , false); + inRemote->listViewPos = oldlistpos; ++changedRemote; } else { // take == 2 take remote - //US syncLocal->removeAddressee( inLocal ); + int oldlistpos = inLocal->listViewPos; (*inLocal) = (*inRemote); - //US syncLocal->insertAddressee( inLocal , false ); + inLocal->listViewPos = oldlistpos; ++changedLocal; } } } else { // no conflict if ( inRemote->meta.update > mLastSync || mode == 5 ) { inRemote->meta.update = modifiedSync; //first check if we have a matching category in the local file const string* remotecat = syncRemote->getCategory(catRemote); //US syncRemote->insertAddressee( inRemote, false ); //US syncLocal->insertAddressee( inRemote, false ); syncLocal->addEntry(remotecat->c_str(), 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 ]; qDebug("sync uid %s from local file", uid.latin1()); inLocal = syncLocal->findEntryByID( uid, &catLocal, &indexLocal ); inRemote = syncRemote->findEntryByID( uid, &catRemote, &indexRemote ); PWM_ASSERT(inLocal); 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 ( ! manager->mWriteBackExistingOnly ) { ++addedPasswordsRemote; inLocal->meta.update = modifiedSync; //first check if we have a matching category in the remote file const string* localcat = syncLocal->getCategory(catLocal); //USsyncLocal->insertAddressee( inLocal, false ); PwMDataItem newEntry; newEntry = *inLocal; inRemote = &newEntry; //USsyncRemote->insertAddressee( inRemote, false ); syncRemote->addEntry(localcat->c_str(), 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 ); - - //US syncRemote->addSyncDataEntry( syncItemRemote, false ); - //US 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 ( manager->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 + //full = true; //debug only if ( full ) { bool equ = ( (*local) == (*remote) ); if ( equ ) { - qDebug("equal "); + //qDebug("equal "); if ( mode < SYNC_PREF_FORCE_LOCAL ) return 0; - }else //debug only - qDebug("not equal %s %s ", local->desc.c_str(), remote->desc.c_str()); + }//else //debug only + //qDebug("not equal %s %s ", local->desc.c_str(), remote->desc.c_str()); } 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: diff --git a/pwmanager/pwmanager/pwmdoc.h b/pwmanager/pwmanager/pwmdoc.h index 6a1dd30..535fb92 100644 --- a/pwmanager/pwmanager/pwmdoc.h +++ b/pwmanager/pwmanager/pwmdoc.h @@ -164,128 +164,109 @@ 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(); } //US ENH: we need this operator to compare two items if we have no unique ids //available. Generaly this happens before the first sync + bool PwMDataItem::operator==( const PwMDataItem &a ) const { - qDebug("oper==%s", a.desc.c_str()); + //qDebug("oper==%s", a.desc.c_str()); if ( desc != a.desc ) return false; if ( name != a.name ) return false; if ( pw != a.pw ) return false; if ( comment != a.comment ) return false; if ( url != a.url ) return false; if ( launcher != a.launcher ) return false; //all other field will not be checked. return true; } - - //US ENH:this operator is used to copy an elements data during syncronization - //Attention: listViewPos will not be copied. So the position will stay the same. - PwMDataItem& operator = (const PwMDataItem& x) - { - // qDebug("oper=%s", x.desc.c_str()); - desc = x.desc; - name = x.name; - pw = x.pw; - comment = x.comment; - url = x.url; - launcher = x.launcher; - lockStat = x.lockStat; - //Do not copy listViewPos!!! listViewPos = x.listViewPos; - binary = x.binary; - meta = x.meta; - rev = x.rev; - return *this; - } - }; 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) { |