maildir
maildir.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "maildir.h"
00021
00022 #include <QDir>
00023 #include <QFileInfo>
00024 #include <QUuid>
00025 #include <QDebug>
00026
00027 #include <klocale.h>
00028 #include <kpimutils/kfileio.h>
00029
00030 using namespace KPIM;
00031
00032 class Maildir::Private
00033 {
00034 public:
00035 Private( const QString& p )
00036 :path(p)
00037 {
00038 }
00039
00040 Private( const QString& p, bool isRoot )
00041 :path(p), isRoot(isRoot)
00042 {
00043 }
00044
00045 Private( const Private& rhs )
00046 {
00047 path = rhs.path;
00048 }
00049
00050 bool operator==( const Private& rhs ) const
00051 {
00052 return path == rhs.path;
00053 }
00054 bool accessIsPossible( QString& error ) const;
00055 bool canAccess( const QString& path ) const;
00056
00057 QStringList subPaths() const
00058 {
00059 QStringList paths;
00060 paths << path + QString::fromLatin1("/cur");
00061 paths << path + QString::fromLatin1("/new");
00062 paths << path + QString::fromLatin1("/tmp");
00063 return paths;
00064 }
00065
00066 QStringList listNew() const
00067 {
00068 QDir d( path + QString::fromLatin1("/new") );
00069 return d.entryList(QDir::Files);
00070 }
00071
00072 QStringList listCurrent() const
00073 {
00074 QDir d( path + QString::fromLatin1("/cur") );
00075 return d.entryList(QDir::Files);
00076 }
00077
00078 QString findRealKey( const QString& key ) const
00079 {
00080 QString realKey = path + QString::fromLatin1("/new/") + key;
00081 QFile f( realKey );
00082 if ( !f.exists() )
00083 realKey = path + QString::fromLatin1("/cur/") + key;
00084 QFile f2( realKey );
00085 if ( !f2.exists() )
00086 realKey.clear();
00087 return realKey;
00088 }
00089
00090 QString subDirPath() const
00091 {
00092 QDir dir( path );
00093 return QString::fromLatin1(".%1.directory").arg( dir.dirName() );
00094 }
00095
00096 QString path;
00097 bool isRoot;
00098 };
00099
00100 Maildir::Maildir( const QString& path, bool isRoot )
00101 :d( new Private(path, isRoot) )
00102 {
00103 }
00104
00105 void Maildir::swap( const Maildir &rhs )
00106 {
00107 Private *p = d;
00108 d = new Private( *rhs.d );
00109 delete p;
00110 }
00111
00112
00113 Maildir::Maildir(const Maildir & rhs)
00114 :d( new Private(*rhs.d) )
00115
00116 {
00117 }
00118
00119
00120 Maildir& Maildir::operator= (const Maildir & rhs)
00121 {
00122
00123 Maildir temp(rhs);
00124 swap( temp );
00125 return *this;
00126 }
00127
00128
00129 bool Maildir::operator== (const Maildir & rhs) const
00130 {
00131 return *d == *rhs.d;
00132 }
00133
00134
00135 Maildir::~Maildir()
00136 {
00137 delete d;
00138 }
00139
00140 bool Maildir::Private::canAccess( const QString& path ) const
00141 {
00142
00143
00144 QFileInfo d(path);
00145 return d.isReadable() && d.isWritable();
00146 }
00147
00148 bool Maildir::Private::accessIsPossible( QString& error ) const
00149 {
00150 QStringList paths = subPaths();
00151 paths.prepend( path );
00152
00153 Q_FOREACH( const QString &p, paths )
00154 {
00155 if ( !QFile::exists(p) ) {
00156 error = i18n("Error opening %1; this folder is missing.",p);
00157 return false;
00158 }
00159 if ( !canAccess( p ) ) {
00160 error = i18n("Error opening %1; either this is not a valid "
00161 "maildir folder, or you do not have sufficient access permissions." ,p);
00162 return false;
00163 }
00164 }
00165 return true;
00166 }
00167
00168 bool Maildir::isValid() const
00169 {
00170 QString error;
00171 return isValid( error );
00172 }
00173
00174 bool Maildir::isValid( QString &error ) const
00175 {
00176 if ( d->accessIsPossible( error ) ) {
00177 return true;
00178 }
00179 return false;
00180 }
00181
00182
00183 bool Maildir::create()
00184 {
00185
00186
00187 Q_FOREACH( const QString &p, d->subPaths() ) {
00188 QDir dir( p );
00189 if ( !dir.exists( p ) ) {
00190 if ( !dir.mkpath( p ) )
00191 return false;
00192 }
00193 }
00194 return true;
00195 }
00196
00197 QString Maildir::path() const
00198 {
00199 return d->path;
00200 }
00201
00202 QString Maildir::addSubFolder( const QString& path )
00203 {
00204 if ( !isValid() )
00205 return QString();
00206
00207
00208 QDir dir( d->path );
00209 if ( !d->isRoot ) {
00210 dir.cdUp();
00211 if (!dir.exists( d->subDirPath() ) )
00212 dir.mkdir( d->subDirPath() );
00213 dir.cd( d->subDirPath() );
00214 }
00215
00216 const QString fullPath = dir.path() + '/' + path;
00217 Maildir subdir( fullPath );
00218 if ( subdir.create() )
00219 return fullPath;
00220 return QString();
00221 }
00222
00223 bool Maildir::removeSubFolder( const QString& folderName )
00224 {
00225 if ( !isValid() ) return false;
00226 QDir dir( d->path );
00227 if ( !d->isRoot ) {
00228 dir.cdUp();
00229 if ( !dir.exists( d->subDirPath() ) ) return false;
00230 dir.cd( d->subDirPath() );
00231 }
00232 if ( !dir.exists( folderName ) ) return false;
00233
00234
00235 return KPIMUtils::removeDirAndContentsRecursively( dir.absolutePath() + '/' + folderName );
00236 }
00237
00238 Maildir Maildir::subFolder( const QString& subFolder )
00239 {
00240 if ( isValid() ) {
00241
00242 QDir dir( d->path );
00243 if ( !d->isRoot ) {
00244 dir.cdUp();
00245 if ( dir.exists( d->subDirPath() ) ) {
00246 dir.cd( d->subDirPath() );
00247 }
00248 }
00249 return Maildir( dir.path() + '/' + subFolder );
00250 }
00251 return Maildir();
00252 }
00253
00254 QStringList Maildir::entryList() const
00255 {
00256 QStringList result;
00257 if ( isValid() ) {
00258 result += d->listNew();
00259 result += d->listCurrent();
00260 }
00261
00262 return result;
00263 }
00264
00265
00266 QStringList Maildir::subFolderList() const
00267 {
00268 QDir dir( d->path );
00269
00270
00271 if ( !d->isRoot ) {
00272 dir.cdUp();
00273 if (!dir.exists( d->subDirPath() ) ) return QStringList();
00274 dir.cd( d->subDirPath() );
00275 }
00276 dir.setFilter( QDir::Dirs | QDir::NoDotAndDotDot );
00277 QStringList entries = dir.entryList();
00278 entries.removeAll( "cur" );
00279 entries.removeAll( "new" );
00280 entries.removeAll( "tmp" );
00281 return entries;
00282 }
00283
00284 QByteArray Maildir::readEntry( const QString& key ) const
00285 {
00286 QByteArray result;
00287
00288 QString realKey( d->findRealKey( key ) );
00289 if ( realKey.isEmpty() ) {
00290
00291 qWarning() << "Maildir::readEntry unable to find: " << key;
00292 return result;
00293 }
00294
00295 QFile f( realKey );
00296 f.open( QIODevice::ReadOnly );
00297
00298
00299 result = f.readAll();
00300
00301 return result;
00302 }
00303
00304 QByteArray Maildir::readEntryHeaders( const QString& key ) const
00305 {
00306 QByteArray result;
00307
00308 QString realKey( d->findRealKey( key ) );
00309 if ( realKey.isEmpty() ) {
00310
00311 qWarning() << "Maildir::readEntryHeaders unable to find: " << key;
00312 return result;
00313 }
00314
00315 QFile f( realKey );
00316 if ( !f.open( QIODevice::ReadOnly ) ) {
00317
00318 qWarning() << "Maildir::readEntryHeaders unable to find: " << key;
00319 return result;
00320 }
00321 forever {
00322 QByteArray line = f.readLine();
00323 if ( line.trimmed().isEmpty() )
00324 break;
00325 result.append( line );
00326 }
00327 return result;
00328 }
00329
00330
00331 static QString createUniqueFileName()
00332 {
00333 return QUuid::createUuid().toString();
00334 }
00335
00336 void Maildir::writeEntry( const QString& key, const QByteArray& data )
00337 {
00338 QString realKey( d->findRealKey( key ) );
00339 if ( realKey.isEmpty() ) {
00340
00341 qWarning() << "Maildir::writeEntry unable to find: " << key;
00342 return;
00343 }
00344 QFile f( realKey );
00345 f.open( QIODevice::WriteOnly );
00346 f.write( data );
00347 f.close();
00348 }
00349
00350 QString Maildir::addEntry( const QByteArray& data )
00351 {
00352 QString uniqueKey( createUniqueFileName() );
00353 QString key( d->path + "/tmp/" + uniqueKey );
00354 QString finalKey( d->path + "/new/" + uniqueKey );
00355 QFile f( key );
00356 f.open( QIODevice::WriteOnly );
00357 f.write( data );
00358 f.close();
00359
00360
00361
00362
00363
00364
00365
00366 if (!f.rename( finalKey )) {
00367 qWarning() << "Maildir: Failed to add entry: " << finalKey << "!";
00368 }
00369 return uniqueKey;
00370 }
00371
00372 bool Maildir::removeEntry( const QString& key )
00373 {
00374 QString realKey( d->findRealKey( key ) );
00375 if ( realKey.isEmpty() ) {
00376
00377 qWarning() << "Maildir::removeEntry unable to find: " << key;
00378 return false;
00379 }
00380 return QFile::remove(realKey);
00381 }
00382
00383