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