Fix: Different qm files in different paths, no overruling (Bug #2657158)
Fix: Unable to open kdb from read-only location (Bug #2657228) git-svn-id: https://svn.code.sf.net/p/keepassx/code/trunk@279 b624d157-de02-0410-bad0-e51aec6abb33
This commit is contained in:
parent
df17d76ce7
commit
139078801c
|
@ -246,7 +246,7 @@ public:
|
|||
\param identifier Normally this is the filename of the database but it can also be an IP address or something else if the database is not file based.
|
||||
\return TRUE if loading was successfull, otherwise FALSE.
|
||||
*/
|
||||
virtual bool load(QString identifier)=0;
|
||||
virtual bool load(QString identifier, bool readOnly)=0;
|
||||
|
||||
//! Saves the current database.
|
||||
/*! It is not allowed to call this function if no database is loaded.
|
||||
|
|
|
@ -493,8 +493,8 @@ void Kdb3Database::restoreGroupTreeState(){
|
|||
}
|
||||
}
|
||||
|
||||
bool Kdb3Database::load(QString identifier){
|
||||
return loadReal(identifier, false);
|
||||
bool Kdb3Database::load(QString identifier, bool readOnly){
|
||||
return loadReal(identifier, readOnly, false);
|
||||
}
|
||||
|
||||
#define LOAD_RETURN_CLEANUP \
|
||||
|
@ -503,7 +503,7 @@ bool Kdb3Database::load(QString identifier){
|
|||
delete[] buffer; \
|
||||
return false;
|
||||
|
||||
bool Kdb3Database::loadReal(QString filename, bool differentEncoding) {
|
||||
bool Kdb3Database::loadReal(QString filename, bool readOnly, bool differentEncoding) {
|
||||
unsigned long total_size,crypto_size;
|
||||
quint32 Signature1,Signature2,Version,NumGroups,NumEntries,Flags;
|
||||
quint8 FinalRandomSeed[16];
|
||||
|
@ -511,7 +511,7 @@ bool Kdb3Database::loadReal(QString filename, bool differentEncoding) {
|
|||
quint8 EncryptionIV[16];
|
||||
|
||||
File = new QFile(filename);
|
||||
if(!File->open(QIODevice::ReadWrite)){
|
||||
if (readOnly) {
|
||||
if(!File->open(QIODevice::ReadOnly)){
|
||||
error=tr("Could not open file.");
|
||||
delete File;
|
||||
|
@ -519,6 +519,20 @@ bool Kdb3Database::loadReal(QString filename, bool differentEncoding) {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(!File->open(QIODevice::ReadWrite)){
|
||||
if(!File->open(QIODevice::ReadOnly)){
|
||||
error=tr("Could not open file.");
|
||||
delete File;
|
||||
File = NULL;
|
||||
return false;
|
||||
}
|
||||
else{
|
||||
readOnly = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
total_size=File->size();
|
||||
char* buffer = new char[total_size];
|
||||
File->read(buffer,total_size);
|
||||
|
@ -604,7 +618,7 @@ bool Kdb3Database::loadReal(QString filename, bool differentEncoding) {
|
|||
RawMasterKey.copyData(RawMasterKey_Latin1);
|
||||
PotentialEncodingIssueLatin1 = false;
|
||||
qDebug("Decryption failed. Retrying with Latin-1.");
|
||||
return loadReal(filename, true); // second try
|
||||
return loadReal(filename, readOnly, true); // second try
|
||||
}
|
||||
if(PotentialEncodingIssueUTF8){
|
||||
delete[] buffer;
|
||||
|
@ -614,7 +628,7 @@ bool Kdb3Database::loadReal(QString filename, bool differentEncoding) {
|
|||
RawMasterKey.copyData(RawMasterKey_UTF8);
|
||||
PotentialEncodingIssueUTF8 = false;
|
||||
qDebug("Decryption failed. Retrying with UTF-8.");
|
||||
return loadReal(filename, true); // second/third try
|
||||
return loadReal(filename, readOnly, true); // second/third try
|
||||
}
|
||||
error=tr("Hash test failed.\nThe key is wrong or the file is damaged.");
|
||||
KeyError=true;
|
||||
|
@ -1318,13 +1332,8 @@ bool Kdb3Database::save(){
|
|||
quint8 EncryptionIV[16];
|
||||
|
||||
if(!(File->openMode() & QIODevice::WriteOnly)){
|
||||
File->close();
|
||||
}
|
||||
if(!File->isOpen()){
|
||||
if(!File->open(QIODevice::ReadWrite)){
|
||||
error = tr("Could not open file for writing.");
|
||||
return false;
|
||||
}
|
||||
error = tr("The database has been opened read-only.");
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int FileSize;
|
||||
|
|
|
@ -135,7 +135,7 @@ public:
|
|||
|
||||
Kdb3Database();
|
||||
virtual ~Kdb3Database(){};
|
||||
virtual bool load(QString identifier);
|
||||
virtual bool load(QString identifier, bool readOnly);
|
||||
virtual bool save();
|
||||
virtual bool close();
|
||||
virtual void create();
|
||||
|
@ -190,7 +190,7 @@ public:
|
|||
inline bool hasPasswordEncodingChanged() { return passwordEncodingChanged; };
|
||||
|
||||
private:
|
||||
bool loadReal(QString filename, bool differentEncoding);
|
||||
bool loadReal(QString filename, bool readOnly, bool differentEncoding);
|
||||
QDateTime dateFromPackedStruct5(const unsigned char* pBytes);
|
||||
void dateToPackedStruct5(const QDateTime& datetime, unsigned char* dst);
|
||||
bool isMetaStream(StdEntry& Entry);
|
||||
|
|
|
@ -477,8 +477,7 @@
|
|||
|
||||
|
||||
void Twofish_fatal(const char* msg){
|
||||
qCritical("Twofish: Fatal Error: %s",msg);
|
||||
exit(1);
|
||||
qFatal("Twofish: Fatal Error: %s", msg);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -92,13 +92,15 @@ void SecString::overwrite(QString& str){
|
|||
|
||||
void SecString::generateSessionKey(){
|
||||
sessionkey = new quint8[32];
|
||||
lockPage(sessionkey, 32);
|
||||
if (!lockPage(sessionkey, 32))
|
||||
qDebug("Failed to lock session key page");
|
||||
randomize(sessionkey, 32);
|
||||
RC4.setKey(sessionkey, 32);
|
||||
}
|
||||
|
||||
void SecString::deleteSessionKey() {
|
||||
overwrite(sessionkey, 32);
|
||||
unlockPage(sessionkey, 32);
|
||||
delete[] sessionkey;
|
||||
}
|
||||
|
||||
|
|
|
@ -56,21 +56,21 @@ void createBanner(QPixmap* Pixmap,const QPixmap* IconAlpha,const QString& Text,i
|
|||
|
||||
QString decodeFileError(QFile::FileError Code){
|
||||
switch(Code){
|
||||
case QFile::NoError: return QApplication::translate("FileErrors","No error occurred.");
|
||||
case QFile::ReadError: return QApplication::translate("FileErrors","An error occurred while reading from the file.");
|
||||
case QFile::WriteError: return QApplication::translate("FileErrors","An error occurred while writing to the file.");
|
||||
case QFile::FatalError: return QApplication::translate("FileErrors","A fatal error occurred.");
|
||||
case QFile::ResourceError: return QApplication::translate("FileErrors","An resource error occurred.");
|
||||
case QFile::OpenError: return QApplication::translate("FileErrors","The file could not be opened.");
|
||||
case QFile::AbortError: return QApplication::translate("FileErrors","The operation was aborted.");
|
||||
case QFile::TimeOutError: return QApplication::translate("FileErrors","A timeout occurred.");
|
||||
case QFile::UnspecifiedError: return QApplication::translate("FileErrors","An unspecified error occurred.");
|
||||
case QFile::RemoveError: return QApplication::translate("FileErrors","The file could not be removed.");
|
||||
case QFile::RenameError: return QApplication::translate("FileErrors","The file could not be renamed.");
|
||||
case QFile::PositionError: return QApplication::translate("FileErrors","The position in the file could not be changed.");
|
||||
case QFile::ResizeError: return QApplication::translate("FileErrors","The file could not be resized.");
|
||||
case QFile::PermissionsError: return QApplication::translate("FileErrors","The file could not be accessed.");
|
||||
case QFile::CopyError: return QApplication::translate("FileErrors","The file could not be copied.");
|
||||
case QFile::NoError: return QApplication::translate("FileErrors","No error occurred.");
|
||||
case QFile::ReadError: return QApplication::translate("FileErrors","An error occurred while reading from the file.");
|
||||
case QFile::WriteError: return QApplication::translate("FileErrors","An error occurred while writing to the file.");
|
||||
case QFile::FatalError: return QApplication::translate("FileErrors","A fatal error occurred.");
|
||||
case QFile::ResourceError: return QApplication::translate("FileErrors","An resource error occurred.");
|
||||
case QFile::OpenError: return QApplication::translate("FileErrors","The file could not be opened.");
|
||||
case QFile::AbortError: return QApplication::translate("FileErrors","The operation was aborted.");
|
||||
case QFile::TimeOutError: return QApplication::translate("FileErrors","A timeout occurred.");
|
||||
case QFile::UnspecifiedError: return QApplication::translate("FileErrors","An unspecified error occurred.");
|
||||
case QFile::RemoveError: return QApplication::translate("FileErrors","The file could not be removed.");
|
||||
case QFile::RenameError: return QApplication::translate("FileErrors","The file could not be renamed.");
|
||||
case QFile::PositionError: return QApplication::translate("FileErrors","The position in the file could not be changed.");
|
||||
case QFile::ResizeError: return QApplication::translate("FileErrors","The file could not be resized.");
|
||||
case QFile::PermissionsError: return QApplication::translate("FileErrors","The file could not be accessed.");
|
||||
case QFile::CopyError: return QApplication::translate("FileErrors","The file could not be copied.");
|
||||
}
|
||||
return QString();
|
||||
}
|
||||
|
@ -134,21 +134,20 @@ QString makePathRelative(const QString& AbsDir,const QString& CurDir){
|
|||
}
|
||||
|
||||
void showErrMsg(const QString& msg,QWidget* parent){
|
||||
QMessageBox::critical(parent,QApplication::translate("Main","Error"),msg,QApplication::translate("Main","OK"));
|
||||
QMessageBox::critical(parent, QApplication::translate("Main","Error"), msg);
|
||||
}
|
||||
|
||||
QString getImageFile(const QString& name){
|
||||
if (QFile::exists(DataDir+"/icons/"+name))
|
||||
return DataDir+"/icons/"+name;
|
||||
else{
|
||||
QMessageBox::critical(0,QApplication::translate("Main","Error"),
|
||||
QApplication::translate("Main","File '%1' could not be found.")
|
||||
.arg(name),QApplication::translate("Main","OK"),0,0,2,1);
|
||||
exit(1);
|
||||
QString errMsg = QApplication::translate("Main","File '%1' could not be found.").arg(name);
|
||||
showErrMsg(errMsg);
|
||||
qFatal("File '%s' could not be found.", CSTR(errMsg));
|
||||
return QString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const QIcon& getIcon(const QString& name){
|
||||
static QHash<QString,QIcon*>IconCache;
|
||||
QIcon* CachedIcon=IconCache.value(name);
|
||||
|
@ -284,7 +283,7 @@ void installTranslator(){
|
|||
}
|
||||
|
||||
if (loadTranslation(translator,"keepassx-",language,QStringList()
|
||||
<< DataDir+"/i18n/" << HomeDir))
|
||||
<< HomeDir << DataDir+"/i18n/"))
|
||||
{
|
||||
if (!translatorActive){
|
||||
QApplication::installTranslator(translator);
|
||||
|
@ -297,8 +296,8 @@ void installTranslator(){
|
|||
}
|
||||
|
||||
if (loadTranslation(qtTranslator,"qt_",language,QStringList()
|
||||
<< QLibraryInfo::location(QLibraryInfo::TranslationsPath)
|
||||
<< DataDir+"/i18n/" << HomeDir))
|
||||
<< HomeDir << DataDir+"/i18n/"
|
||||
<< QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
|
||||
{
|
||||
if (!qtTranslatorActive){
|
||||
QApplication::installTranslator(qtTranslator);
|
||||
|
|
|
@ -48,6 +48,8 @@ IIconTheme* IconLoader=NULL;
|
|||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
QT_REQUIRE_VERSION(argc, argv, "4.3.0");
|
||||
|
||||
#if defined(Q_WS_X11) && defined(GLOBAL_AUTOTYPE)
|
||||
QApplication* app = new KeepassApplication(argc,argv);
|
||||
#else
|
||||
|
|
|
@ -78,12 +78,12 @@ KeepassMainWindow::KeepassMainWindow(const QString& ArgFile,bool ArgMin,bool Arg
|
|||
setStateFileOpen(false);
|
||||
setupMenus();
|
||||
DetailView->setVisible(config->showEntryDetails());
|
||||
statusbarState = 0;
|
||||
StatusBarGeneral=new QLabel(tr("Ready"),statusBar());
|
||||
StatusBarGeneral=new QLabel(statusBar());
|
||||
//StatusBarSelection=new QLabel(statusBar());
|
||||
statusBar()->addWidget(StatusBarGeneral,15);
|
||||
//statusBar()->addWidget(StatusBarSelection,85);
|
||||
statusBar()->setVisible(config->showStatusbar());
|
||||
setStatusBarMsg(StatusBarReady);
|
||||
|
||||
NormalCentralWidget=QMainWindow::centralWidget();
|
||||
LockedCentralWidget=new QWidget(this);
|
||||
|
@ -398,19 +398,27 @@ bool KeepassMainWindow::openDatabase(QString filename,bool IsAuto){
|
|||
return false;
|
||||
}
|
||||
|
||||
dbReadOnly = false;
|
||||
|
||||
if (QFile::exists(filename+".lock")){
|
||||
QMessageBox::StandardButton buttonPressed = QMessageBox::question(
|
||||
this,
|
||||
tr("Database locked"),
|
||||
tr("The database you are trying to open is locked.\n"
|
||||
QMessageBox msgBox(this);
|
||||
msgBox.setIcon(QMessageBox::Question);
|
||||
msgBox.setWindowTitle(tr("Database locked"));
|
||||
msgBox.setText(tr("The database you are trying to open is locked.\n"
|
||||
"This means that either someone else has opened the file or KeePassX crashed last time it opened the database.\n\n"
|
||||
"Do you want to open it anyway?"
|
||||
),
|
||||
QMessageBox::Yes|QMessageBox::No,
|
||||
QMessageBox::No
|
||||
);
|
||||
if (buttonPressed != QMessageBox::Yes)
|
||||
));
|
||||
msgBox.addButton(QMessageBox::Yes);
|
||||
msgBox.addButton(QMessageBox::No);
|
||||
QPushButton* readOnlyButton = new QPushButton(tr("Open read-only"), &msgBox);
|
||||
msgBox.addButton(readOnlyButton, QMessageBox::AcceptRole);
|
||||
msgBox.setDefaultButton(readOnlyButton);
|
||||
msgBox.exec();
|
||||
|
||||
if (!msgBox.clickedButton() || msgBox.clickedButton() == msgBox.button(QMessageBox::No))
|
||||
return false;
|
||||
else if (msgBox.clickedButton() == readOnlyButton)
|
||||
dbReadOnly = true;
|
||||
}
|
||||
|
||||
if(!IsAuto){
|
||||
|
@ -439,18 +447,18 @@ bool KeepassMainWindow::openDatabase(QString filename,bool IsAuto){
|
|||
EntryView->db=db;
|
||||
setupDatabaseConnections(db);
|
||||
QString err;
|
||||
statusbarState = 1;
|
||||
StatusBarGeneral->setText(tr("Loading Database..."));
|
||||
setStatusBarMsg(StatusBarLoading);
|
||||
db->setKey(dlg.password(),dlg.keyFile());
|
||||
if(db->load(filename)){
|
||||
if (!QFile::exists(filename+".lock")){
|
||||
QFile lock(filename+".lock");
|
||||
if (!lock.open(QIODevice::WriteOnly)){
|
||||
QMessageBox::critical(this, tr("Error"), tr("Couldn't create database lock file."));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!dbReadOnly && !QFile::exists(filename+".lock")){
|
||||
QFile lock(filename+".lock");
|
||||
if (!lock.open(QIODevice::WriteOnly)){
|
||||
setStatusBarMsg(StatusBarReadOnlyLock);
|
||||
dbReadOnly = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(db->load(filename, dbReadOnly)){
|
||||
if (IsLocked)
|
||||
resetLock();
|
||||
currentFile = filename;
|
||||
|
@ -462,8 +470,7 @@ bool KeepassMainWindow::openDatabase(QString filename,bool IsAuto){
|
|||
setStateFileModified(static_cast<Kdb3Database*>(db)->hasPasswordEncodingChanged());
|
||||
}
|
||||
else{
|
||||
statusbarState = 2;
|
||||
StatusBarGeneral->setText(tr("Loading Failed"));
|
||||
setStatusBarMsg(StatusBarLoadingFailed);
|
||||
QString error=db->getError();
|
||||
if(error.isEmpty())error=tr("Unknown error while loading database.");
|
||||
QMessageBox::critical(this,tr("Error"),
|
||||
|
@ -478,8 +485,8 @@ bool KeepassMainWindow::openDatabase(QString filename,bool IsAuto){
|
|||
return false;
|
||||
}
|
||||
}
|
||||
statusbarState = 0;
|
||||
StatusBarGeneral->setText(tr("Ready"));
|
||||
if (statusbarState != StatusBarReadOnlyLock)
|
||||
setStatusBarMsg(StatusBarReady);
|
||||
inactivityCounter = 0;
|
||||
|
||||
return true;
|
||||
|
@ -509,7 +516,12 @@ bool KeepassMainWindow::closeDatabase(bool lock){
|
|||
QMessageBox::Yes|QMessageBox::No|QMessageBox::Cancel, QMessageBox::Yes);
|
||||
if(r==QMessageBox::Cancel) return false; //Cancel
|
||||
if(r==QMessageBox::Yes){ //Yes (Save file)
|
||||
if(!OnFileSave()) return false;
|
||||
if (dbReadOnly) {
|
||||
if(!OnFileSaveAs()) return false;
|
||||
}
|
||||
else {
|
||||
if(!OnFileSave()) return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1028,6 +1040,14 @@ void KeepassMainWindow::closeEvent(QCloseEvent* e){
|
|||
return;
|
||||
}
|
||||
|
||||
if(FileOpen && !closeDatabase()){
|
||||
ShutingDown=false;
|
||||
e->ignore();
|
||||
return;
|
||||
}
|
||||
|
||||
e->accept();
|
||||
|
||||
#ifdef GLOBAL_AUTOTYPE
|
||||
autoType->unregisterGlobalShortcut();
|
||||
#endif
|
||||
|
@ -1040,19 +1060,8 @@ void KeepassMainWindow::closeEvent(QCloseEvent* e){
|
|||
config->setHSplitterPos(HSplitter->saveState());
|
||||
config->setShowStatusbar(statusBar()->isVisible());
|
||||
|
||||
if(FileOpen){
|
||||
if(!closeDatabase()){
|
||||
ShutingDown=false;
|
||||
e->ignore();
|
||||
return;
|
||||
}
|
||||
else
|
||||
e->accept();
|
||||
}
|
||||
else
|
||||
e->accept();
|
||||
delete SysTray;
|
||||
QCoreApplication::quit();
|
||||
QApplication::quit();
|
||||
}
|
||||
|
||||
void KeepassMainWindow::hideEvent(QHideEvent* event){
|
||||
|
@ -1101,17 +1110,7 @@ void KeepassMainWindow::OnExtrasSettings(){
|
|||
else {
|
||||
setWindowTitle(APP_DISPLAY_NAME);
|
||||
}
|
||||
switch (statusbarState) {
|
||||
case 0:
|
||||
StatusBarGeneral->setText(tr("Ready"));
|
||||
break;
|
||||
case 1:
|
||||
StatusBarGeneral->setText(tr("Loading Database..."));
|
||||
break;
|
||||
case 2:
|
||||
StatusBarGeneral->setText(tr("Loading Failed"));
|
||||
break;
|
||||
}
|
||||
setStatusBarMsg(statusbarState);
|
||||
}
|
||||
|
||||
EntryView->setAlternatingRowColors(config->alternatingRowColors());
|
||||
|
@ -1409,3 +1408,25 @@ void KeepassMainWindow::createBookmarkActions(){
|
|||
menuBookmarks->addAction(action);
|
||||
}
|
||||
}
|
||||
|
||||
void KeepassMainWindow::setStatusBarMsg(StatusBarMsg statusBarMsg) {
|
||||
QString text;
|
||||
|
||||
switch (statusBarMsg) {
|
||||
case StatusBarReady:
|
||||
text = tr("Ready");
|
||||
break;
|
||||
case StatusBarLoading:
|
||||
text = tr("Loading Database...");
|
||||
break;
|
||||
case StatusBarLoadingFailed:
|
||||
text = tr("Loading Failed");
|
||||
break;
|
||||
case StatusBarReadOnlyLock:
|
||||
text = tr("Couldn't create lock file. Opening the database read-only.");
|
||||
break;
|
||||
}
|
||||
|
||||
statusbarState = statusBarMsg;
|
||||
StatusBarGeneral->setText(text);
|
||||
}
|
||||
|
|
|
@ -90,6 +90,11 @@ class KeepassMainWindow : public QMainWindow, private Ui_MainWindow{
|
|||
void showEvent(QShowEvent* event);
|
||||
void setLock();
|
||||
void resetLock();
|
||||
enum StatusBarMsg {
|
||||
StatusBarReady, StatusBarLoading, StatusBarLoadingFailed,
|
||||
StatusBarReadOnlyLock
|
||||
};
|
||||
void setStatusBarMsg(StatusBarMsg statusBarMsg);
|
||||
SelectionState GroupSelection, EntrySelection;
|
||||
bool FileOpen;
|
||||
bool ModFlag;
|
||||
|
@ -115,7 +120,7 @@ class KeepassMainWindow : public QMainWindow, private Ui_MainWindow{
|
|||
void createBookmarkActions();
|
||||
QLineEdit* QuickSearchEdit;
|
||||
QLabel* StatusBarGeneral;
|
||||
QLabel* StatusBarSelection;
|
||||
//QLabel* StatusBarSelection;
|
||||
QToolBar* toolBar;
|
||||
QSystemTrayIcon* SysTray;
|
||||
QAction* ViewShowToolbarAction;
|
||||
|
@ -131,7 +136,8 @@ class KeepassMainWindow : public QMainWindow, private Ui_MainWindow{
|
|||
QString currentFile;
|
||||
int inactivityCounter;
|
||||
QTimer* inactivityTimer;
|
||||
int statusbarState;
|
||||
StatusBarMsg statusbarState;
|
||||
bool dbReadOnly;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue