00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <qfile.h>
00022
00023 #include <kdebug.h>
00024 #include <kio/netaccess.h>
00025 #include <kio/scheduler.h>
00026 #include <klocale.h>
00027 #include <ksavefile.h>
00028 #include <ktempfile.h>
00029 #include <kurlrequester.h>
00030
00031 #include "addressbook.h"
00032 #include "formatfactory.h"
00033 #include "resourcenetconfig.h"
00034 #include "stdaddressbook.h"
00035
00036 #include "resourcenet.h"
00037
00038 using namespace KABC;
00039
00040 class ResourceNet::ResourceNetPrivate
00041 {
00042 public:
00043 KIO::Job *mLoadJob;
00044 bool mIsLoading;
00045
00046 KIO::Job *mSaveJob;
00047 bool mIsSaving;
00048 };
00049
00050 ResourceNet::ResourceNet( const KConfig *config )
00051 : Resource( config ), mFormat( 0 ),
00052 mTempFile( 0 ),
00053 d( new ResourceNetPrivate )
00054 {
00055 if ( config ) {
00056 init( KURL( config->readPathEntry( "NetUrl" ) ), config->readEntry( "NetFormat" ) );
00057 } else {
00058 init( KURL(), "vcard" );
00059 }
00060 }
00061
00062 ResourceNet::ResourceNet( const KURL &url, const QString &format )
00063 : Resource( 0 ), mFormat( 0 ),
00064 mTempFile( 0 ),
00065 d( new ResourceNetPrivate )
00066 {
00067 init( url, format );
00068 }
00069
00070 void ResourceNet::init( const KURL &url, const QString &format )
00071 {
00072 d->mLoadJob = 0;
00073 d->mIsLoading = false;
00074 d->mSaveJob = 0;
00075 d->mIsSaving = false;
00076
00077 mFormatName = format;
00078
00079 FormatFactory *factory = FormatFactory::self();
00080 mFormat = factory->format( mFormatName );
00081 if ( !mFormat ) {
00082 mFormatName = "vcard";
00083 mFormat = factory->format( mFormatName );
00084 }
00085
00086 setUrl( url );
00087 }
00088
00089 ResourceNet::~ResourceNet()
00090 {
00091 if ( d->mIsLoading )
00092 d->mLoadJob->kill();
00093 if ( d->mIsSaving )
00094 d->mSaveJob->kill();
00095
00096 delete d;
00097 d = 0;
00098
00099 delete mFormat;
00100 mFormat = 0;
00101
00102 deleteLocalTempFile();
00103 }
00104
00105 void ResourceNet::writeConfig( KConfig *config )
00106 {
00107 Resource::writeConfig( config );
00108
00109 config->writePathEntry( "NetUrl", mUrl.url() );
00110 config->writeEntry( "NetFormat", mFormatName );
00111 }
00112
00113 Ticket *ResourceNet::requestSaveTicket()
00114 {
00115 kdDebug(5700) << "ResourceNet::requestSaveTicket()" << endl;
00116
00117 return createTicket( this );
00118 }
00119
00120 void ResourceNet::releaseSaveTicket( Ticket *ticket )
00121 {
00122 delete ticket;
00123 }
00124
00125 bool ResourceNet::doOpen()
00126 {
00127 return true;
00128 }
00129
00130 void ResourceNet::doClose()
00131 {
00132 }
00133
00134 bool ResourceNet::load()
00135 {
00136 QString tempFile;
00137
00138 if ( !KIO::NetAccess::download( mUrl, tempFile, 0 ) ) {
00139 addressBook()->error( i18n( "Unable to download file '%1'." ).arg( mUrl.prettyURL() ) );
00140 return false;
00141 }
00142
00143 QFile file( tempFile );
00144 if ( !file.open( IO_ReadOnly ) ) {
00145 addressBook()->error( i18n( "Unable to open file '%1'." ).arg( tempFile ) );
00146 KIO::NetAccess::removeTempFile( tempFile );
00147 return false;
00148 }
00149
00150 bool result = clearAndLoad( &file );
00151 if ( !result )
00152 addressBook()->error( i18n( "Problems during parsing file '%1'." ).arg( tempFile ) );
00153
00154 KIO::NetAccess::removeTempFile( tempFile );
00155
00156 return result;
00157 }
00158
00159 bool ResourceNet::clearAndLoad( QFile *file )
00160 {
00161 clear();
00162 return mFormat->loadAll( addressBook(), this, file );
00163 }
00164
00165 bool ResourceNet::asyncLoad()
00166 {
00167 if ( d->mIsLoading ) {
00168 abortAsyncLoading();
00169 }
00170
00171 if (d->mIsSaving) {
00172 kdWarning(5700) << "Aborted asyncLoad() because we're still asyncSave()ing!" << endl;
00173 return false;
00174 }
00175
00176 bool ok = createLocalTempFile();
00177 if ( ok )
00178 ok = mTempFile->close();
00179
00180 if ( !ok ) {
00181 emit loadingError( this, i18n( "Unable to open file '%1'." ).arg( mTempFile->name() ) );
00182 deleteLocalTempFile();
00183 return false;
00184 }
00185
00186 KURL dest;
00187 dest.setPath( mTempFile->name() );
00188
00189 KIO::Scheduler::checkSlaveOnHold( true );
00190 d->mLoadJob = KIO::file_copy( mUrl, dest, -1, true, false, false );
00191 d->mIsLoading = true;
00192 connect( d->mLoadJob, SIGNAL( result( KIO::Job* ) ),
00193 this, SLOT( downloadFinished( KIO::Job* ) ) );
00194
00195 return true;
00196 }
00197
00198 void ResourceNet::abortAsyncLoading()
00199 {
00200 kdDebug(5700) << "ResourceNet::abortAsyncLoading()" << endl;
00201
00202 if ( d->mLoadJob ) {
00203 d->mLoadJob->kill();
00204 d->mLoadJob = 0;
00205 }
00206
00207 deleteLocalTempFile();
00208 d->mIsLoading = false;
00209 }
00210
00211 void ResourceNet::abortAsyncSaving()
00212 {
00213 kdDebug(5700) << "ResourceNet::abortAsyncSaving()" << endl;
00214
00215 if ( d->mSaveJob ) {
00216 d->mSaveJob->kill();
00217 d->mSaveJob = 0;
00218 }
00219
00220 deleteLocalTempFile();
00221 d->mIsSaving = false;
00222 }
00223
00224 bool ResourceNet::save( Ticket* )
00225 {
00226 kdDebug(5700) << "ResourceNet::save()" << endl;
00227
00228 if (d->mIsSaving) {
00229 abortAsyncSaving();
00230 }
00231
00232 KTempFile tempFile;
00233 tempFile.setAutoDelete( true );
00234 bool ok = false;
00235
00236 if ( tempFile.status() == 0 && tempFile.file() ) {
00237 saveToFile( tempFile.file() );
00238 ok = tempFile.close();
00239 }
00240
00241 if ( !ok ) {
00242 addressBook()->error( i18n( "Unable to save file '%1'." ).arg( tempFile.name() ) );
00243 return false;
00244 }
00245
00246 ok = KIO::NetAccess::upload( tempFile.name(), mUrl, 0 );
00247 if ( !ok )
00248 addressBook()->error( i18n( "Unable to upload to '%1'." ).arg( mUrl.prettyURL() ) );
00249
00250 return ok;
00251 }
00252
00253 bool ResourceNet::asyncSave( Ticket* )
00254 {
00255 kdDebug(5700) << "ResourceNet::asyncSave()" << endl;
00256
00257 if (d->mIsSaving) {
00258 abortAsyncSaving();
00259 }
00260
00261 if (d->mIsLoading) {
00262 kdWarning(5700) << "Aborted asyncSave() because we're still asyncLoad()ing!" << endl;
00263 return false;
00264 }
00265
00266 bool ok = createLocalTempFile();
00267 if ( ok ) {
00268 saveToFile( mTempFile->file() );
00269 ok = mTempFile->close();
00270 }
00271
00272 if ( !ok ) {
00273 emit savingError( this, i18n( "Unable to save file '%1'." ).arg( mTempFile->name() ) );
00274 deleteLocalTempFile();
00275 return false;
00276 }
00277
00278 KURL src;
00279 src.setPath( mTempFile->name() );
00280
00281 KIO::Scheduler::checkSlaveOnHold( true );
00282 d->mIsSaving = true;
00283 d->mSaveJob = KIO::file_copy( src, mUrl, -1, true, false, false );
00284 connect( d->mSaveJob, SIGNAL( result( KIO::Job* ) ),
00285 this, SLOT( uploadFinished( KIO::Job* ) ) );
00286
00287 return true;
00288 }
00289
00290 bool ResourceNet::createLocalTempFile()
00291 {
00292 deleteStaleTempFile();
00293 mTempFile = new KTempFile();
00294 mTempFile->setAutoDelete( true );
00295 return mTempFile->status() == 0;
00296 }
00297
00298 void ResourceNet::deleteStaleTempFile()
00299 {
00300 if ( hasTempFile() ) {
00301 kdDebug(5700) << "stale temp file detected " << mTempFile->name() << endl;
00302 deleteLocalTempFile();
00303 }
00304 }
00305
00306 void ResourceNet::deleteLocalTempFile()
00307 {
00308 delete mTempFile;
00309 mTempFile = 0;
00310 }
00311
00312 void ResourceNet::saveToFile( QFile *file )
00313 {
00314 mFormat->saveAll( addressBook(), this, file );
00315 }
00316
00317 void ResourceNet::setUrl( const KURL &url )
00318 {
00319 mUrl = url;
00320 }
00321
00322 KURL ResourceNet::url() const
00323 {
00324 return mUrl;
00325 }
00326
00327 void ResourceNet::setFormat( const QString &name )
00328 {
00329 mFormatName = name;
00330 if ( mFormat )
00331 delete mFormat;
00332
00333 FormatFactory *factory = FormatFactory::self();
00334 mFormat = factory->format( mFormatName );
00335 }
00336
00337 QString ResourceNet::format() const
00338 {
00339 return mFormatName;
00340 }
00341
00342 void ResourceNet::downloadFinished( KIO::Job* )
00343 {
00344 kdDebug(5700) << "ResourceNet::downloadFinished()" << endl;
00345
00346 d->mIsLoading = false;
00347
00348 if ( !hasTempFile() || mTempFile->status() != 0 ) {
00349 emit loadingError( this, i18n( "Download failed in some way!" ) );
00350 return;
00351 }
00352
00353 QFile file( mTempFile->name() );
00354 if ( file.open( IO_ReadOnly ) ) {
00355 if ( clearAndLoad( &file ) )
00356 emit loadingFinished( this );
00357 else
00358 emit loadingError( this, i18n( "Problems during parsing file '%1'." ).arg( mTempFile->name() ) );
00359 }
00360 else {
00361 emit loadingError( this, i18n( "Unable to open file '%1'." ).arg( mTempFile->name() ) );
00362 }
00363
00364 deleteLocalTempFile();
00365 }
00366
00367 void ResourceNet::uploadFinished( KIO::Job *job )
00368 {
00369 kdDebug(5700) << "ResourceFile::uploadFinished()" << endl;
00370
00371 d->mIsSaving = false;
00372
00373 if ( job->error() )
00374 emit savingError( this, job->errorString() );
00375 else
00376 emit savingFinished( this );
00377
00378 deleteLocalTempFile();
00379 }
00380
00381 #include "resourcenet.moc"