-rw-r--r-- | pwmanager/pwmanager/pwm.cpp | 57 | ||||
-rw-r--r-- | pwmanager/pwmanager/pwm.h | 8 | ||||
-rw-r--r-- | pwmanager/pwmanager/pwmdoc.cpp | 85 | ||||
-rw-r--r-- | pwmanager/pwmanager/pwmdoc.h | 39 | ||||
-rw-r--r-- | pwmanager/pwmanager/pwmview.cpp | 92 | ||||
-rw-r--r-- | pwmanager/pwmanager/pwmview.h | 25 | ||||
-rw-r--r-- | pwmanager/pwmanager/serializer.cpp | 126 |
7 files changed, 287 insertions, 145 deletions
diff --git a/pwmanager/pwmanager/pwm.cpp b/pwmanager/pwmanager/pwm.cpp index 014e809..57b4432 100644 --- a/pwmanager/pwmanager/pwm.cpp +++ b/pwmanager/pwmanager/pwm.cpp @@ -103,89 +103,90 @@ enum { enum { BUTTON_POPUP_VIEW_FIND = 0, BUTTON_POPUP_VIEW_LOCK, BUTTON_POPUP_VIEW_DEEPLOCK, BUTTON_POPUP_VIEW_UNLOCK }; // Button IDs for "options" popup menu enum { BUTTON_POPUP_OPTIONS_CONFIG = 0 }; // Button IDs for "export" popup menu (in "file" popup menu) enum { BUTTON_POPUP_EXPORT_TEXT = 0, BUTTON_POPUP_EXPORT_GPASMAN #ifdef CONFIG_KWALLETIF ,BUTTON_POPUP_EXPORT_KWALLET #endif }; // Button IDs for "import" popup menu (in "file" popup menu) enum { BUTTON_POPUP_IMPORT_TEXT = 0, BUTTON_POPUP_IMPORT_GPASMAN #ifdef CONFIG_KWALLETIF ,BUTTON_POPUP_IMPORT_KWALLET #endif }; #ifdef PWM_EMBEDDED // Button IDs for "help" popup menu enum { BUTTON_POPUP_HELP_LICENSE = 0, BUTTON_POPUP_HELP_FAQ, - BUTTON_POPUP_HELP_ABOUT + BUTTON_POPUP_HELP_ABOUT, + BUTTON_POPUP_HELP_SYNC }; #endif // Button IDs for toolbar enum { BUTTON_TOOL_NEW = 0, BUTTON_TOOL_OPEN, BUTTON_TOOL_SAVE, BUTTON_TOOL_SAVEAS, BUTTON_TOOL_PRINT, BUTTON_TOOL_ADD, BUTTON_TOOL_EDIT, BUTTON_TOOL_DEL, BUTTON_TOOL_FIND, BUTTON_TOOL_LOCK, BUTTON_TOOL_DEEPLOCK, BUTTON_TOOL_UNLOCK }; PwM::PwM(PwMInit *_init, PwMDoc *doc, bool virginity, QWidget *parent, const char *name) - : KMainWindow(parent, name) + : KMainWindow(parent, "HALLO") , forceQuit (false) , forceMinimizeToTray (false) { init = _init; connect(doc, SIGNAL(docClosed(PwMDoc *)), this, SLOT(docClosed(PwMDoc *))); initMenubar(); initToolbar(); initMetrics(); setVirgin(virginity); setFocusPolicy(QWidget::WheelFocus); #ifndef PWM_EMBEDDED statusBar()->show(); #endif view = makeNewListView(doc); setCentralWidget(view); updateCaption(); showStatMsg(i18n("Ready.")); } PwM::~PwM() { disconnect(curDoc(), SIGNAL(docClosed(PwMDoc *)), this, SLOT(docClosed(PwMDoc *))); conf()->confWndMainWndSize(size()); emit closed(this); delete view; } void PwM::initMenubar() { KIconLoader* picons; @@ -329,64 +330,68 @@ void PwM::initMenubar() menuBar()->insertItem(i18n("&View"), viewPopup); // "options" popup menu optionsPopup->insertItem(QIconSet(picons->loadIcon("configure", KIcon::Small)), i18n("&Configure..."), this, SLOT(config_slot()), BUTTON_POPUP_OPTIONS_CONFIG); menuBar()->insertItem(i18n("&Options"), optionsPopup); // "help" popup menu #ifndef PWM_EMBEDDED helpPopup = helpMenu(QString::null, false); #else menuBar()->insertItem(i18n("&Sync"), syncPopup); helpPopup = new KPopupMenu(this); helpPopup->insertItem(i18n("&License"), this, SLOT(showLicense_slot()), 0, BUTTON_POPUP_HELP_LICENSE); helpPopup->insertItem(i18n("&Faq"), this, SLOT(faq_slot()), 0, BUTTON_POPUP_HELP_FAQ); helpPopup->insertItem(i18n("&About PwManager"), this, SLOT(createAboutData_slot()), 0, BUTTON_POPUP_HELP_ABOUT); + helpPopup->insertItem(i18n("&Sync HowTo"), this, + SLOT(syncHowTo_slot()), 0, + BUTTON_POPUP_HELP_SYNC); + #endif menuBar()->insertItem(i18n("&Help"), helpPopup); } void PwM::initToolbar() { KIconLoader* picons; #ifndef PWM_EMBEDDED KIconLoader icons; picons = &icons; #else picons = KGlobal::iconLoader(); #endif #ifdef PWM_EMBEDDED if ( QApplication::desktop()->width() > 320 ) #endif { toolBar()->insertButton(picons->loadIcon("filenew", KIcon::Toolbar), BUTTON_TOOL_NEW, SIGNAL(clicked(int)), this, SLOT(new_slot()), true, i18n("New")); toolBar()->insertButton(picons->loadIcon("fileopen", KIcon::Toolbar), BUTTON_TOOL_OPEN, SIGNAL(clicked(int)), this, SLOT(open_slot()), true, i18n("Open")); toolBar()->insertSeparator(); } toolBar()->insertButton(picons->loadIcon("filesave", KIcon::Toolbar), BUTTON_TOOL_SAVE, SIGNAL(clicked(int)), this, SLOT(save_slot()), true, i18n("Save")); toolBar()->insertButton(picons->loadIcon("filesaveas", KIcon::Toolbar), BUTTON_TOOL_SAVEAS, SIGNAL(clicked(int)), this, @@ -580,82 +585,88 @@ void PwM::addPwd_slot() } void PwM::addPwd_slot(QString *pw, PwMDoc *_doc) { PwMDoc *doc; if (_doc) { doc = _doc; } else { doc = curDoc(); } PWM_ASSERT(doc); doc->timer()->getLock(DocTimer::id_autoLockTimer); #ifndef PWM_EMBEDDED AddEntryWndImpl w; #else AddEntryWndImpl w(this, "addentrywndimpl"); #endif vector<string> catList; doc->getCategoryList(&catList); unsigned i, size = catList.size(); for (i = 0; i < size; ++i) { w.addCategory(catList[i].c_str()); } w.setCurrCategory(view->getCurrentCategory()); if (pw) w.pwLineEdit->setText(*pw); tryAgain: if (w.exec() == 1) { PwMDataItem d; + + //US BUG: to initialize all values of curEntr with meaningfulldata, + // we call clear on it. Reason: Metadata will be uninitialized otherwise. + // another option would be to create a constructor for PwMDataItem + d.clear(true); + d.desc = w.getDescription().latin1(); d.name = w.getUsername().latin1(); d.pw = w.getPassword().latin1(); d.comment = w.getComment().latin1(); d.url = w.getUrl().latin1(); d.launcher = w.getLauncher().latin1(); PwMerror ret = doc->addEntry(w.getCategory(), &d); if (ret == e_entryExists) { KMessageBox::error(this, i18n - ("An entry with this \"Description\", " + ("An entry with this \"Description\",\n" "does already exist.\n" "Please select another description."), i18n("entry already exists.")); goto tryAgain; } else if (ret == e_maxAllowedEntr) { - KMessageBox::error(this, i18n("The maximum possible number of entries " - "has been reached. You can't add more entries."), + KMessageBox::error(this, i18n("The maximum possible number of\nentries" + "has been reached.\nYou can't add more entries."), i18n("maximum number of entries")); doc->timer()->putLock(DocTimer::id_autoLockTimer); return; } } setVirgin(false); doc->timer()->putLock(DocTimer::id_autoLockTimer); } //US ENH : changed code to run with older MOC void PwM::editPwd_slot() { editPwd_slot(0,0,0); } void PwM::editPwd_slot(const QString *category) { editPwd_slot(category, 0, 0); } void PwM::editPwd_slot(const QString *category, const int *index, PwMDoc *_doc) { PwMDoc *doc; if (_doc) { doc = _doc; } else { doc = curDoc(); } PWM_ASSERT(doc); if (doc->isDocEmpty()) return; @@ -1258,108 +1269,96 @@ void PwM::copyToClipboard(const QString &s) void PwM::showStatMsg(const QString &msg) { #ifndef PWM_EMBEDDED KStatusBar *statBar = statusBar(); statBar->message(msg, STATUSBAR_MSG_TIMEOUT * 1000); #else qDebug("Statusbar : %s",msg.latin1()); #endif } void PwM::focusInEvent(QFocusEvent *e) { if (e->gotFocus()) { emit gotFocus(this); } else if (e->lostFocus()) { emit lostFocus(this); } } #ifdef PWM_EMBEDDED void PwM::showLicense_slot() { KApplication::showLicence(); } void PwM::faq_slot() { KApplication::showFile( "PWM/Pi FAQ", "kdepim/pwmanager/pwmanagerFAQ.txt" ); } +void PwM::syncHowTo_slot() +{ + qDebug("PwM::syncHowTo_slot"); + KApplication::showFile( "KDE-Pim/Pi Synchronization HowTo", "kdepim/SyncHowto.txt" ); +} + + void PwM::createAboutData_slot() { QString version; #include <../version> QMessageBox::about( this, "About PwManager/Pi", "PwManager/Platform-independent\n" "(PWM/Pi) " +version + " - " + #ifdef DESKTOP_VERSION "Desktop Edition\n" #else "PDA-Edition\n" "for: Zaurus 5500 / 7x0 / 8x0\n" #endif "(c) 2004 Ulf Schenk\n" "(c) 2004 Lutz Rogowski\n" "(c) 1997-2004, The KDE PIM Team\n" "(c) Michael Buesch - main programming\nand current maintainer\nmbuesch@freenet.de\n" "Matt Scifo - mscifo@o1.com\n" "Elias Probst - elias.probst@gmx.de\n" "George Staikos - staikos@kde.org\n" "Matthew Palmer - mjp16@uow.edu.au\n" "Olivier Sessink - gpasman@nl.linux.org\n" "The libgcrypt developers -\nBlowfish and SHA1 algorithms\nftp://ftp.gnupg.org/gcrypt/alpha/libgcrypt/\n" "Troy Engel - tengel@sonic.net\n" "Wickey - wickey@gmx.at\n" "Ian MacGregor - original documentation author.\n" ); } //this are the overwritten callbackmethods from the syncinterface bool PwM::sync(KSyncManager* manager, QString filename, int mode) { PWM_ASSERT(curDoc()); bool ret = curDoc()->sync(manager, filename, mode); + qDebug("PwM::sync save now: ret=%i", ret); + if (ret == true) { //US BUG: what can we call here to update the view of the current doc? //mViewManager->refreshView(); + + //US curDoc()->sync sets the dirtyFlag in case the sync was successfull. + save(); } return ret; } - -//called by the syncmanager to indicate that the work has to be marked as dirty. -void PwM::sync_setModified() -{ - PWM_ASSERT(curDoc()); - curDoc()->sync_setModified(); -} - -//called by the syncmanager to ask if the dirty flag is set. -bool PwM::sync_isModified() -{ - PWM_ASSERT(curDoc()); - return curDoc()->sync_isModified(); -} - -//called by the syncmanager to indicate that the work has to be saved. -void PwM::sync_save() -{ - PWM_ASSERT(curDoc()); - return curDoc()->sync_save(); -} - - - #endif #ifndef PWM_EMBEDDED #include "pwm.moc" #endif diff --git a/pwmanager/pwmanager/pwm.h b/pwmanager/pwmanager/pwm.h index 7c6bf0d..6ed9d34 100644 --- a/pwmanager/pwmanager/pwm.h +++ b/pwmanager/pwmanager/pwm.h @@ -148,64 +148,65 @@ public slots: void execLauncher_slot(); /** open browser with URL entry */ void goToURL_slot(); /** manage/changeMasterPwd triggered */ void changeMasterPwd_slot(); /** lock current document */ void lockWnd_slot(); /** deeplock current document */ void deepLockWnd_slot(); /** window/unlock triggered */ void unlockWnd_slot(); /** find item */ void find_slot(); /** configure clicked */ void config_slot(); /** (de)activate the "change master pw" button in the menu-bar */ void activateMpButton(bool activate = true); /** generate a new chipcard */ void genNewCard_slot(); /** completely erase the current card */ void eraseCard_slot(); /** returns the ID number of the current card */ void readCardId_slot(); /** make backup image of the current card */ void makeCardBackup_slot(); /** write backup image to current card */ void replayCardBackup_slot(); #ifdef PWM_EMBEDDED void showLicense_slot(); void faq_slot(); void createAboutData_slot(); + void syncHowTo_slot(); #endif protected: /** is this window virgin? */ bool isVirgin() { return virgin; } /** add/remove virginity */ void setVirgin(bool v); /** initialize the menubar */ void initMenubar(); /** initialize the toolbar */ void initToolbar(); /** initialize the window-metrics */ void initMetrics(); /** close-event */ void closeEvent(QCloseEvent *e); /** creates a new PwM-ListView and returns it */ PwMView * makeNewListView(PwMDoc *doc); /** Window hide-event */ void hideEvent(QHideEvent *); /** is this window minimized? */ bool isMinimized() { #ifndef PWM_EMBEDDED #if KDE_VERSION >= KDE_MAKE_VERSION(3, 2, 0) return KWin::windowInfo(winId()).isMinimized(); #else // KDE_VERSION return KWin::info(winId()).isIconified(); #endif // KDE_VERSION #else return false; #endif @@ -243,55 +244,48 @@ protected: /** "file" popup-menu */ KPopupMenu *filePopup; /** "manage" popup-menu */ KPopupMenu *managePopup; #ifdef CONFIG_KEYCARD /** "chipcard" popup-menu */ KPopupMenu *chipcardPopup; #endif // CONFIG_KEYCARD /** "view" popup-menu */ KPopupMenu *viewPopup; /** "options" popup-menu */ KPopupMenu *optionsPopup; /** "help" popup-menu */ KPopupMenu *helpPopup; /** "export" popup-menu */ KPopupMenu *exportPopup; /** "import" popup-menu */ KPopupMenu *importPopup; /** force quit this window? */ bool forceQuit; /** force minimize this window to the tray */ bool forceMinimizeToTray; private: #ifdef PWM_EMBEDDED //this 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 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(); - // LR ******************************* // sync stuff! QPopupMenu *syncPopup; KSyncManager* syncManager; #endif }; #endif diff --git a/pwmanager/pwmanager/pwmdoc.cpp b/pwmanager/pwmanager/pwmdoc.cpp index 0ac5517..2a7b11d 100644 --- a/pwmanager/pwmanager/pwmdoc.cpp +++ b/pwmanager/pwmanager/pwmdoc.cpp @@ -458,65 +458,66 @@ PwMerror PwMDoc::saveDoc(char compress, const QString *file) f.close(); ret = e_weakPw; goto out_moveback; } else if (e == e_cryptNotImpl) { printDebug("PwMDoc::saveDoc(): encrypt() failed: e_cryptNotImpl"); f.close(); ret = e_cryptNotImpl; goto out_moveback; } else if (e != e_success) { printDebug("PwMDoc::saveDoc(): encrypt() failed"); f.close(); ret = e_enc; goto out_moveback; } unsetDocStatFlag(DOC_STAT_DISK_DIRTY); f.close(); if (chmod(filename.latin1(), conf()->confGlobFilePermissions())) { printWarn(string("chmod failed: ") + strerror(errno)); } openDocList.edit(this, getTitle().latin1()); if (wasDeepLocked) deepLock(true); if (tmpFileMoved != QString::null) { // now remove the moved file. if (!QFile::remove(tmpFileMoved)) { printWarn(string("removing file ") + tmpFileMoved.latin1() + " failed!"); } } ret = e_success; - printDebug(string("writing file { compress: ") + printDebug(string("writing file { name: ") + + filename.latin1() + " compress: " + tostr(static_cast<int>(compress)) + " cryptAlgo: " + tostr(static_cast<int>(cryptAlgo)) + " hashAlgo: " + tostr(static_cast<int>(hashAlgo)) + " }"); goto out; out_moveback: if (tmpFileMoved != QString::null) { if (copyFile(tmpFileMoved, filename)) { if (!QFile::remove(tmpFileMoved)) { printWarn(string("removing tmp file ") + filename.latin1() + " failed!"); } } else { printWarn(string("couldn't copy file ") + tmpFileMoved.latin1() + " back to " + filename.latin1()); } } out: return ret; } PwMerror PwMDoc::openDoc(const QString *file, int openLocked) { PWM_ASSERT(file); PWM_ASSERT(openLocked == 0 || openLocked == 1 || openLocked == 2); string decrypted, dataHash; PwMerror ret; char cryptAlgo, dataHashType, compress; unsigned int headerLen; @@ -576,65 +577,67 @@ PwMerror PwMDoc::openDoc(const QString *file, int openLocked) f.close(); return e_fileCorrupt; } ret = checkDataHash(dataHashType, &dataHash, &decrypted); if (ret == e_hashNotImpl) { printDebug("PwMDoc::openDoc(): checkDataHash() failed: e_hashNotImpl"); f.close(); return e_hashNotImpl; } else if (ret != e_success) { printDebug("PwMDoc::openDoc(): checkDataHash() failed"); f.close(); return e_fileCorrupt; } if (!deSerializeDta(&decrypted, openLocked == 1)) { printDebug("PwMDoc::openDoc(): deSerializeDta() failed"); f.close(); return e_readFile; } f.close(); timer()->start(DocTimer::id_mpwTimer); timer()->start(DocTimer::id_autoLockTimer); out_success: openDocList.edit(this, getTitle().latin1()); emit docOpened(this); return e_success; } PwMerror PwMDoc::writeFileHeader(char keyHash, char dataHash, char crypt, char compress, QString *pw, QFile *f) { PWM_ASSERT(pw); PWM_ASSERT(f); - PWM_ASSERT(listView); + //US ENH: or maybe a bug: checking here for listView does not make sense because we do not check anywhere else + //Wenn I sync, I open a doc without a view => listView is 0 => Assertion + //US PWM_ASSERT(listView); if (f->writeBlock(FILE_ID_HEADER, strlen(FILE_ID_HEADER)) != static_cast<Q_LONG>(strlen(FILE_ID_HEADER))) { return e_writeFile; } if (f->putch(PWM_FILE_VER) == -1 || f->putch(keyHash) == -1 || f->putch(dataHash) == -1 || f->putch(crypt) == -1 || f->putch(compress) == -1 || f->putch((getDocStatFlag(DOC_STAT_USE_CHIPCARD)) ? (static_cast<char>(0x01)) : (static_cast<char>(0x00))) == -1) { return e_writeFile; } // write bytes of NUL-data. These bytes are reserved for future-use. const int bufSize = 64; char tmp_buf[bufSize]; memset(tmp_buf, 0x00, bufSize); if (f->writeBlock(tmp_buf, bufSize) != bufSize) return e_writeFile; switch (keyHash) { case PWM_HASH_SHA1: { const int hashlen = SHA1_HASH_LEN_BYTE; Sha1 hash; hash.sha1_write(reinterpret_cast<const byte *>(pw->latin1()), pw->length()); string ret = hash.sha1_read(); if (f->writeBlock(ret.c_str(), hashlen) != hashlen) return e_writeFile; break; } case PWM_HASH_SHA256: @@ -2775,108 +2778,141 @@ PwMerror PwMDoc::importFromGpasman(const QString *file) do { ret = gp.load_entry(entry); if(ret != 1) break; tmpData.desc = entry[0]; tmpData.name = entry[1]; tmpData.pw = entry[2]; tmpData.comment = entry[3]; tmpData.lockStat = true; tmpData.listViewPos = -1; ret2 = addEntry(DEFAULT_CATEGORY, &tmpData, true); for (i = 0; i < 4; ++i) free(entry[i]); if (ret2 == e_maxAllowedEntr) { gp.load_finalize(); return e_maxAllowedEntr; } } while (1); gp.load_finalize(); if (isDocEmpty()) return e_wrongPw; // we assume this. flagDirty(); return e_success; } void PwMDoc::ensureLvp() { if (isDocEmpty()) return; + //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 + //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<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; + else + sorted[tmpLvp] = entrI; + //US else if (tmpLvp > lvpTop) + //US lvpTop = tmpLvp; ++entrI; } + + //now we have all undefied in the collection. Now insert the existing + sortedBegin = sorted.begin(); + sortedEnd = sorted.end(); + sortedI = sortedBegin; + + while (sortedI != sortedEnd) { + tmpLvp = (*sortedI)->listViewPos; + undefined[tmpLvp] = *sortedI; + ++sortedI; + } + undefBegin = undefined.begin(); undefEnd = undefined.end(); undefI = undefBegin; while (undefI != undefEnd) { (*undefI)->listViewPos = ++lvpTop; ++undefI; } ++catI; } } QString PwMDoc::getTitle() { /* NOTE: We have to ensure, that the returned title * is unique and not reused somewhere else while * this document is valid (open). */ QString title(getFilename()); + + //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; } } out_accept: deleted = true; delete this; return true; @@ -2898,189 +2934,191 @@ PwMerror PwMDoc::syncronize(KSyncManager* manager, PwMDoc* syncLocal , PwMDoc* s 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()); + 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" ,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()); + // 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("mLastAddressbookSync %s ",mLastAddressbookSync.toString().latin1() ); + 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, inL.summary().latin1()); + qDebug("take %d %s ", take, inLocal->desc.c_str()); 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; //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; @@ -3103,74 +3141,74 @@ PwMerror PwMDoc::syncronize(KSyncManager* manager, PwMDoc* syncLocal , PwMDoc* s // 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 = true;//US ( (*local) == (*remote) ); + 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->summary().latin1(), remote->summary().latin1()); + }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() ); @@ -3186,133 +3224,116 @@ int PwMDoc::takePwMDataItem( PwMDataItem* local, PwMDataItem* remote, QDateTime 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(); //1) unlock local file first if necessary (ask for password) if (this->isDeepLocked()) { PwMerror ret = this->deepLock(false); if (ret != e_success) return false; } - //2) construct and open a new doc on the stack(automatic cleanup) for remote file. + //2) construct and open a new doc on the stack(automatic cleanup of remote file). PwMDoc syncTarget(this, "synctarget"); PwMDoc* pSyncTarget = &syncTarget; PwMerror err = pSyncTarget->openDoc(&filename, 1 /*== open with all entries locked*/); if (err == e_alreadyOpen) { PwMDocList::listItem li; if (getOpenDocList()->find(filename.latin1(), &li)) pSyncTarget = li.doc; else { qDebug("PwmDoc::sync: sync failed. Error %i while opening file %s",err, filename.latin1()); return false; } } else if (err != e_success) { qDebug("PwmDoc::sync: sync failed. Error %i while opening file %s",err, filename.latin1()); return false; } qDebug("PWM file loaded %s,sync mode %d",filename.latin1(), mode ); //3) unlock remote file first if necessary (ask for password) if (pSyncTarget->isDeepLocked()) { PwMerror ret = pSyncTarget->deepLock(false); if (ret != e_success) return false; } err = syncronize(manager, this, pSyncTarget, mode ); if (err == e_success) { if ( manager->mWriteBackFile ) { qDebug("Saving remote PWManager file"); err = pSyncTarget->saveDoc(conf()->confGlobCompression()); if (err != e_success) { qDebug("PwmDoc::sync: Sync failed. Error %i while storing file %s",err, filename.latin1()); return false; } } flagDirty(); return true; } else { return false; } } -//called by the syncmanager to indicate that the work has to marked as dirty. -void PwMDoc::sync_setModified() -{ - flagDirty(); -} - -//called by the syncmanager to ask if the dirty flag is set. -bool PwMDoc::sync_isModified() -{ - return isDirty(); -} - -//called by the syncmanager to indicate that the work has to be saved. -void PwMDoc::sync_save() -{ - 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; diff --git a/pwmanager/pwmanager/pwmdoc.h b/pwmanager/pwmanager/pwmdoc.h index 2e9547e..6a1dd30 100644 --- a/pwmanager/pwmanager/pwmdoc.h +++ b/pwmanager/pwmanager/pwmdoc.h @@ -101,74 +101,64 @@ struct PwMMetaData : updateInt (0) { } /** creation date of the PwMDataItem to which * this meta data belongs. */ QDateTime create; /** becomes valid on this date */ QDateTime valid; /** expire date */ QDateTime expire; /** update date (last updated at this date) */ QDateTime update; /** update interval (in minutes). Time since the * last update to remind the user to update the item. * 0 disables. */ unsigned long updateInt; //US ENH: enhancements of the filestructure /* each entry gets a unique id assigned */ string uniqueid; void clear() { create = QDateTime(); expire = QDateTime(); update = QDateTime(); updateInt = 0; uniqueid = KApplication::randomString(8); } - PwMMetaData& operator = (const PwMMetaData& x) - { - create = x.create; - expire = x.expire; - update = x.update; - updateInt = x.updateInt; - uniqueid = x.uniqueid; - return *this; - } - inline bool isValid() const { if (valid.isNull()) return true; return (valid < QDateTime::currentDateTime()); } inline bool isExpired() const { if (expire.isNull()) return false; return (expire < QDateTime::currentDateTime()); } inline bool isUpdateIntOver() const { if (updateInt == 0 || update.isNull()) return false; QDateTime d(update); return (d.addSecs(updateInt * 60) < QDateTime::currentDateTime()); } }; struct PwMDataItem { PwMDataItem() : lockStat (true) , listViewPos (-1) , binary (false) , rev (0) { } /** password description */ @@ -188,76 +178,92 @@ struct PwMDataItem /** position of this item in main "list-view" * If -1, the position is not yet specified and should be appended to the list */ int listViewPos; /** does this entry contain binary data? */ bool binary; /** meta data for this data item. */ PwMMetaData meta; /** data revision counter. This counter can be used * to easily, efficiently determine if this data item * has changed since some time. * This counter is incremented on every update. */ unsigned int rev; void clear(bool clearMeta = true) { /* NOTE: Don't use .clear() here to be * backward compatible with gcc-2 (Debian Woody) */ desc = ""; name = ""; pw = ""; comment = ""; url = ""; launcher = ""; lockStat = true; listViewPos = -1; binary = false; if (clearMeta) meta.clear(); } - + //US ENH: we need this operator to compare two items if we have no unique ids + //available. Generaly this happens before the first sync + bool PwMDataItem::operator==( const PwMDataItem &a ) const + { + qDebug("oper==%s", a.desc.c_str()); + if ( desc != a.desc ) return false; + if ( name != a.name ) return false; + if ( pw != a.pw ) return false; + if ( comment != a.comment ) return false; + if ( url != a.url ) return false; + if ( launcher != a.launcher ) return false; + //all other field will not be checked. + return true; + } + + //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()); + // 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; - listViewPos = x.listViewPos; + //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 = ""; } @@ -745,62 +751,55 @@ protected: 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/pwmview.cpp b/pwmanager/pwmanager/pwmview.cpp index e23ce25..e53124f 100644 --- a/pwmanager/pwmanager/pwmview.cpp +++ b/pwmanager/pwmanager/pwmview.cpp @@ -427,95 +427,175 @@ void PwMView::copyUrlToClip() unsigned int curIndex = 0; if (!getCurEntryIndex(&curIndex)) return; PwMDataItem d; document()->getEntry(getCurrentCategory(), curIndex, &d); PwM::copyToClipboard(d.url.c_str()); } void PwMView::copyLauncherToClip() { if (doc->isDeepLocked()) return; unsigned int curIndex = 0; if (!getCurEntryIndex(&curIndex)) return; PwMDataItem d; document()->getEntry(getCurrentCategory(), curIndex, &d); PwM::copyToClipboard(d.launcher.c_str()); } void PwMView::copyCommentToClip() { if (doc->isDeepLocked()) return; unsigned int curIndex = 0; if (!getCurEntryIndex(&curIndex)) return; PwMDataItem d; document()->getEntry(getCurrentCategory(), curIndex, &d); PwM::copyToClipboard(d.comment.c_str()); } +/************************************************************************ + * + * + * + ************************************************************************/ + + +PwMDataItemView::PwMDataItemView( QWidget *parent, const char *name ) + : QTextBrowser( parent, name ) + + +{ +//US setWrapPolicy( QTextEdit::AtWordBoundary ); + setLinkUnderline( false ); + // setVScrollBarMode( QScrollView::AlwaysOff ); + //setHScrollBarMode( QScrollView::AlwaysOff ); + +//US QStyleSheet *sheet = styleSheet(); +//US QStyleSheetItem *link = sheet->item( "a" ); +//US link->setColor( KGlobalSettings::linkColor() ); + +} + +void PwMDataItemView::setPwMDataItem( const PwMDataItem& a ) + +{ + mItem = a; + // clear view + setText( QString::null ); + + + QString dynamicPart; + QString format = "<tr><td align=\"right\"><b>%1</b></td>" + "<td align=\"left\">%2</td></tr>"; + + dynamicPart += format + .arg( i18n("Description") ) + .arg( mItem.desc.c_str() ); + dynamicPart += format + .arg( i18n("Name") ) + .arg( mItem.name.c_str() ); + + dynamicPart += format + .arg( i18n("Password") ) + .arg( mItem.pw.c_str() ); + + QString comment(mItem.pw.c_str()); + dynamicPart += format + .arg( i18n("Comment") ) + .arg( comment.replace( QRegExp("\n"), "<br>" ) ); + + dynamicPart += format + .arg( i18n("URL") ) + .arg( mItem.url.c_str() ); + + dynamicPart += format + .arg( i18n("Launcher") ) + .arg( mItem.launcher.c_str() ); + + QString mText = "<table><td colspan=\"2\"> </td>"; + + mText += dynamicPart; + mText += "</table>"; + + // at last display it... + setText( mText ); + +} + +PwMDataItem PwMDataItemView::pwmdataitem() const +{ + return mItem; +} + +/************************************************************************ + * + * + * + ************************************************************************/ -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) +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 ); + PwMDataItemView * av = new PwMDataItemView( subframe ); + av->setPwMDataItem( 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 ); + av = new PwMDataItemView( subframe ); + av->setPwMDataItem( 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(); } diff --git a/pwmanager/pwmanager/pwmview.h b/pwmanager/pwmanager/pwmview.h index 75cce51..e42b17a 100644 --- a/pwmanager/pwmanager/pwmview.h +++ b/pwmanager/pwmanager/pwmview.h @@ -12,64 +12,65 @@ /*************************************************************************** * copyright (C) 2004 by Ulf Schenk * This file is originaly based on version 1.0.1 of pwmanager * and was modified to run on embedded devices that run microkde * * $Id$ **************************************************************************/ #ifndef PWMVIEW_H #define PWMVIEW_H //US ENH: wouldn't it be a good idea if we could use this consts everywhere else. //US ENH: for examle in listviewpwm.cpp //US ENH: Because of that I transfer them into the headerfile. #define COLUMN_DESC 0 #define COLUMN_NAME 1 #define COLUMN_PW 2 #define COLUMN_URL 3 #define COLUMN_LAUNCHER 4 #include "listviewpwm.h" #include "pwmdoc.h" #include "pwmviewstyle.h" #include <kconfig.h> #include <klocale.h> #include <kdialogbase.h> #include <qevent.h> #include <qfont.h> #include <qobject.h> +#include <qtextbrowser.h> #include <vector> #include <string> using std::string; using std::vector; class PwM; class ConfFile; class PwMStatusBar; /** View class for PwM */ class PwMView : public PwMViewStyle { Q_OBJECT friend class PwMViewStyle; public: /** construtor */ PwMView(PwM *_mainClass, QWidget* parent, PwMDoc *_doc, const char *name = 0); /** destructor */ ~PwMView(); /** returns pointer to the document */ PwMDoc* document() { return doc; } /** returns the index of the currently selected entry. * (index as represented in PwMDoc !) */ bool getCurEntryIndex(unsigned int *index); /** returns the position of the given item in the document @@ -120,53 +121,77 @@ protected: } /** The user pressed and released a key. */ void keyReleaseEvent(QKeyEvent *e); protected slots: /** changes the comment text-edit, because a new item has been selected */ void refreshCommentTextEdit(QListViewItem *curItem); /** copy pw to clipboard */ void copyPwToClip(); /** copy name to clipboard */ void copyNameToClip(); /** copy desc to clipboard */ void copyDescToClip(); /** copy url to clipboard */ void copyUrlToClip(); /** copy launcher to clipboard */ void copyLauncherToClip(); /** copy comment to clipboard */ void copyCommentToClip(); /** reorganize the "listViewPos" positions in the document * (for the current category only!) */ void reorgLp(); private: /** document */ PwMDoc *doc; /** pointer to the main class "PwM" */ PwM *mainClass; }; +//US ENH basic widget to view an password entry. We need it for the sync stuff. +//But might be oif interest for other functionalities as well. +class PwMDataItemView : public QTextBrowser +{ + public: + PwMDataItemView( QWidget *parent = 0, const char *name = 0 ); + + /** + Sets the PwMDataItem object. It is displayed immediately. + + @param a The PwMDataItem object. + */ + void setPwMDataItem( const PwMDataItem& a ); + + /** + Returns the current PwMDataItem object. + */ + PwMDataItem pwmdataitem() const; + + private: + PwMDataItem mItem; +}; + + //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 203f82c..5c6568f 100644 --- a/pwmanager/pwmanager/serializer.cpp +++ b/pwmanager/pwmanager/serializer.cpp @@ -1,62 +1,62 @@ /*************************************************************************** * * * copyright (C) 2004 by Michael Buesch * * email: mbuesch@freenet.de * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License version 2 * * as published by the Free Software Foundation. * * * ***************************************************************************/ /*************************************************************************** * copyright (C) 2004 by Ulf Schenk * This file is originaly based on version 2.0 of pwmanager * and was modified to run on embedded devices that run microkde * * $Id$ **************************************************************************/ #include "serializer.h" #include "pwmexception.h" #ifdef PWM_EMBEDDED #include <kglobal.h> #include <klocale.h> #endif /* enable/disable serializer debugging (0/1) */ -#define SERIALIZER_DEBUG 0 +#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" @@ -275,64 +275,68 @@ bool Serializer::readCategories(const QDomNode &n, } for (i = 0; i < numCat; ++i) { cur = nl.item(i); if (cur.nodeName().left(1) == CAT_PREFIX_NEW || cur.nodeName().left(4) == CAT_PREFIX_OLD) { name = cur.toElement().attribute(CAT_NAME_NEW); if (name == QString::null) name = cur.toElement().attribute(CAT_NAME_OLD); PWM_ASSERT(name != QString::null); PWM_ASSERT(name != ""); curCat.clear(); curCat.name = name.latin1(); if (!readEntries(cur, &curEntr)) { dta->clear(); return false; } curCat.d = curEntr; dta->push_back(curCat); } else { printDebug("Serializer::readCategories(): uh? not a category?"); } } return true; } bool Serializer::readEntries(const QDomNode &n, vector<PwMDataItem> *dta) { QDomNodeList nl(n.childNodes()); QDomNode cur; unsigned int numEntr = nl.count(), i; PwMDataItem curEntr; + //US BUG: to initialize all values of curEntr with meaningfulldata, + // we call clear on it. Reason: Information in the file we will read might be incomplete. + // e.g. the metadata is missing. + curEntr.clear(true); dta->clear(); for (i = 0; i < numEntr; ++i) { cur = nl.item(i); if (cur.nodeName().left(1) == ENTRY_PREFIX_NEW || cur.nodeName().left(6) == ENTRY_PREFIX_OLD) { if (!extractEntry(cur, &curEntr)) { return false; } dta->push_back(curEntr); } else { printDebug("Serializer::readEntries(): hm? not an entry?"); } } return true; } bool Serializer::extractEntry(const QDomNode &n, PwMDataItem *dta) { QDomNodeList nl(n.childNodes()); QDomNode cur, cdata; unsigned int cnt = nl.count(), i; QString name, text; if (!cnt) { printDebug("Serializer::extractEntry(): empty"); return false; } dta->clear(); for (i = 0; i < cnt; ++i) { cur = nl.item(i); @@ -372,108 +376,109 @@ bool Serializer::extractEntry(const QDomNode &n, } else if (name == ENTRY_BIN_NEW) { // ENTRY_BIN_NEW == ENTRY_BIN_OLD if (text == "0") { dta->binary = false; } else { dta->binary = true; } } else if (name == ENTRY_META_NEW) { // ENTRY_META_NEW == ENTRY_META_OLD if (!extractMeta(cur, &dta->meta)) return false; } else { printDebug(string("Serializer::extractEntry(): invalid: ") + name.latin1()); } } dta->lockStat = defaultLockStat; return true; } bool Serializer::extractMeta(const QDomNode &n, PwMMetaData *dta) { QDomNode cur(n.firstChild()); QString name, val; while (!cur.isNull()) { name = cur.nodeName(); val = cur.toElement().text(); if (val == "") { cur = cur.nextSibling(); continue; } + + //US BUG: The transformation of an empty date into an ISO date and back is different on different systems/compilers. + //because of that it is possible that here some values are not set, which means they are null. + //US ENH: at the same moment we need backwardcompatibility. So older versions might have stored invalid dates. + + QDateTime dtval; //dtval should be invalid by definition. + + if ((name == META_CREATE_DATE) || + (name == META_VALID_DATE) || + (name == META_EXPIRE_DATE) || + (name == META_UPDATE_DATE)) + { + //qDebug("Serializer::extractMeta:: val:%s, empty:%i, length:%i",val.utf8(), val.isEmpty(), val.length()); + #ifndef PWM_EMBEDDED - if (name == META_CREATE_DATE) { - dta->create = QDateTime::fromString(val, Qt::ISODate); - } else if (name == META_VALID_DATE) { - dta->valid = QDateTime::fromString(val, Qt::ISODate); - } else if (name == META_EXPIRE_DATE) { - dta->expire = QDateTime::fromString(val, Qt::ISODate); - } else if (name == META_UPDATE_DATE) { - dta->update = QDateTime::fromString(val, Qt::ISODate); - } else if (name == META_UPDATE_INT) { - dta->updateInt = strtoul(val.latin1(), 0, 10); - } else if (name == META_UNIQUEID) { - dta->uniqueid = unescapeEntryData(val).latin1(); - } else { - printDebug(string("extractMeta(): invalid: ") - + name.latin1()); - } + dtval = QDateTime::fromString(val, Qt::ISODate); #else + bool ok; + dtval = KGlobal::locale()->readDateTime(val, KLocale::ISODate, &ok); + + if (ok == false) + qDebug("Serializer::extractMeta invalid date or time !!!!!!!!!!!!!"); +#endif + //if the parsed data is wrong, dtval should be invalid at this time. - bool ok = true; + } if (name == META_CREATE_DATE) { - dta->create = KGlobal::locale()->readDateTime(val, KLocale::ISODate, &ok); + dta->create = dtval; } else if (name == META_VALID_DATE) { - dta->valid = KGlobal::locale()->readDateTime(val, KLocale::ISODate, &ok); + dta->valid = dtval; } else if (name == META_EXPIRE_DATE) { - dta->expire = KGlobal::locale()->readDateTime(val, KLocale::ISODate, &ok); + dta->expire = dtval; } else if (name == META_UPDATE_DATE) { - dta->update = KGlobal::locale()->readDateTime(val, KLocale::ISODate, &ok); + dta->update = dtval; } else if (name == META_UPDATE_INT) { dta->updateInt = strtoul(val.latin1(), 0, 10); } else if (name == META_UNIQUEID) { dta->uniqueid = unescapeEntryData(val).latin1(); } else { printDebug(string("extractMeta(): invalid: ") + name.latin1()); } - if (ok == false) - qDebug("Serializer::extractMeta invalid date or time !!!!!!!!!!!!!"); - - -#endif cur = cur.nextSibling(); } return true; } bool Serializer::checkValid() { PWM_ASSERT(domDoc); QDomElement root(domDoc->documentElement()); if (root.nodeName() != ROOT_MAGIC_NEW && root.nodeName() != ROOT_MAGIC_OLD) { printDebug("Serializer: wrong magic"); return false; } if (root.attribute(VER_STR_NEW) != COMPAT_VER_NEW && root.attribute(VER_STR_OLD) != COMPAT_VER_OLD) { printDebug("Serializer: wrong version"); return false; } return true; } QDomElement Serializer::genNewRoot() { PWM_ASSERT(domDoc); QDomElement root(domDoc->createElement(ROOT_MAGIC_WR)); root.setAttribute(VER_STR_WR, COMPAT_VER_WR); domDoc->appendChild(root); return root; } bool Serializer::addCategories(QDomElement *e, @@ -575,182 +580,201 @@ bool Serializer::writeEntry(QDomElement *e, curText = new_text(escapeEntryData(dta.launcher.c_str())); tag.appendChild(curText); e->appendChild(tag); tag = domDoc->createElement(ENTRY_LVP_WR); plainText = domDoc->createTextNode(tostr(dta.listViewPos).c_str()); tag.appendChild(plainText); e->appendChild(tag); tag = domDoc->createElement(ENTRY_BIN_WR); if (dta.binary) plainText = domDoc->createTextNode("1"); else plainText = domDoc->createTextNode("0"); tag.appendChild(plainText); e->appendChild(tag); tag = domDoc->createElement(ENTRY_META_WR); if (!writeMeta(&tag, dta.meta)) return false; e->appendChild(tag); #undef new_text return true; } bool Serializer::writeMeta(QDomElement *e, const PwMMetaData &dta) { QDomText text; QDomElement tag; - tag = domDoc->createElement(META_CREATE_DATE); + //US BUG!!!: The transformation of an empty date into an ISO date is different on different systems/compilers. + //So do not transform an empty value at all. + if (dta.create.isValid()) + { + tag = domDoc->createElement(META_CREATE_DATE); #ifndef PWM_EMBEDDED - text = domDoc->createTextNode(dta.create.toString(Qt::ISODate)); + text = domDoc->createTextNode(dta.create.toString(Qt::ISODate)); #else - text = domDoc->createTextNode(KGlobal::locale()->formatDateTime(dta.create, KLocale::ISODate)); + text = domDoc->createTextNode(KGlobal::locale()->formatDateTime(dta.create, KLocale::ISODate)); #endif - tag.appendChild(text); - e->appendChild(tag); + tag.appendChild(text); + e->appendChild(tag); + } - tag = domDoc->createElement(META_VALID_DATE); + //US BUG!!!: The transformation of an empty date into an ISO date is different on different systems/compilers. + //So do not transform an empty value at all. + if (dta.valid.isValid()) + { + tag = domDoc->createElement(META_VALID_DATE); #ifndef PWM_EMBEDDED - text = domDoc->createTextNode(dta.valid.toString(Qt::ISODate)); + text = domDoc->createTextNode(dta.valid.toString(Qt::ISODate)); #else - text = domDoc->createTextNode(KGlobal::locale()->formatDateTime(dta.valid, KLocale::ISODate)); + text = domDoc->createTextNode(KGlobal::locale()->formatDateTime(dta.valid, KLocale::ISODate)); #endif - tag.appendChild(text); - e->appendChild(tag); + tag.appendChild(text); + e->appendChild(tag); + } - tag = domDoc->createElement(META_EXPIRE_DATE); + //US BUG!!!: The transformation of an empty date into an ISO date is different on different systems/compilers. + //So do not transform an empty value at all. + if (dta.expire.isValid()) + { + tag = domDoc->createElement(META_EXPIRE_DATE); #ifndef PWM_EMBEDDED - text = domDoc->createTextNode(dta.expire.toString(Qt::ISODate)); + text = domDoc->createTextNode(dta.expire.toString(Qt::ISODate)); #else - text = domDoc->createTextNode(KGlobal::locale()->formatDateTime(dta.expire, KLocale::ISODate)); + text = domDoc->createTextNode(KGlobal::locale()->formatDateTime(dta.expire, KLocale::ISODate)); #endif - tag.appendChild(text); - e->appendChild(tag); + tag.appendChild(text); + e->appendChild(tag); + } - tag = domDoc->createElement(META_UPDATE_DATE); + //US BUG!!!: The transformation of an empty date into an ISO date is different on different systems/compilers. + //So do not transform an empty value at all. + if (dta.update.isValid()) + { + tag = domDoc->createElement(META_UPDATE_DATE); #ifndef PWM_EMBEDDED - text = domDoc->createTextNode(dta.update.toString(Qt::ISODate)); + text = domDoc->createTextNode(dta.update.toString(Qt::ISODate)); #else - text = domDoc->createTextNode(KGlobal::locale()->formatDateTime(dta.update, KLocale::ISODate)); + text = domDoc->createTextNode(KGlobal::locale()->formatDateTime(dta.update, KLocale::ISODate)); #endif - tag.appendChild(text); - e->appendChild(tag); + tag.appendChild(text); + e->appendChild(tag); + } tag = domDoc->createElement(META_UPDATE_INT); text = domDoc->createTextNode(tostr(dta.updateInt).c_str()); tag.appendChild(text); e->appendChild(tag); tag = domDoc->createElement(META_UNIQUEID); text = domDoc->createTextNode(escapeEntryData(dta.uniqueid.c_str())); tag.appendChild(text); e->appendChild(tag); #undef new_text return true; } QString Serializer::escapeEntryData(QString dta) { #ifndef PWM_EMBEDDED dta.replace('\n', "$>--endl--<$"); dta.replace("]]>", "||>"); #else dta.replace(QRegExp("\n"), "$>--endl--<$"); dta.replace(QRegExp("]]>"), "||>"); #endif return dta; } QString Serializer::unescapeEntryData(QString dta) { #ifndef PWM_EMBEDDED dta.replace("$>--endl--<$", "\n"); dta.replace("||>", "]]>"); #else - dta.replace(QRegExp("$>--endl--<$"), "\n"); + dta.replace(QRegExp("\\$>--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; + QDomElement curSync; 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); + curSync.appendChild(text); e->appendChild(curSync); } return true; } |