patch for KABC file plugin
Carsten Pfeiffer
Carsten.Pfeiffer at alumni.TU-Berlin.DE
Sun Feb 19 12:48:07 GMT 2006
On Thu, Feb 16, 2006 at 05:49:01PM +0100, Carsten Pfeiffer wrote:
On Thursday 16 February 2006 17:49, Carsten Pfeiffer wrote:
Hi,
> Attached is a patch for the 3.5 branch. I'll also fix the net plugin later,
> which has similar issues.
here's a revisited patch, which adds further error handling, fixes usage of
KTempFile/KSaveFile and also covers the net plugin.
Note: I didn't care about binary compatibility, because I think that noone
uses these classes directly. Please correct me if I'm wrong.
Cheers,
Carsten
-------------- next part --------------
Index: plugins/file/resourcefile.cpp
===================================================================
--- plugins/file/resourcefile.cpp (Revision 510236)
+++ plugins/file/resourcefile.cpp (Arbeitskopie)
@@ -58,7 +58,7 @@ class ResourceFile::ResourceFilePrivate
};
ResourceFile::ResourceFile( const KConfig *config )
- : Resource( config ), mFormat( 0 ), mLocalTempFile( 0 ),
+ : Resource( config ), mFormat( 0 ), mTempFile( 0 ),
mAsynchronous( false ), d( new ResourceFilePrivate )
{
QString fileName, formatName;
@@ -76,7 +76,7 @@ ResourceFile::ResourceFile( const KConfi
ResourceFile::ResourceFile( const QString &fileName,
const QString &formatName )
- : Resource( 0 ), mFormat( 0 ), mLocalTempFile( 0 ),
+ : Resource( 0 ), mFormat( 0 ), mTempFile( 0 ),
mAsynchronous( false ), d( new ResourceFilePrivate )
{
init( fileName, formatName );
@@ -119,8 +119,8 @@ ResourceFile::~ResourceFile()
d = 0;
delete mFormat;
mFormat = 0;
- delete mLocalTempFile;
- mLocalTempFile = 0;
+
+ deleteLocalTempFile();
}
void ResourceFile::writeConfig( KConfig *config )
@@ -207,6 +207,10 @@ bool ResourceFile::load()
{
kdDebug(5700) << "ResourceFile::load(): '" << mFileName << "'" << endl;
+ if ( d->mIsLoading ) {
+ abortAsyncLoading();
+ }
+
mAsynchronous = false;
QFile file( mFileName );
@@ -215,24 +219,45 @@ bool ResourceFile::load()
return false;
}
- return mFormat->loadAll( addressBook(), this, &file );
+ if ( !clearAndLoad( &file ) ) {
+ addressBook()->error( i18n( "Problems during parsing file '%1'." ).arg( mFileName ) );
+ return false;
+ }
+
+ return true;
+}
+
+bool ResourceFile::clearAndLoad( QFile *file )
+{
+ clear();
+ return mFormat->loadAll( addressBook(), this, file );
}
bool ResourceFile::asyncLoad()
{
- mAsynchronous = true;
+ if ( d->mIsLoading ) {
+ abortAsyncLoading();
+ }
- if ( mLocalTempFile ) {
- kdDebug(5700) << "stale temp file detected " << mLocalTempFile->name() << endl;
- delete mLocalTempFile;
+ if (d->mIsSaving) {
+ kdWarning(5700) << "Aborted asyncSave() because we're still asyncSave()ing!" << endl;
+ return false;
}
- mLocalTempFile = new KTempFile();
- mLocalTempFile->setAutoDelete( true );
- mTempFile = mLocalTempFile->name();
+ mAsynchronous = true;
+
+ bool ok = createLocalTempFile();
+ if ( ok )
+ ok = mTempFile->close(); // we only need the filename
+
+ if ( !ok ) {
+ emit loadingError( this, i18n( "Unable to open file '%1'." ).arg( mTempFile->name() ) );
+ deleteLocalTempFile();
+ return false;
+ }
KURL dest, src;
- dest.setPath( mTempFile );
+ dest.setPath( mTempFile->name() );
src.setPath( mFileName );
KIO::Scheduler::checkSlaveOnHold( true );
@@ -244,26 +269,60 @@ bool ResourceFile::asyncLoad()
return true;
}
+void ResourceFile::abortAsyncLoading()
+{
+ kdDebug(5700) << "ResourceFile::abortAsyncLoading()" << endl;
+
+ if ( d->mLoadJob ) {
+ d->mLoadJob->kill(); // result not emitted
+ d->mLoadJob = 0;
+ }
+
+ deleteLocalTempFile();
+ d->mIsLoading = false;
+}
+
+void ResourceFile::abortAsyncSaving()
+{
+ kdDebug(5700) << "ResourceFile::abortAsyncSaving()" << endl;
+
+ if ( d->mSaveJob ) {
+ d->mSaveJob->kill(); // result not emitted
+ d->mSaveJob = 0;
+ }
+
+ deleteLocalTempFile();
+ d->mIsSaving = false;
+}
+
bool ResourceFile::save( Ticket * )
{
kdDebug(5700) << "ResourceFile::save()" << endl;
+ if (d->mIsSaving) {
+ abortAsyncSaving();
+ }
+
// create backup file
QString extension = "_" + QString::number( QDate::currentDate().dayOfWeek() );
(void) KSaveFile::backupFile( mFileName, QString::null /*directory*/,
extension );
mDirWatch.stopScan();
+
KSaveFile saveFile( mFileName );
bool ok = false;
- if ( saveFile.status() == 0 && saveFile.file() )
- {
- mFormat->saveAll( addressBook(), this, saveFile.file() );
+
+ if ( saveFile.status() == 0 && saveFile.file() ) {
+ saveToFile( saveFile.file() );
ok = saveFile.close();
}
- if ( !ok )
+ if ( !ok ) {
+ saveFile.abort();
addressBook()->error( i18n( "Unable to save file '%1'." ).arg( mFileName ) );
+ }
+
mDirWatch.startScan();
return ok;
@@ -271,30 +330,70 @@ bool ResourceFile::save( Ticket * )
bool ResourceFile::asyncSave( Ticket * )
{
- QFile file( mTempFile );
+ kdDebug(5700) << "ResourceFile::asyncSave()" << endl;
+
+ if (d->mIsSaving) {
+ abortAsyncSaving();
+ }
- if ( !file.open( IO_WriteOnly ) ) {
- emit savingError( this, i18n( "Unable to open file '%1'." ).arg( mTempFile ) );
+ if (d->mIsLoading) {
+ kdWarning(5700) << "Aborted asyncSave() because we're still asyncLoad()ing!" << endl;
return false;
}
- mDirWatch.stopScan();
- mFormat->saveAll( addressBook(), this, &file );
- file.close();
+ bool ok = createLocalTempFile();
+ if ( ok ) {
+ saveToFile( mTempFile->file() );
+ ok = mTempFile->close();
+ }
+
+ if ( !ok ) {
+ emit savingError( this, i18n( "Unable to save file '%1'." ).arg( mTempFile->name() ) );
+ deleteLocalTempFile();
+ return false;
+ }
KURL src, dest;
- src.setPath( mTempFile );
+ src.setPath( mTempFile->name() );
dest.setPath( mFileName );
KIO::Scheduler::checkSlaveOnHold( true );
- d->mSaveJob = KIO::file_copy( src, dest, -1, true, false, false );
d->mIsSaving = true;
+ mDirWatch.stopScan(); // restarted in uploadFinished()
+ d->mSaveJob = KIO::file_copy( src, dest, -1, true, false, false );
connect( d->mSaveJob, SIGNAL( result( KIO::Job* ) ),
this, SLOT( uploadFinished( KIO::Job* ) ) );
return true;
}
+bool ResourceFile::createLocalTempFile()
+{
+ deleteStaleTempFile();
+ mTempFile = new KTempFile();
+ mTempFile->setAutoDelete( true );
+ return mTempFile->status() == 0;
+}
+
+void ResourceFile::deleteStaleTempFile()
+{
+ if ( hasTempFile() ) {
+ kdDebug(5700) << "stale temp file detected " << mTempFile->name() << endl;
+ deleteLocalTempFile();
+ }
+}
+
+void ResourceFile::deleteLocalTempFile()
+{
+ delete mTempFile;
+ mTempFile = 0;
+}
+
+void ResourceFile::saveToFile( QFile *file )
+{
+ mFormat->saveAll( addressBook(), this, file );
+}
+
void ResourceFile::setFileName( const QString &fileName )
{
mDirWatch.stopScan();
@@ -328,10 +427,12 @@ QString ResourceFile::format() const
void ResourceFile::fileChanged()
{
+ kdDebug(5700) << "ResourceFile::fileChanged(): " << mFileName << endl;
+
if ( !addressBook() )
return;
- clear();
+// clear(); // moved to clearAndLoad()
if ( mAsynchronous )
asyncLoad();
else {
@@ -352,31 +453,41 @@ void ResourceFile::removeAddressee( cons
void ResourceFile::downloadFinished( KIO::Job* )
{
+ kdDebug(5700) << "ResourceFile::downloadFinished()" << endl;
+
d->mIsLoading = false;
- if ( !mLocalTempFile )
+ if ( !hasTempFile() || mTempFile->status() != 0 ) {
emit loadingError( this, i18n( "Download failed in some way!" ) );
-
- QFile file( mTempFile );
- if ( !file.open( IO_ReadOnly ) ) {
- emit loadingError( this, i18n( "Unable to open file '%1'." ).arg( mTempFile ) );
return;
}
- if ( !mFormat->loadAll( addressBook(), this, &file ) )
- emit loadingError( this, i18n( "Problems during parsing file '%1'." ).arg( mTempFile ) );
- else
+ QFile file( mTempFile->name() );
+ if ( file.open( IO_ReadOnly ) ) {
+ if ( clearAndLoad( &file ) )
emit loadingFinished( this );
+ else
+ emit loadingError( this, i18n( "Problems during parsing file '%1'." ).arg( mTempFile->name() ) );
+ }
+ else {
+ emit loadingError( this, i18n( "Unable to open file '%1'." ).arg( mTempFile->name() ) );
+ }
+
+ deleteLocalTempFile();
}
void ResourceFile::uploadFinished( KIO::Job *job )
{
+ kdDebug(5700) << "ResourceFile::uploadFinished()" << endl;
+
d->mIsSaving = false;
if ( job->error() )
emit savingError( this, job->errorString() );
else
emit savingFinished( this );
+
+ deleteLocalTempFile();
mDirWatch.startScan();
}
Index: plugins/file/resourcefile.h
===================================================================
--- plugins/file/resourcefile.h (Revision 510236)
+++ plugins/file/resourcefile.h (Arbeitskopie)
@@ -28,8 +28,8 @@
#include <kabc/resource.h>
+class QFile;
class QTimer;
-
class KTempFile;
namespace KIO {
@@ -148,6 +148,15 @@ class KABC_EXPORT ResourceFile : public
void unlock( const QString &fileName );
private:
+ bool clearAndLoad( QFile *file );
+ void saveToFile( QFile *file );
+ void abortAsyncLoading();
+ void abortAsyncSaving();
+ bool createLocalTempFile();
+ void deleteLocalTempFile();
+ void deleteStaleTempFile();
+ bool hasTempFile() const { return mTempFile != 0; }
+
QString mFileName;
QString mFormatName;
@@ -157,8 +166,7 @@ class KABC_EXPORT ResourceFile : public
KDirWatch mDirWatch;
- QString mTempFile;
- KTempFile *mLocalTempFile;
+ KTempFile *mTempFile;
bool mAsynchronous;
Index: plugins/net/resourcenet.cpp
===================================================================
--- plugins/net/resourcenet.cpp (Revision 510236)
+++ plugins/net/resourcenet.cpp (Arbeitskopie)
@@ -24,6 +24,7 @@
#include <kio/netaccess.h>
#include <kio/scheduler.h>
#include <klocale.h>
+#include <ksavefile.h>
#include <ktempfile.h>
#include <kurlrequester.h>
@@ -48,7 +49,7 @@ class ResourceNet::ResourceNetPrivate
ResourceNet::ResourceNet( const KConfig *config )
: Resource( config ), mFormat( 0 ),
- mLocalTempFile( 0 ), mUseLocalTempFile( false ),
+ mTempFile( 0 ),
d( new ResourceNetPrivate )
{
if ( config ) {
@@ -60,7 +61,7 @@ ResourceNet::ResourceNet( const KConfig
ResourceNet::ResourceNet( const KURL &url, const QString &format )
: Resource( 0 ), mFormat( 0 ),
- mLocalTempFile( 0 ), mUseLocalTempFile( false ),
+ mTempFile( 0 ),
d( new ResourceNetPrivate )
{
init( url, format );
@@ -98,8 +99,7 @@ ResourceNet::~ResourceNet()
delete mFormat;
mFormat = 0;
- delete mLocalTempFile;
- mLocalTempFile = 0;
+ deleteLocalTempFile();
}
void ResourceNet::writeConfig( KConfig *config )
@@ -114,15 +114,11 @@ Ticket *ResourceNet::requestSaveTicket()
{
kdDebug(5700) << "ResourceNet::requestSaveTicket()" << endl;
- if ( mTempFile.isEmpty() )
- return 0;
-
return createTicket( this );
}
void ResourceNet::releaseSaveTicket( Ticket *ticket )
{
- KIO::NetAccess::removeTempFile( mTempFile );
delete ticket;
}
@@ -137,41 +133,58 @@ void ResourceNet::doClose()
bool ResourceNet::load()
{
- if ( !KIO::NetAccess::exists( mUrl, true, 0 ) ) {
- mLocalTempFile = new KTempFile();
- mLocalTempFile->setAutoDelete( true );
- mUseLocalTempFile = true;
- mTempFile = mLocalTempFile->name();
- }
+ QString tempFile;
- if ( !KIO::NetAccess::download( mUrl, mTempFile, 0 ) ) {
- addressBook()->error( i18n( "Unable to download file '%1'." ).arg( mUrl.url() ) );
+ if ( !KIO::NetAccess::download( mUrl, tempFile, 0 ) ) {
+ addressBook()->error( i18n( "Unable to download file '%1'." ).arg( mUrl.prettyURL() ) );
return false;
}
- QFile file( mTempFile );
+ QFile file( tempFile );
if ( !file.open( IO_ReadOnly ) ) {
- addressBook()->error( i18n( "Unable to open file '%1'." ).arg( mUrl.url() ) );
+ addressBook()->error( i18n( "Unable to open file '%1'." ).arg( tempFile ) );
+ KIO::NetAccess::removeTempFile( tempFile );
return false;
}
- return mFormat->loadAll( addressBook(), this, &file );
+ bool result = clearAndLoad( &file );
+ if ( !result )
+ addressBook()->error( i18n( "Problems during parsing file '%1'." ).arg( tempFile ) );
+
+ KIO::NetAccess::removeTempFile( tempFile );
+
+ return result;
+}
+
+bool ResourceNet::clearAndLoad( QFile *file )
+{
+ clear();
+ return mFormat->loadAll( addressBook(), this, file );
}
bool ResourceNet::asyncLoad()
{
- if ( mLocalTempFile ) {
- kdDebug(5700) << "stale temp file detected " << mLocalTempFile->name() << endl;
- mLocalTempFile->setAutoDelete( true );
- delete mLocalTempFile;
+ if ( d->mIsLoading ) {
+ abortAsyncLoading();
+ }
+
+ if (d->mIsSaving) {
+ kdWarning(5700) << "Aborted asyncLoad() because we're still asyncSave()ing!" << endl;
+ return false;
}
- mLocalTempFile = new KTempFile();
- mUseLocalTempFile = true;
- mTempFile = mLocalTempFile->name();
+ bool ok = createLocalTempFile();
+ if ( ok )
+ ok = mTempFile->close();
+
+ if ( !ok ) {
+ emit loadingError( this, i18n( "Unable to open file '%1'." ).arg( mTempFile->name() ) );
+ deleteLocalTempFile();
+ return false;
+ }
KURL dest;
- dest.setPath( mTempFile );
+ dest.setPath( mTempFile->name() );
KIO::Scheduler::checkSlaveOnHold( true );
d->mLoadJob = KIO::file_copy( mUrl, dest, -1, true, false, false );
@@ -182,45 +195,125 @@ bool ResourceNet::asyncLoad()
return true;
}
+void ResourceNet::abortAsyncLoading()
+{
+ kdDebug(5700) << "ResourceNet::abortAsyncLoading()" << endl;
+
+ if ( d->mLoadJob ) {
+ d->mLoadJob->kill(); // result not emitted
+ d->mLoadJob = 0;
+ }
+
+ deleteLocalTempFile();
+ d->mIsLoading = false;
+}
+
+void ResourceNet::abortAsyncSaving()
+{
+ kdDebug(5700) << "ResourceNet::abortAsyncSaving()" << endl;
+
+ if ( d->mSaveJob ) {
+ d->mSaveJob->kill(); // result not emitted
+ d->mSaveJob = 0;
+ }
+
+ deleteLocalTempFile();
+ d->mIsSaving = false;
+}
+
bool ResourceNet::save( Ticket* )
{
- QFile file( mTempFile );
+ kdDebug(5700) << "ResourceNet::save()" << endl;
+
+ if (d->mIsSaving) {
+ abortAsyncSaving();
+ }
+
+ KTempFile tempFile;
+ tempFile.setAutoDelete( true );
+ bool ok = false;
+
+ if ( tempFile.status() == 0 && tempFile.file() ) {
+ saveToFile( tempFile.file() );
+ ok = tempFile.close();
+ }
- if ( !file.open( IO_WriteOnly ) ) {
- addressBook()->error( i18n( "Unable to open file '%1'." ).arg( mUrl.url() ) );
+ if ( !ok ) {
+ addressBook()->error( i18n( "Unable to save file '%1'." ).arg( tempFile.name() ) );
return false;
}
- mFormat->saveAll( addressBook(), this, &file );
- file.close();
+ ok = KIO::NetAccess::upload( tempFile.name(), mUrl, 0 );
+ if ( !ok )
+ addressBook()->error( i18n( "Unable to upload to '%1'." ).arg( mUrl.prettyURL() ) );
- return KIO::NetAccess::upload( mTempFile, mUrl, 0 );
+ return ok;
}
bool ResourceNet::asyncSave( Ticket* )
{
- QFile file( mTempFile );
+ kdDebug(5700) << "ResourceNet::asyncSave()" << endl;
- if ( !file.open( IO_WriteOnly ) ) {
- emit savingError( this, i18n( "Unable to open file '%1'." ).arg( mTempFile ) );
+ if (d->mIsSaving) {
+ abortAsyncSaving();
+ }
+
+ if (d->mIsLoading) {
+ kdWarning(5700) << "Aborted asyncSave() because we're still asyncLoad()ing!" << endl;
return false;
}
- mFormat->saveAll( addressBook(), this, &file );
- file.close();
+ bool ok = createLocalTempFile();
+ if ( ok ) {
+ saveToFile( mTempFile->file() );
+ ok = mTempFile->close();
+ }
+
+ if ( !ok ) {
+ emit savingError( this, i18n( "Unable to save file '%1'." ).arg( mTempFile->name() ) );
+ deleteLocalTempFile();
+ return false;
+ }
KURL src;
- src.setPath( mTempFile );
+ src.setPath( mTempFile->name() );
KIO::Scheduler::checkSlaveOnHold( true );
- d->mSaveJob = KIO::file_copy( src, mUrl, -1, true, false, false );
d->mIsSaving = true;
+ d->mSaveJob = KIO::file_copy( src, mUrl, -1, true, false, false );
connect( d->mSaveJob, SIGNAL( result( KIO::Job* ) ),
this, SLOT( uploadFinished( KIO::Job* ) ) );
return true;
}
+bool ResourceNet::createLocalTempFile()
+{
+ deleteStaleTempFile();
+ mTempFile = new KTempFile();
+ mTempFile->setAutoDelete( true );
+ return mTempFile->status() == 0;
+}
+
+void ResourceNet::deleteStaleTempFile()
+{
+ if ( hasTempFile() ) {
+ kdDebug(5700) << "stale temp file detected " << mTempFile->name() << endl;
+ deleteLocalTempFile();
+ }
+}
+
+void ResourceNet::deleteLocalTempFile()
+{
+ delete mTempFile;
+ mTempFile = 0;
+}
+
+void ResourceNet::saveToFile( QFile *file )
+{
+ mFormat->saveAll( addressBook(), this, file );
+}
+
void ResourceNet::setUrl( const KURL &url )
{
mUrl = url;
@@ -248,31 +341,41 @@ QString ResourceNet::format() const
void ResourceNet::downloadFinished( KIO::Job* )
{
+ kdDebug(5700) << "ResourceNet::downloadFinished()" << endl;
+
d->mIsLoading = false;
- if ( !mLocalTempFile )
+ if ( !hasTempFile() || mTempFile->status() != 0 ) {
emit loadingError( this, i18n( "Download failed in some way!" ) );
-
- QFile file( mTempFile );
- if ( !file.open( IO_ReadOnly ) ) {
- emit loadingError( this, i18n( "Unable to open file '%1'." ).arg( mTempFile ) );
return;
}
- if ( !mFormat->loadAll( addressBook(), this, &file ) )
- emit loadingError( this, i18n( "Problems during parsing file '%1'." ).arg( mTempFile ) );
- else
+ QFile file( mTempFile->name() );
+ if ( file.open( IO_ReadOnly ) ) {
+ if ( clearAndLoad( &file ) )
emit loadingFinished( this );
+ else
+ emit loadingError( this, i18n( "Problems during parsing file '%1'." ).arg( mTempFile->name() ) );
+ }
+ else {
+ emit loadingError( this, i18n( "Unable to open file '%1'." ).arg( mTempFile->name() ) );
+ }
+
+ deleteLocalTempFile();
}
void ResourceNet::uploadFinished( KIO::Job *job )
{
+ kdDebug(5700) << "ResourceFile::uploadFinished()" << endl;
+
d->mIsSaving = false;
if ( job->error() )
emit savingError( this, job->errorString() );
else
emit savingFinished( this );
+
+ deleteLocalTempFile();
}
#include "resourcenet.moc"
Index: plugins/net/resourcenet.h
===================================================================
--- plugins/net/resourcenet.h (Revision 510236)
+++ plugins/net/resourcenet.h (Arbeitskopie)
@@ -27,6 +27,7 @@
#include <kabc/resource.h>
+class QFile;
class QTimer;
class KTempFile;
@@ -91,13 +92,20 @@ class KABC_EXPORT ResourceNet : public R
void uploadFinished( KIO::Job* );
private:
+ bool clearAndLoad( QFile *file );
+ void saveToFile( QFile *file );
+ bool hasTempFile() const { return mTempFile != 0; }
+ void abortAsyncLoading();
+ void abortAsyncSaving();
+ bool createLocalTempFile();
+ void deleteLocalTempFile();
+ void deleteStaleTempFile();
+
FormatPlugin *mFormat;
QString mFormatName;
KURL mUrl;
- QString mTempFile;
- KTempFile *mLocalTempFile;
- bool mUseLocalTempFile;
+ KTempFile *mTempFile;
class ResourceNetPrivate;
ResourceNetPrivate *d;
More information about the kde-core-devel
mailing list