• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • kdepim
  • Sitemap
  • Contact Us
 

maildir

maildir.cpp

Go to the documentation of this file.
00001 /*
00002     Copyright (c) 2007 Till Adam <adam@kde.org>
00003 
00004     This library is free software; you can redistribute it and/or modify it
00005     under the terms of the GNU Library General Public License as published by
00006     the Free Software Foundation; either version 2 of the License, or (at your
00007     option) any later version.
00008 
00009     This library is distributed in the hope that it will be useful, but WITHOUT
00010     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00011     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00012     License for more details.
00013 
00014     You should have received a copy of the GNU Library General Public License
00015     along with this library; see the file COPYING.LIB.  If not, write to the
00016     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00017     02110-1301, USA.
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     // copy and swap, exception safe, and handles assignment to self
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     //return access(QFile::encodeName( path ), R_OK | W_OK | X_OK ) != 0;
00143     // FIXME X_OK?
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     // FIXME: in a failure case, this will leave partially created dirs around
00186     // we should clean them up, but only if they didn't previously existed...
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     // make the subdir dir
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     // remove it recursively
00235     return KPIMUtils::removeDirAndContentsRecursively( dir.absolutePath() + '/' + folderName );
00236 }
00237 
00238 Maildir Maildir::subFolder( const QString& subFolder )
00239 {
00240     if ( isValid() ) {
00241         // make the subdir dir
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     //  kDebug() <<"Maildir::entryList()" << result;
00262     return result;
00263 }
00264 
00265 
00266 QStringList Maildir::subFolderList() const
00267 {
00268     QDir dir( d->path );
00269 
00270     // the root maildir has its subfolders directly beneath it
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         // FIXME error handling?
00291         qWarning() << "Maildir::readEntry unable to find: " << key;
00292         return result;
00293     }
00294 
00295     QFile f( realKey );
00296     f.open( QIODevice::ReadOnly );
00297 
00298     // FIXME be safer than this
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         // FIXME error handling?
00311         qWarning() << "Maildir::readEntryHeaders unable to find: " << key;
00312         return result;
00313     }
00314 
00315     QFile f( realKey );
00316     if ( !f.open( QIODevice::ReadOnly ) ) {
00317         // FIXME error handling?
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         // FIXME error handling?
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      * FIXME:
00361      *
00362      * THe whole point of the locking free maildir idea is that the moves between
00363      * the internal directories are atomic. Afaik QFile::rename does not guarantee
00364      * that, so this will need to be done properly. - ta
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         // FIXME error handling?
00377         qWarning() << "Maildir::removeEntry unable to find: " << key;
00378         return false;
00379     }
00380     return QFile::remove(realKey);
00381 }
00382 
00383 

maildir

Skip menu "maildir"
  • Main Page
  • Namespace List
  • Alphabetical List
  • Class List
  • File List
  • Class Members

kdepim

Skip menu "kdepim"
  • akonadi
  •   clients
  •   kabc
  •   kcal
  •   kcm
  • akregator
  • console
  •   kabcclient
  •   konsolekalendar
  • kaddressbook
  • kalarm
  •   lib
  • kdgantt
  • kdgantt1
  • kjots
  • kleopatra
  • kmail
  • kmobiletools
  • knode
  • knotes
  • kontact
  • kontactinterfaces
  • korganizer
  •   korgac
  • kpilot
  • ktimetracker
  •   doc
  • libkdepim
  • libkholidays
  • libkleo
  • libkpgp
  • maildir
Generated for kdepim by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal