• Skip to content
  • Skip to link menu
KDE 4.6 API Reference
  • KDE API Reference
  • KDE-PIM Libraries
  • KDE Home
  • Contact Us
 

KMBox Library

mbox.cpp

00001 /*
00002     Copyright (c) 1996-1998 Stefan Taferner <taferner@kde.org>
00003     Copyright (c) 2009 Bertjan Broeksema <broeksema@kde.org>
00004 
00005     This library is free software; you can redistribute it and/or modify it
00006     under the terms of the GNU Library General Public License as published by
00007     the Free Software Foundation; either version 2 of the License, or (at your
00008     option) any later version.
00009 
00010     This library is distributed in the hope that it will be useful, but WITHOUT
00011     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00012     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00013     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 the
00017     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00018     02110-1301, USA.
00019 
00020     NOTE: Most of the code inside here is an slightly adjusted version of
00021           kdepim/kmail/kmfoldermbox.cpp. This is why I added a line for Stefan
00022           Taferner.
00023 
00024           Bertjan Broeksema, april 2009
00025 */
00026 
00027 #include "mbox.h"
00028 #include "mbox_p.h"
00029 #include "mboxentry_p.h"
00030 
00031 #include <KDebug>
00032 #include <KStandardDirs>
00033 #include <KUrl>
00034 
00035 #include <QtCore/QBuffer>
00036 #include <QtCore/QProcess>
00037 
00038 using namespace KMBox;
00039 
00041 
00042 MBox::MBox()
00043   : d( new MBoxPrivate( this ) )
00044 {
00045   // Set some sane defaults
00046   d->mFileLocked = false;
00047   d->mLockType = None;
00048 
00049   d->mUnlockTimer.setInterval( 0 );
00050   d->mUnlockTimer.setSingleShot( true );
00051 }
00052 
00053 MBox::~MBox()
00054 {
00055   if ( d->mFileLocked ) {
00056     unlock();
00057   }
00058 
00059   d->close();
00060 
00061   delete d;
00062 }
00063 
00064 // Appended entries works as follows: When an mbox file is loaded from disk,
00065 // d->mInitialMboxFileSize is set to the file size at that moment. New entries
00066 // are stored in memory (d->mAppendedEntries). The initial file size and the size
00067 // of the buffer determine the offset for the next message to append.
00068 MBoxEntry MBox::appendMessage( const KMime::Message::Ptr &entry )
00069 {
00070   // It doesn't make sense to add entries when we don't have an reference file.
00071   Q_ASSERT( !d->mMboxFile.fileName().isEmpty() );
00072 
00073   const QByteArray rawEntry = MBoxPrivate::escapeFrom( entry->encodedContent() );
00074 
00075   if ( rawEntry.size() <= 0 ) {
00076     kDebug() << "Message added to folder `" << d->mMboxFile.fileName()
00077              << "' contains no data. Ignoring it.";
00078     return MBoxEntry();
00079   }
00080 
00081   int nextOffset = d->mAppendedEntries.size(); // Offset of the appended message
00082 
00083   // Make sure the byte array is large enough to check for an end character.
00084   // Then check if the required newlines are there.
00085   if ( nextOffset < 1 && d->mMboxFile.size() > 0 ) { // Empty, add one empty line
00086     d->mAppendedEntries.append( "\n" );
00087     ++nextOffset;
00088   } else if ( nextOffset == 1 && d->mAppendedEntries.at( 0 ) != '\n' ) {
00089     // This should actually not happen, but catch it anyway.
00090     if ( d->mMboxFile.size() < 0 ) {
00091       d->mAppendedEntries.append( "\n" );
00092       ++nextOffset;
00093     }
00094   } else if ( nextOffset >= 2 ) {
00095     if ( d->mAppendedEntries.at( nextOffset - 1 ) != '\n' ) {
00096       if ( d->mAppendedEntries.at( nextOffset ) != '\n' ) {
00097         d->mAppendedEntries.append( "\n\n" );
00098         nextOffset += 2;
00099       } else {
00100         d->mAppendedEntries.append( "\n" );
00101         ++nextOffset;
00102       }
00103     }
00104   }
00105 
00106   const QByteArray separator = MBoxPrivate::mboxMessageSeparator( rawEntry );
00107   d->mAppendedEntries.append( separator );
00108   d->mAppendedEntries.append( rawEntry );
00109   if ( rawEntry[rawEntry.size() - 1] != '\n' ) {
00110     d->mAppendedEntries.append( "\n\n" );
00111   } else {
00112     d->mAppendedEntries.append( "\n" );
00113   }
00114 
00115   MBoxEntry resultEntry;
00116   resultEntry.d->mOffset = d->mInitialMboxFileSize + nextOffset;
00117   resultEntry.d->mMessageSize = rawEntry.size();
00118   resultEntry.d->mSeparatorSize = separator.size();
00119   d->mEntries << resultEntry;
00120 
00121   return resultEntry;
00122 }
00123 
00124 MBoxEntry::List MBox::entries( const MBoxEntry::List &deletedEntries ) const
00125 {
00126   MBoxEntry::List result;
00127 
00128   foreach ( const MBoxEntry &entry, d->mEntries ) {
00129     if ( !deletedEntries.contains( entry ) ) {
00130       result << entry;
00131     }
00132   }
00133 
00134   return result;
00135 }
00136 
00137 QString MBox::fileName() const
00138 {
00139   return d->mMboxFile.fileName();
00140 }
00141 
00142 bool MBox::load( const QString &fileName )
00143 {
00144   if ( d->mFileLocked ) {
00145     return false;
00146   }
00147 
00148   d->initLoad( fileName );
00149 
00150   if ( !lock() ) {
00151     kDebug() << "Failed to lock";
00152     return false;
00153   }
00154 
00155   QByteArray line;
00156   QByteArray prevSeparator;
00157   quint64 offs = 0; // The offset of the next message to read.
00158 
00159   while ( !d->mMboxFile.atEnd() ) {
00160     quint64 pos = d->mMboxFile.pos();
00161 
00162     line = d->mMboxFile.readLine();
00163 
00164     // if atEnd, use mail only if there was a separator line at all,
00165     // otherwise it's not a valid mbox
00166     if ( d->isMBoxSeparator( line ) ||
00167          ( d->mMboxFile.atEnd() && ( prevSeparator.size() != 0 ) ) ) {
00168 
00169       // Found the separator or at end of file, the message starts at offs
00170       quint64 msgSize = pos - offs;
00171 
00172       if( pos > 0 ) {
00173         // This is not the separator of the first mail in the file. If pos == 0
00174         // than we matched the separator of the first mail in the file.
00175         MBoxEntry entry;
00176         entry.d->mOffset = offs;
00177         entry.d->mSeparatorSize = prevSeparator.size();
00178 
00179         // There is always a blank line and a separator line between two emails.
00180         // Sometimes there are two '\n' characters added to the email (i.e. when
00181         // the mail self did not end with a '\n' char) and sometimes only one to
00182         // achieve this. When reading the file it is not possible to see which
00183         // was the case.
00184         if ( d->mMboxFile.atEnd() ) {
00185           entry.d->mMessageSize = msgSize; // We use readLine so there's no additional '\n'
00186         } else {
00187           entry.d->mMessageSize = msgSize - 1;
00188         }
00189 
00190         // Don't add the separator size and the newline up to the message size.
00191         entry.d->mMessageSize -= prevSeparator.size() + 1;
00192 
00193         d->mEntries << entry;
00194       }
00195 
00196       if ( d->isMBoxSeparator( line ) ) {
00197         prevSeparator = line;
00198       }
00199 
00200       offs += msgSize; // Mark the beginning of the next message.
00201     }
00202   }
00203 
00204   // FIXME: What if unlock fails?
00205   // if no separator was found, the file is still valid if it is empty
00206   return unlock() && ( ( prevSeparator.size() != 0 ) || ( d->mMboxFile.size() == 0 ) );
00207 }
00208 
00209 bool MBox::lock()
00210 {
00211   if ( d->mMboxFile.fileName().isEmpty() ) {
00212     return false; // We cannot lock if there is no file loaded.
00213   }
00214 
00215   // We can't load another file when the mbox currently is locked so if d->mFileLocked
00216   // is true atm just return true.
00217   if ( locked() ) {
00218     return true;
00219   }
00220 
00221   if ( d->mLockType == None ) {
00222     d->mFileLocked = true;
00223     if ( d->open() ) {
00224       d->startTimerIfNeeded();
00225       return true;
00226     }
00227 
00228     d->mFileLocked = false;
00229     return false;
00230   }
00231 
00232   QStringList args;
00233   int rc = 0;
00234 
00235   switch( d->mLockType ) {
00236   case ProcmailLockfile:
00237     args << QLatin1String( "-l20" ) << QLatin1String( "-r5" );
00238     if ( !d->mLockFileName.isEmpty() ) {
00239       args << QString::fromLocal8Bit( QFile::encodeName( d->mLockFileName ) );
00240     } else {
00241       args << QString::fromLocal8Bit( QFile::encodeName( d->mMboxFile.fileName() +
00242                                                          QLatin1String( ".lock" ) ) );
00243     }
00244 
00245     rc = QProcess::execute( QLatin1String( "lockfile" ), args );
00246     if ( rc != 0 ) {
00247       kDebug() << "lockfile -l20 -r5 " << d->mMboxFile.fileName()
00248                << ": Failed ("<< rc << ") switching to read only mode";
00249       d->mReadOnly = true; // In case the MBox object was created read/write we
00250       // set it to read only when locking failed.
00251     } else {
00252       d->mFileLocked = true;
00253     }
00254     break;
00255 
00256   case MuttDotlock:
00257     args << QString::fromLocal8Bit( QFile::encodeName( d->mMboxFile.fileName() ) );
00258     rc = QProcess::execute( QLatin1String( "mutt_dotlock" ), args );
00259 
00260     if ( rc != 0 ) {
00261       kDebug() << "mutt_dotlock " << d->mMboxFile.fileName()
00262                << ": Failed (" << rc << ") switching to read only mode";
00263       d->mReadOnly = true; // In case the MBox object was created read/write we
00264       // set it to read only when locking failed.
00265     } else {
00266       d->mFileLocked = true;
00267     }
00268     break;
00269 
00270   case MuttDotlockPrivileged:
00271     args << QLatin1String( "-p" )
00272          << QString::fromLocal8Bit( QFile::encodeName( d->mMboxFile.fileName() ) );
00273     rc = QProcess::execute( QLatin1String( "mutt_dotlock" ), args );
00274 
00275     if ( rc != 0 ) {
00276       kDebug() << "mutt_dotlock -p " << d->mMboxFile.fileName() << ":"
00277                << ": Failed (" << rc << ") switching to read only mode";
00278       d->mReadOnly = true;
00279     } else {
00280       d->mFileLocked = true;
00281     }
00282     break;
00283 
00284   case None:
00285     d->mFileLocked = true;
00286     break;
00287   default:
00288     break;
00289   }
00290 
00291   if ( d->mFileLocked ) {
00292     if ( !d->open() ) {
00293       const bool unlocked = unlock();
00294       Q_ASSERT( unlocked ); // If this fails we're in trouble.
00295       Q_UNUSED( unlocked );
00296     }
00297   }
00298 
00299   d->startTimerIfNeeded();
00300   return d->mFileLocked;
00301 }
00302 
00303 bool MBox::locked() const
00304 {
00305   return d->mFileLocked;
00306 }
00307 
00308 static bool lessThanByOffset( const MBoxEntry &left, const MBoxEntry &right )
00309 {
00310   return left.messageOffset() < right.messageOffset();
00311 }
00312 
00313 bool MBox::purge( const MBoxEntry::List &deletedEntries, QList<MBoxEntry::Pair> *movedEntries )
00314 {
00315   if ( d->mMboxFile.fileName().isEmpty() ) {
00316     return false; // No file loaded yet.
00317   }
00318 
00319   if ( deletedEntries.isEmpty() ) {
00320     return true; // Nothing to do.
00321   }
00322 
00323   if ( !lock() ) {
00324     return false;
00325   }
00326 
00327   foreach ( const MBoxEntry &entry, deletedEntries ) {
00328     d->mMboxFile.seek( entry.messageOffset() );
00329     const QByteArray line = d->mMboxFile.readLine();
00330 
00331     if ( !d->isMBoxSeparator( line ) ) {
00332       qDebug() << "Found invalid separator at:" << entry.messageOffset();
00333       unlock();
00334       return false; // The file is messed up or the index is incorrect.
00335     }
00336   }
00337 
00338   // All entries are deleted, so just resize the file to a size of 0.
00339   if ( deletedEntries.size() == d->mEntries.size() ) {
00340     d->mEntries.clear();
00341     d->mMboxFile.resize( 0 );
00342     kDebug() << "Purge comleted successfully, unlocking the file.";
00343     return unlock();
00344   }
00345 
00346   qSort( d->mEntries.begin(), d->mEntries.end(), lessThanByOffset );
00347   quint64 writeOffset = 0;
00348   bool writeOffSetInitialized = false;
00349   MBoxEntry::List resultingEntryList;
00350   QList<MBoxEntry::Pair> tmpMovedEntries;
00351 
00352   quint64 origFileSize = d->mMboxFile.size();
00353 
00354   QListIterator<MBoxEntry> i( d->mEntries );
00355   while ( i.hasNext() ) {
00356     MBoxEntry entry = i.next();
00357 
00358     if ( deletedEntries.contains( entry ) && !writeOffSetInitialized ) {
00359       writeOffset = entry.messageOffset();
00360       writeOffSetInitialized = true;
00361     } else if ( writeOffSetInitialized &&
00362                 writeOffset < entry.messageOffset() &&
00363                 !deletedEntries.contains( entry ) ) {
00364       // The current message doesn't have to be deleted, but must be moved.
00365       // First determine the size of the entry that must be moved.
00366       quint64 entrySize = 0;
00367       if ( i.hasNext() ) {
00368         entrySize = i.next().messageOffset() - entry.messageOffset();
00369         i.previous(); // Go back to make sure that we also handle the next entry.
00370       } else {
00371         entrySize = origFileSize - entry.messageOffset();
00372       }
00373 
00374       Q_ASSERT( entrySize > 0 ); // MBox entries really cannot have a size <= 0;
00375 
00376       // we map the whole area of the file starting at the writeOffset up to the
00377       // message that have to be moved into memory. This includes eventually the
00378       // messages that are the deleted between the first deleted message
00379       // encountered and the message that has to be moved.
00380       quint64 mapSize = entry.messageOffset() + entrySize - writeOffset;
00381 
00382       // Now map writeOffSet + mapSize into mem.
00383       uchar *memArea = d->mMboxFile.map( writeOffset, mapSize );
00384 
00385       // Now read the entry that must be moved to writeOffset.
00386       quint64 startOffset = entry.messageOffset() - writeOffset;
00387       memmove( memArea, memArea + startOffset, entrySize );
00388 
00389       d->mMboxFile.unmap( memArea );
00390 
00391       MBoxEntry resultEntry;
00392       resultEntry.d->mOffset = writeOffset;
00393       resultEntry.d->mSeparatorSize = entry.separatorSize();
00394       resultEntry.d->mMessageSize = entry.messageSize();
00395 
00396       resultingEntryList << resultEntry;
00397       tmpMovedEntries << MBoxEntry::Pair( MBoxEntry( entry.messageOffset() ),
00398                                           MBoxEntry( resultEntry.messageOffset() ) );
00399       writeOffset += entrySize;
00400     } else if ( !deletedEntries.contains( entry ) ) {
00401       // Unmoved and not deleted entry, can only ocure before the first deleted
00402       // entry.
00403       Q_ASSERT( !writeOffSetInitialized );
00404       resultingEntryList << entry;
00405     }
00406   }
00407 
00408   // Chop off remaining entry bits.
00409   d->mMboxFile.resize( writeOffset );
00410   d->mEntries = resultingEntryList;
00411 
00412   kDebug() << "Purge comleted successfully, unlocking the file.";
00413   if ( movedEntries ) {
00414     *movedEntries = tmpMovedEntries;
00415   }
00416   return unlock(); // FIXME: What if this fails? It will return false but the
00417                    // file has changed.
00418 }
00419 
00420 QByteArray MBox::readRawMessage( const MBoxEntry &entry )
00421 {
00422   const bool wasLocked = locked();
00423   if ( !wasLocked ) {
00424     if ( !lock() ) {
00425       return QByteArray();
00426     }
00427   }
00428 
00429   // TODO: Add error handling in case locking failed.
00430 
00431   quint64 offset = entry.messageOffset();
00432 
00433   Q_ASSERT( d->mFileLocked );
00434   Q_ASSERT( d->mMboxFile.isOpen() );
00435   Q_ASSERT( ( d->mInitialMboxFileSize + d->mAppendedEntries.size() ) > offset );
00436 
00437   QByteArray message;
00438 
00439   if ( offset < d->mInitialMboxFileSize ) {
00440     d->mMboxFile.seek( offset );
00441 
00442     QByteArray line = d->mMboxFile.readLine();
00443 
00444     if ( !d->isMBoxSeparator( line ) ) {
00445       kDebug() << "[MBox::readEntry] Invalid entry at:" << offset;
00446       if ( !wasLocked ) {
00447         unlock();
00448       }
00449       return QByteArray(); // The file is messed up or the index is incorrect.
00450     }
00451 
00452     line = d->mMboxFile.readLine();
00453     while ( !d->isMBoxSeparator( line ) && !d->mMboxFile.atEnd() ) {
00454       message += line;
00455       line = d->mMboxFile.readLine();
00456     }
00457   } else {
00458     offset -= d->mInitialMboxFileSize;
00459     if ( offset > static_cast<quint64>( d->mAppendedEntries.size() ) ) {
00460       if ( !wasLocked ) {
00461         unlock();
00462       }
00463       return QByteArray();
00464     }
00465 
00466     QBuffer buffer( &(d->mAppendedEntries) );
00467     buffer.open( QIODevice::ReadOnly );
00468     buffer.seek( offset );
00469 
00470     QByteArray line = buffer.readLine();
00471 
00472     if ( !d->isMBoxSeparator( line ) ) {
00473       kDebug() << "[MBox::readEntry] Invalid appended entry at:" << offset;
00474       if ( !wasLocked ) {
00475         unlock();
00476       }
00477       return QByteArray(); // The file is messed up or the index is incorrect.
00478     }
00479 
00480     line = buffer.readLine();
00481     while ( !d->isMBoxSeparator( line ) && !buffer.atEnd() ) {
00482       message += line;
00483       line = buffer.readLine();
00484     }
00485   }
00486 
00487   // Remove te last '\n' added by writeEntry.
00488   if ( message.endsWith( '\n' ) ) {
00489     message.chop( 1 );
00490   }
00491 
00492   MBoxPrivate::unescapeFrom( message.data(), message.size() );
00493 
00494   if ( !wasLocked ) {
00495     if ( !d->startTimerIfNeeded() ) {
00496       const bool unlocked = unlock();
00497       Q_ASSERT( unlocked );
00498       Q_UNUSED( unlocked );
00499     }
00500   }
00501 
00502   return message;
00503 }
00504 
00505 KMime::Message *MBox::readMessage( const MBoxEntry &entry )
00506 {
00507   const QByteArray message = readRawMessage( entry );
00508   if ( message.isEmpty() ) {
00509     return 0;
00510   }
00511 
00512   KMime::Message *mail = new KMime::Message();
00513   mail->setContent( KMime::CRLFtoLF( message ) );
00514   mail->parse();
00515 
00516   return mail;
00517 }
00518 
00519 QByteArray MBox::readMessageHeaders( const MBoxEntry &entry )
00520 {
00521   const bool wasLocked = d->mFileLocked;
00522   if ( !wasLocked ) {
00523     lock();
00524   }
00525 
00526   const quint64 offset = entry.messageOffset();
00527 
00528   Q_ASSERT( d->mFileLocked );
00529   Q_ASSERT( d->mMboxFile.isOpen() );
00530   Q_ASSERT( ( d->mInitialMboxFileSize + d->mAppendedEntries.size() ) > offset );
00531 
00532   QByteArray headers;
00533   if ( offset < d->mInitialMboxFileSize ) {
00534     d->mMboxFile.seek( offset );
00535     QByteArray line = d->mMboxFile.readLine();
00536 
00537     while ( line[0] != '\n' && !d->mMboxFile.atEnd() ) {
00538       headers += line;
00539       line = d->mMboxFile.readLine();
00540     }
00541   } else {
00542     QBuffer buffer( &(d->mAppendedEntries) );
00543     buffer.open( QIODevice::ReadOnly );
00544     buffer.seek( offset - d->mInitialMboxFileSize );
00545     QByteArray line = buffer.readLine();
00546 
00547     while ( line[0] != '\n' && !buffer.atEnd() ) {
00548       headers += line;
00549       line = buffer.readLine();
00550     }
00551   }
00552 
00553   if ( !wasLocked ) {
00554     unlock();
00555   }
00556 
00557   return headers;
00558 }
00559 
00560 bool MBox::save( const QString &fileName )
00561 {
00562   if ( !fileName.isEmpty() && KUrl( fileName ).toLocalFile() != d->mMboxFile.fileName() ) {
00563     if ( !d->mMboxFile.copy( fileName ) ) {
00564       return false;
00565     }
00566 
00567     if ( d->mAppendedEntries.size() == 0 ) {
00568       return true; // Nothing to do
00569     }
00570 
00571     QFile otherFile( fileName );
00572     Q_ASSERT( otherFile.exists() );
00573     if ( !otherFile.open( QIODevice::ReadWrite ) ) {
00574       return false;
00575     }
00576 
00577     otherFile.seek( d->mMboxFile.size() );
00578     otherFile.write( d->mAppendedEntries );
00579 
00580     // Don't clear mAppendedEntries and don't update mInitialFileSize. These
00581     // are still valid for the original file.
00582     return true;
00583   }
00584 
00585   if ( d->mAppendedEntries.size() == 0 ) {
00586     return true; // Nothing to do.
00587   }
00588 
00589   if ( !lock() ) {
00590     return false;
00591   }
00592 
00593   Q_ASSERT( d->mMboxFile.isOpen() );
00594 
00595   d->mMboxFile.seek( d->mMboxFile.size() );
00596   d->mMboxFile.write( d->mAppendedEntries );
00597   d->mAppendedEntries.clear();
00598   d->mInitialMboxFileSize = d->mMboxFile.size();
00599 
00600   return unlock();
00601 }
00602 
00603 bool MBox::setLockType( LockType ltype )
00604 {
00605   if ( d->mFileLocked ) {
00606     kDebug() << "File is currently locked.";
00607     return false; // Don't change the method if the file is currently locked.
00608   }
00609 
00610   switch ( ltype ) {
00611     case ProcmailLockfile:
00612       if ( KStandardDirs::findExe( QLatin1String( "lockfile" ) ).isEmpty() ) {
00613         kDebug() << "Could not find the lockfile executable";
00614         return false;
00615       }
00616       break;
00617     case MuttDotlock: // fall through
00618     case MuttDotlockPrivileged:
00619       if ( KStandardDirs::findExe( QLatin1String( "mutt_dotlock" ) ).isEmpty() ) {
00620         kDebug() << "Could not find the mutt_dotlock executable";
00621         return false;
00622       }
00623       break;
00624     default:
00625       break; // We assume fcntl available and lock_none doesn't need a check.
00626   }
00627 
00628   d->mLockType = ltype;
00629   return true;
00630 }
00631 
00632 void MBox::setLockFile( const QString &lockFile )
00633 {
00634   d->mLockFileName = lockFile;
00635 }
00636 
00637 void MBox::setUnlockTimeout( int msec )
00638 {
00639   d->mUnlockTimer.setInterval( msec );
00640 }
00641 
00642 bool MBox::unlock()
00643 {
00644   if ( d->mLockType == None && !d->mFileLocked ) {
00645     d->mFileLocked = false;
00646     d->mMboxFile.close();
00647     return true;
00648   }
00649 
00650   int rc = 0;
00651   QStringList args;
00652 
00653   switch( d->mLockType ) {
00654     case ProcmailLockfile:
00655       // QFile::remove returns true on succes so negate the result.
00656       if ( !d->mLockFileName.isEmpty() ) {
00657         rc = !QFile( d->mLockFileName ).remove();
00658       } else {
00659         rc = !QFile( d->mMboxFile.fileName() + QLatin1String( ".lock" ) ).remove();
00660       }
00661       break;
00662 
00663     case MuttDotlock:
00664       args << QLatin1String( "-u" )
00665            << QString::fromLocal8Bit( QFile::encodeName( d->mMboxFile.fileName() ) );
00666       rc = QProcess::execute( QLatin1String( "mutt_dotlock" ), args );
00667       break;
00668 
00669     case MuttDotlockPrivileged:
00670       args << QLatin1String( "-u" ) << QLatin1String( "-p" )
00671            << QString::fromLocal8Bit( QFile::encodeName( d->mMboxFile.fileName() ) );
00672       rc = QProcess::execute( QLatin1String( "mutt_dotlock" ), args );
00673       break;
00674 
00675     case None: // Fall through.
00676     default:
00677       break;
00678   }
00679 
00680   if ( rc == 0 ) { // Unlocking succeeded
00681     d->mFileLocked = false;
00682   }
00683 
00684   d->mMboxFile.close();
00685 
00686   return !d->mFileLocked;
00687 }

KMBox Library

Skip menu "KMBox Library"
  • Main Page
  • Alphabetical List
  • Class List
  • File List
  • Class Members
  • Related Pages

KDE-PIM Libraries

Skip menu "KDE-PIM Libraries"
  • akonadi
  •   contact
  •   kmime
  • kabc
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  •   richtextbuilders
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Generated for KDE-PIM Libraries by doxygen 1.7.3
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