static bool initSettings(SettingsFile *settings, QLockFile **lockFile, QString &errorMessage) { /* If built in portable mode (default), configuration is stored in the 'config' * directory next to the binary. If not writable, launching fails. * * Portable OS X is an exception. In that case, configuration is stored in a * 'config.ricochet' folder next to the application bundle, unless the application * path contains "/Applications", in which case non-portable mode is used. * * When not in portable mode, a platform-specific per-user config location is used. * * This behavior may be overriden by passing a folder path as the first argument. */ QString configPath; QStringList args = qApp->arguments(); if (args.size() > 1) { configPath = args[1]; } else { #ifndef RICOCHET_NO_PORTABLE # ifdef Q_OS_MAC if (!qApp->applicationDirPath().contains(QStringLiteral("/Applications"))) { // Try old configuration path first configPath = appBundlePath() + QStringLiteral("config.torsion"); if (!QFile::exists(configPath)) configPath = appBundlePath() + QStringLiteral("config.ricochet"); } # else configPath = qApp->applicationDirPath() + QStringLiteral("/config"); # endif #endif if (configPath.isEmpty()) configPath = userConfigPath(); } QDir dir(configPath); if (!dir.exists() && !dir.mkpath(QStringLiteral("."))) { errorMessage = QStringLiteral("Cannot create directory: %1").arg(dir.path()); return false; } // Reset to config directory for consistency; avoid depending on this behavior for paths if (QDir::setCurrent(dir.absolutePath()) && dir.isRelative()) dir.setPath(QStringLiteral(".")); QLockFile *lock = new QLockFile(dir.filePath(QStringLiteral("ricochet.json.lock"))); *lockFile = lock; lock->setStaleLockTime(0); if (!lock->tryLock()) { if (lock->error() == QLockFile::LockFailedError) { // This happens if a stale lock file exists and another process uses that PID. // Try removing the stale file, which will fail if a real process is holding a // file-level lock. A false error is more problematic than not locking properly // on corner-case systems. if (!lock->removeStaleLockFile() || !lock->tryLock()) { errorMessage = QStringLiteral("Configuration file is already in use"); return false; } else qDebug() << "Removed stale lock file"; } else { errorMessage = QStringLiteral("Cannot write configuration file (failed to acquire lock)"); return false; } } settings->setFilePath(dir.filePath(QStringLiteral("ricochet.json"))); if (settings->hasError()) { errorMessage = settings->errorMessage(); return false; } if (settings->root()->data().isEmpty()) { QString filePath = dir.filePath(QStringLiteral("Torsion.ini")); if (!QFile::exists(filePath)) filePath = dir.filePath(QStringLiteral("ricochet.ini")); if (QFile::exists(filePath)) importLegacySettings(settings, filePath); } return true; }
void DatabaseTabWidget::openDatabase(const QString& fileName, const QString& pw, const QString& keyFile) { QFileInfo fileInfo(fileName); QString canonicalFilePath = fileInfo.canonicalFilePath(); if (canonicalFilePath.isEmpty()) { MessageBox::warning(this, tr("Warning"), tr("File not found!")); return; } QHashIterator<Database*, DatabaseManagerStruct> i(m_dbList); while (i.hasNext()) { i.next(); if (i.value().canonicalFilePath == canonicalFilePath) { setCurrentIndex(databaseIndex(i.key())); return; } } DatabaseManagerStruct dbStruct; // test if we can read/write or read the file QFile file(fileName); if (!file.open(QIODevice::ReadWrite)) { if (!file.open(QIODevice::ReadOnly)) { MessageBox::warning(this, tr("Error"), tr("Unable to open the database.").append("\n") .append(file.errorString())); return; } else { // can only open read-only dbStruct.readOnly = true; } } file.close(); QLockFile* lockFile = new QLockFile(QString("%1/.%2.lock").arg(fileInfo.canonicalPath(), fileInfo.fileName())); lockFile->setStaleLockTime(0); if (!dbStruct.readOnly && !lockFile->tryLock()) { // for now silently ignore if we can't create a lock file // due to lack of permissions if (lockFile->error() != QLockFile::PermissionError) { QMessageBox::StandardButton result = MessageBox::question(this, tr("Open database"), tr("The database you are trying to open is locked by another instance of KeePassX.\n" "Do you want to open it anyway? Alternatively the database is opened read-only."), QMessageBox::Yes | QMessageBox::No); if (result == QMessageBox::No) { dbStruct.readOnly = true; delete lockFile; lockFile = nullptr; } else { // take over the lock file if possible if (lockFile->removeStaleLockFile()) { lockFile->tryLock(); } } } } Database* db = new Database(); dbStruct.dbWidget = new DatabaseWidget(db, this); dbStruct.lockFile = lockFile; dbStruct.saveToFilename = !dbStruct.readOnly; dbStruct.filePath = fileInfo.absoluteFilePath(); dbStruct.canonicalFilePath = canonicalFilePath; dbStruct.fileName = fileInfo.fileName(); insertDatabase(db, dbStruct); updateLastDatabases(dbStruct.filePath); if (!pw.isNull() || !keyFile.isEmpty()) { dbStruct.dbWidget->switchToOpenDatabase(dbStruct.filePath, pw, keyFile); } else { dbStruct.dbWidget->switchToOpenDatabase(dbStruct.filePath); } }