/* This file is part of the KDE libraries Copyright (c) 2006 Jacob R Rideout This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kautosavefile.h" #include // for FILENAME_MAX #include #include #include "klockfile.h" #include "krandom.h" #include "kglobal.h" #include "kstandarddirs.h" class KAutoSaveFilePrivate { public: KAutoSaveFilePrivate() : lock(0), managedFileNameChanged(false) {} QString tempFileName(); KUrl managedFile; KLockFile::Ptr lock; static const int padding; bool managedFileNameChanged; }; const int KAutoSaveFilePrivate::padding = 8; QString KAutoSaveFilePrivate::tempFileName() { static const int maxNameLength = FILENAME_MAX; // Note: we drop any query string and user/pass info QString protocol(managedFile.protocol()); QString path(managedFile.directory()); QString name(managedFile.fileName()); // Remove any part of the path to the right if it is longer than the max file size and // ensure that the max filesize takes into account the other parts of the tempFileName // Subtract 1 for the _ char, 3 for the padding sepperator, 5 is for the .lock path = path.left(maxNameLength - padding - name.size() - protocol.size() - 9); QString junk = KRandom::randomString(padding); // tempName = fileName + junk.trunicated + protocol + _ + path.trunicated + junk // This is done so that the separation between the filename and path can be determined name += junk.right(3) + protocol + QLatin1Char('_'); name += path + junk; return QString::fromLatin1(KUrl::toPercentEncoding(name)); } KAutoSaveFile::KAutoSaveFile(const KUrl &filename, QObject *parent) : QFile(parent), d(new KAutoSaveFilePrivate) { setManagedFile(filename); KGlobal::dirs()->addResourceType("stale", 0, QString::fromLatin1("data/stalefiles")); } KAutoSaveFile::KAutoSaveFile(QObject *parent) : QFile(parent), d(new KAutoSaveFilePrivate) { KGlobal::dirs()->addResourceType("stale", 0, QString::fromLatin1("data/stalefiles")); } KAutoSaveFile::~KAutoSaveFile() { releaseLock(); delete d; } KUrl KAutoSaveFile::managedFile() const { return d->managedFile; } void KAutoSaveFile::setManagedFile(const KUrl &filename) { releaseLock(); d->managedFile = filename; d->managedFileNameChanged = true; } void KAutoSaveFile::releaseLock() { if (d->lock && d->lock->isLocked()) { d->lock.clear(); if (!fileName().isEmpty()) { remove(); } } } bool KAutoSaveFile::open(OpenMode openmode) { if (d->managedFile == KUrl()) { return false; } QString tempFile; if (d->managedFileNameChanged) { tempFile = KStandardDirs::locateLocal("stale", QCoreApplication::instance()->applicationName() + QChar::fromLatin1('/') + d->tempFileName() ); } else { tempFile = fileName(); } d->managedFileNameChanged = false; setFileName(tempFile); if (QFile::open(openmode)) { d->lock = new KLockFile(tempFile + QString::fromLatin1(".lock")); d->lock->setStaleTime(60); // HARDCODE, 1 minute if (d->lock->lock(KLockFile::ForceFlag|KLockFile::NoBlockFlag) == KLockFile::LockOK) { return true; } else { close(); } } return false; } QList KAutoSaveFile::staleFiles(const KUrl &filename, const QString &applicationName) { KGlobal::dirs()->addResourceType("stale", 0, QString::fromLatin1("data/stalefiles")); QString appName(applicationName); if (appName.isEmpty()) { appName = QCoreApplication::instance()->applicationName(); } QString url = filename.fileName(); if (url.isEmpty()) { return QList(); } // get stale files const QStringList files = KGlobal::dirs()->findAllResources("stale", appName + QChar::fromLatin1('/') + url + QChar::fromLatin1('*'), KStandardDirs::Recursive); QList list; KAutoSaveFile * asFile; // contruct a KAutoSaveFile for each stale file foreach(const QString &file, files) { if (file.endsWith(QLatin1String(".lock"))) continue; // sets managedFile asFile = new KAutoSaveFile(filename); asFile->setFileName(file); // flags the name, so it isn't regenerated asFile->d->managedFileNameChanged = false; list.append(asFile); } return list; } QList KAutoSaveFile::allStaleFiles(const QString &applicationName) { KGlobal::dirs()->addResourceType("stale", 0, QString::fromLatin1("data/stalefiles")); QString appName(applicationName); if (appName.isEmpty()) { appName = QCoreApplication::instance()->applicationName(); } // get stale files const QStringList files = KGlobal::dirs()->findAllResources("stale", appName + QLatin1String("/*")); QList list; // contruct a KAutoSaveFile for each stale file foreach(QString file, files) { // krazy:exclude=foreach (no const& because modified below) if (file.endsWith(QLatin1String(".lock"))) continue; const QString sep = file.right(3); file.chop(KAutoSaveFilePrivate::padding); int sepPos = file.indexOf(sep); int pathPos = file.indexOf(QChar::fromLatin1('_'), sepPos); KUrl name; name.setProtocol(file.mid(sepPos + 3, pathPos - sep.size() - 3)); name.setPath(KUrl::fromPercentEncoding(file.right(pathPos - 1).toLatin1())); name.addPath(KUrl::fromPercentEncoding(file.left(sepPos).toLatin1())); // sets managedFile KAutoSaveFile* asFile = new KAutoSaveFile(name); asFile->setFileName(file); // flags the name, so it isn't regenerated asFile->d->managedFileNameChanged = false; list.append(asFile); } return list; } #include "moc_kautosavefile.cpp"