resourcenet.cpp
00001 /* 00002 This file is part of libtdeabc. 00003 Copyright (c) 2003 Tobias Koenig <tokoe@kde.org> 00004 00005 This library is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU Library General Public 00007 License as published by the Free Software Foundation; either 00008 version 2 of the License, or (at your option) any later version. 00009 00010 This library is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 Library General Public License for more details. 00014 00015 You should have received a copy of the GNU Library General Public License 00016 along with this library; see the file COPYING.LIB. If not, write to 00017 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00018 Boston, MA 02110-1301, USA. 00019 */ 00020 00021 #include <tqfile.h> 00022 00023 #include <kdebug.h> 00024 #include <tdeio/netaccess.h> 00025 #include <tdeio/scheduler.h> 00026 #include <tdelocale.h> 00027 #include <ksavefile.h> 00028 #include <tdetempfile.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 TDEABC; 00039 00040 class ResourceNet::ResourceNetPrivate 00041 { 00042 public: 00043 TDEIO::Job *mLoadJob; 00044 bool mIsLoading; 00045 00046 TDEIO::Job *mSaveJob; 00047 bool mIsSaving; 00048 00049 TQString mLastErrorString; 00050 }; 00051 00052 ResourceNet::ResourceNet( const TDEConfig *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(), TQString("vcard").latin1() ); 00061 } 00062 } 00063 00064 ResourceNet::ResourceNet( const KURL &url, const TQString &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 TQString &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 = TQString("vcard").latin1(); 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( TDEConfig *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 TQString tempFile; 00139 00140 if ( !TDEIO::NetAccess::download( mUrl, tempFile, 0 ) ) { 00141 addressBook()->error( i18n( "Unable to download file '%1'." ).arg( mUrl.prettyURL() ) ); 00142 return false; 00143 } 00144 00145 TQFile file( tempFile ); 00146 if ( !file.open( IO_ReadOnly ) ) { 00147 addressBook()->error( i18n( "Unable to open file '%1'." ).arg( tempFile ) ); 00148 TDEIO::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 TDEIO::NetAccess::removeTempFile( tempFile ); 00157 00158 return result; 00159 } 00160 00161 bool ResourceNet::clearAndLoad( TQFile *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 mTempFile->sync(); 00181 ok = mTempFile->close(); 00182 00183 if ( !ok ) { 00184 emit loadingError( this, i18n( "Unable to open file '%1'." ).arg( mTempFile->name() ) ); 00185 deleteLocalTempFile(); 00186 return false; 00187 } 00188 00189 KURL dest; 00190 dest.setPath( mTempFile->name() ); 00191 00192 TDEIO::Scheduler::checkSlaveOnHold( true ); 00193 d->mLoadJob = TDEIO::file_copy( mUrl, dest, -1, true, false, false ); 00194 d->mIsLoading = true; 00195 connect( d->mLoadJob, TQT_SIGNAL( result( TDEIO::Job* ) ), 00196 this, TQT_SLOT( downloadFinished( TDEIO::Job* ) ) ); 00197 00198 return true; 00199 } 00200 00201 void ResourceNet::abortAsyncLoading() 00202 { 00203 kdDebug(5700) << "ResourceNet::abortAsyncLoading()" << endl; 00204 00205 if ( d->mLoadJob ) { 00206 d->mLoadJob->kill(); // result not emitted 00207 d->mLoadJob = 0; 00208 } 00209 00210 deleteLocalTempFile(); 00211 d->mIsLoading = false; 00212 } 00213 00214 void ResourceNet::abortAsyncSaving() 00215 { 00216 kdDebug(5700) << "ResourceNet::abortAsyncSaving()" << endl; 00217 00218 if ( d->mSaveJob ) { 00219 d->mSaveJob->kill(); // result not emitted 00220 d->mSaveJob = 0; 00221 } 00222 00223 deleteLocalTempFile(); 00224 d->mIsSaving = false; 00225 } 00226 00227 bool ResourceNet::save( Ticket* ) 00228 { 00229 kdDebug(5700) << "ResourceNet::save()" << endl; 00230 00231 if (d->mIsSaving) { 00232 abortAsyncSaving(); 00233 } 00234 00235 KTempFile tempFile; 00236 tempFile.setAutoDelete( true ); 00237 bool ok = false; 00238 00239 if ( tempFile.status() == 0 && tempFile.file() ) { 00240 saveToFile( tempFile.file() ); 00241 tempFile.sync(); 00242 ok = tempFile.close(); 00243 } 00244 00245 if ( !ok ) { 00246 addressBook()->error( i18n( "Unable to save file '%1'." ).arg( tempFile.name() ) ); 00247 return false; 00248 } 00249 00250 ok = TDEIO::NetAccess::upload( tempFile.name(), mUrl, 0 ); 00251 if ( !ok ) 00252 addressBook()->error( i18n( "Unable to upload to '%1'." ).arg( mUrl.prettyURL() ) ); 00253 00254 return ok; 00255 } 00256 00257 bool ResourceNet::asyncSave( Ticket* ) 00258 { 00259 kdDebug(5700) << "ResourceNet::asyncSave()" << endl; 00260 00261 if (d->mIsSaving) { 00262 abortAsyncSaving(); 00263 } 00264 00265 if (d->mIsLoading) { 00266 kdWarning(5700) << "Aborted asyncSave() because we're still asyncLoad()ing!" << endl; 00267 return false; 00268 } 00269 00270 bool ok = createLocalTempFile(); 00271 if ( ok ) { 00272 saveToFile( mTempFile->file() ); 00273 mTempFile->sync(); 00274 ok = mTempFile->close(); 00275 } 00276 00277 if ( !ok ) { 00278 emit savingError( this, i18n( "Unable to save file '%1'." ).arg( mTempFile->name() ) ); 00279 deleteLocalTempFile(); 00280 return false; 00281 } 00282 00283 KURL src; 00284 src.setPath( mTempFile->name() ); 00285 00286 TDEIO::Scheduler::checkSlaveOnHold( true ); 00287 d->mIsSaving = true; 00288 d->mSaveJob = TDEIO::file_copy( src, mUrl, -1, true, false, false ); 00289 connect( d->mSaveJob, TQT_SIGNAL( result( TDEIO::Job* ) ), 00290 this, TQT_SLOT( uploadFinished( TDEIO::Job* ) ) ); 00291 00292 return true; 00293 } 00294 00295 bool ResourceNet::createLocalTempFile() 00296 { 00297 deleteStaleTempFile(); 00298 mTempFile = new KTempFile(); 00299 mTempFile->setAutoDelete( true ); 00300 return mTempFile->status() == 0; 00301 } 00302 00303 void ResourceNet::deleteStaleTempFile() 00304 { 00305 if ( hasTempFile() ) { 00306 kdDebug(5700) << "stale temp file detected " << mTempFile->name() << endl; 00307 deleteLocalTempFile(); 00308 } 00309 } 00310 00311 void ResourceNet::deleteLocalTempFile() 00312 { 00313 delete mTempFile; 00314 mTempFile = 0; 00315 } 00316 00317 void ResourceNet::saveToFile( TQFile *file ) 00318 { 00319 mFormat->saveAll( addressBook(), this, file ); 00320 } 00321 00322 void ResourceNet::setUrl( const KURL &url ) 00323 { 00324 mUrl = url; 00325 } 00326 00327 KURL ResourceNet::url() const 00328 { 00329 return mUrl; 00330 } 00331 00332 void ResourceNet::setFormat( const TQString &name ) 00333 { 00334 mFormatName = name; 00335 if ( mFormat ) 00336 delete mFormat; 00337 00338 FormatFactory *factory = FormatFactory::self(); 00339 mFormat = factory->format( mFormatName ); 00340 } 00341 00342 TQString ResourceNet::format() const 00343 { 00344 return mFormatName; 00345 } 00346 00347 void ResourceNet::downloadFinished( TDEIO::Job* ) 00348 { 00349 kdDebug(5700) << "ResourceNet::downloadFinished()" << endl; 00350 00351 d->mIsLoading = false; 00352 00353 if ( !hasTempFile() || mTempFile->status() != 0 ) { 00354 d->mLastErrorString = i18n( "Download failed: Unable to create temporary file" ); 00355 TQTimer::singleShot( 0, this, TQT_SLOT( signalError() ) ); 00356 return; 00357 } 00358 00359 TQFile file( mTempFile->name() ); 00360 if ( file.open( IO_ReadOnly ) ) { 00361 if ( clearAndLoad( &file ) ) 00362 emit loadingFinished( this ); 00363 else 00364 emit loadingError( this, i18n( "Problems during parsing file '%1'." ).arg( mTempFile->name() ) ); 00365 } 00366 else { 00367 emit loadingError( this, i18n( "Unable to open file '%1'." ).arg( mTempFile->name() ) ); 00368 } 00369 00370 deleteLocalTempFile(); 00371 } 00372 00373 void ResourceNet::uploadFinished( TDEIO::Job *job ) 00374 { 00375 kdDebug(5700) << "ResourceFile::uploadFinished()" << endl; 00376 00377 d->mIsSaving = false; 00378 00379 if ( job->error() ) 00380 emit savingError( this, job->errorString() ); 00381 else 00382 emit savingFinished( this ); 00383 00384 deleteLocalTempFile(); 00385 } 00386 00387 void ResourceNet::signalError() 00388 { 00389 emit loadingError( this, d->mLastErrorString ); 00390 d->mLastErrorString.truncate( 0 ); 00391 } 00392 00393 #include "resourcenet.moc"