• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdepimlibs API Reference
  • KDE Home
  • Contact Us
 

KMBox Library

  • sources
  • kde-4.12
  • kdepimlibs
  • kmbox
mbox.cpp
1 /*
2  Copyright (c) 1996-1998 Stefan Taferner <taferner@kde.org>
3  Copyright (c) 2009 Bertjan Broeksema <broeksema@kde.org>
4 
5  This library is free software; you can redistribute it and/or modify it
6  under the terms of the GNU Library General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or (at your
8  option) any later version.
9 
10  This library is distributed in the hope that it will be useful, but WITHOUT
11  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
13  License for more details.
14 
15  You should have received a copy of the GNU Library General Public License
16  along with this library; see the file COPYING.LIB. If not, write to the
17  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18  02110-1301, USA.
19 
20  NOTE: Most of the code inside here is an slightly adjusted version of
21  kdepim/kmail/kmfoldermbox.cpp. This is why I added a line for Stefan Taferner.
22 
23  Bertjan Broeksema, april 2009
24 */
25 
26 #include "mbox.h"
27 #include "mbox_p.h"
28 #include "mboxentry_p.h"
29 
30 #include <KDebug>
31 #include <KStandardDirs>
32 #include <KUrl>
33 
34 #include <QtCore/QBuffer>
35 #include <QtCore/QProcess>
36 
37 using namespace KMBox;
38 
40 
41 MBox::MBox()
42  : d( new MBoxPrivate( this ) )
43 {
44  // Set some sane defaults
45  d->mFileLocked = false;
46  d->mLockType = None;
47 
48  d->mUnlockTimer.setInterval( 0 );
49  d->mUnlockTimer.setSingleShot( true );
50 }
51 
52 MBox::~MBox()
53 {
54  if ( d->mFileLocked ) {
55  unlock();
56  }
57 
58  d->close();
59 
60  delete d;
61 }
62 
63 // Appended entries works as follows: When an mbox file is loaded from disk,
64 // d->mInitialMboxFileSize is set to the file size at that moment. New entries
65 // are stored in memory (d->mAppendedEntries). The initial file size and the size
66 // of the buffer determine the offset for the next message to append.
67 MBoxEntry MBox::appendMessage( const KMime::Message::Ptr &entry )
68 {
69  // It doesn't make sense to add entries when we don't have an reference file.
70  Q_ASSERT( !d->mMboxFile.fileName().isEmpty() );
71 
72  const QByteArray rawEntry = MBoxPrivate::escapeFrom( entry->encodedContent() );
73 
74  if ( rawEntry.size() <= 0 ) {
75  kDebug() << "Message added to folder `" << d->mMboxFile.fileName()
76  << "' contains no data. Ignoring it.";
77  return MBoxEntry();
78  }
79 
80  int nextOffset = d->mAppendedEntries.size(); // Offset of the appended message
81 
82  // Make sure the byte array is large enough to check for an end character.
83  // Then check if the required newlines are there.
84  if ( nextOffset < 1 && d->mMboxFile.size() > 0 ) { // Empty, add one empty line
85  d->mAppendedEntries.append( "\n" );
86  ++nextOffset;
87  } else if ( nextOffset == 1 && d->mAppendedEntries.at( 0 ) != '\n' ) {
88  // This should actually not happen, but catch it anyway.
89  if ( d->mMboxFile.size() < 0 ) {
90  d->mAppendedEntries.append( "\n" );
91  ++nextOffset;
92  }
93  } else if ( nextOffset >= 2 ) {
94  if ( d->mAppendedEntries.at( nextOffset - 1 ) != '\n' ) {
95  if ( d->mAppendedEntries.at( nextOffset ) != '\n' ) {
96  d->mAppendedEntries.append( "\n\n" );
97  nextOffset += 2;
98  } else {
99  d->mAppendedEntries.append( "\n" );
100  ++nextOffset;
101  }
102  }
103  }
104 
105  const QByteArray separator = MBoxPrivate::mboxMessageSeparator( rawEntry );
106  d->mAppendedEntries.append( separator );
107  d->mAppendedEntries.append( rawEntry );
108  if ( rawEntry[rawEntry.size() - 1] != '\n' ) {
109  d->mAppendedEntries.append( "\n\n" );
110  } else {
111  d->mAppendedEntries.append( "\n" );
112  }
113 
114  MBoxEntry resultEntry;
115  resultEntry.d->mOffset = d->mInitialMboxFileSize + nextOffset;
116  resultEntry.d->mMessageSize = rawEntry.size();
117  resultEntry.d->mSeparatorSize = separator.size();
118  d->mEntries << resultEntry;
119 
120  return resultEntry;
121 }
122 
123 MBoxEntry::List MBox::entries( const MBoxEntry::List &deletedEntries ) const
124 {
125  if ( deletedEntries.isEmpty() ) {
126  // fast path
127  return d->mEntries;
128  }
129 
130  MBoxEntry::List result;
131 
132  foreach ( const MBoxEntry &entry, d->mEntries ) {
133  if ( !deletedEntries.contains( entry ) ) {
134  result << entry;
135  }
136  }
137 
138  return result;
139 }
140 
141 QString MBox::fileName() const
142 {
143  return d->mMboxFile.fileName();
144 }
145 
146 bool MBox::load( const QString &fileName )
147 {
148  if ( d->mFileLocked ) {
149  return false;
150  }
151 
152  d->initLoad( fileName );
153 
154  if ( !lock() ) {
155  kDebug() << "Failed to lock";
156  return false;
157  }
158 
159  d->mInitialMboxFileSize = d->mMboxFile.size(); // AFTER the file has been locked
160 
161  QByteArray line;
162  QByteArray prevSeparator;
163  quint64 offs = 0; // The offset of the next message to read.
164 
165  while ( !d->mMboxFile.atEnd() ) {
166  quint64 pos = d->mMboxFile.pos();
167 
168  line = d->mMboxFile.readLine();
169 
170  // if atEnd, use mail only if there was a separator line at all,
171  // otherwise it's not a valid mbox
172  if ( d->isMBoxSeparator( line ) ||
173  ( d->mMboxFile.atEnd() && ( prevSeparator.size() != 0 ) ) ) {
174 
175  // if we are the at the file end, update pos to not forget the last line
176  if ( d->mMboxFile.atEnd() ) {
177  pos = d->mMboxFile.pos();
178  }
179 
180  // Found the separator or at end of file, the message starts at offs
181  quint64 msgSize = pos - offs;
182 
183  if ( pos > 0 ) {
184  // This is not the separator of the first mail in the file. If pos == 0
185  // than we matched the separator of the first mail in the file.
186  MBoxEntry entry;
187  entry.d->mOffset = offs;
188  entry.d->mSeparatorSize = prevSeparator.size();
189  entry.d->mMessageSize = msgSize - 1;
190 
191  // Don't add the separator size and the newline up to the message size.
192  entry.d->mMessageSize -= prevSeparator.size() + 1;
193 
194  d->mEntries << entry;
195  }
196 
197  if ( d->isMBoxSeparator( line ) ) {
198  prevSeparator = line;
199  }
200 
201  offs += msgSize; // Mark the beginning of the next message.
202  }
203  }
204 
205  // FIXME: What if unlock fails?
206  // if no separator was found, the file is still valid if it is empty
207  return unlock() && ( ( prevSeparator.size() != 0 ) || ( d->mMboxFile.size() == 0 ) );
208 }
209 
210 bool MBox::lock()
211 {
212  if ( d->mMboxFile.fileName().isEmpty() ) {
213  return false; // We cannot lock if there is no file loaded.
214  }
215 
216  // We can't load another file when the mbox currently is locked so if d->mFileLocked
217  // is true atm just return true.
218  if ( locked() ) {
219  return true;
220  }
221 
222  if ( d->mLockType == None ) {
223  d->mFileLocked = true;
224  if ( d->open() ) {
225  d->startTimerIfNeeded();
226  return true;
227  }
228 
229  d->mFileLocked = false;
230  return false;
231  }
232 
233  QStringList args;
234  int rc = 0;
235 
236  switch ( d->mLockType ) {
237  case ProcmailLockfile:
238  args << QLatin1String( "-l20" ) << QLatin1String( "-r5" );
239  if ( !d->mLockFileName.isEmpty() ) {
240  args << QString::fromLocal8Bit( QFile::encodeName( d->mLockFileName ) );
241  } else {
242  args << QString::fromLocal8Bit( QFile::encodeName( d->mMboxFile.fileName() +
243  QLatin1String( ".lock" ) ) );
244  }
245 
246  rc = QProcess::execute( QLatin1String( "lockfile" ), args );
247  if ( rc != 0 ) {
248  kDebug() << "lockfile -l20 -r5 " << d->mMboxFile.fileName()
249  << ": Failed (" << rc << ") switching to read only mode";
250  d->mReadOnly = true; // In case the MBox object was created read/write we
251  // set it to read only when locking failed.
252  } else {
253  d->mFileLocked = true;
254  }
255  break;
256 
257  case MuttDotlock:
258  args << QString::fromLocal8Bit( QFile::encodeName( d->mMboxFile.fileName() ) );
259  rc = QProcess::execute( QLatin1String( "mutt_dotlock" ), args );
260 
261  if ( rc != 0 ) {
262  kDebug() << "mutt_dotlock " << d->mMboxFile.fileName()
263  << ": Failed (" << rc << ") switching to read only mode";
264  d->mReadOnly = true; // In case the MBox object was created read/write we
265  // set it to read only when locking failed.
266  } else {
267  d->mFileLocked = true;
268  }
269  break;
270 
271  case MuttDotlockPrivileged:
272  args << QLatin1String( "-p" )
273  << QString::fromLocal8Bit( QFile::encodeName( d->mMboxFile.fileName() ) );
274  rc = QProcess::execute( QLatin1String( "mutt_dotlock" ), args );
275 
276  if ( rc != 0 ) {
277  kDebug() << "mutt_dotlock -p " << d->mMboxFile.fileName() << ":"
278  << ": Failed (" << rc << ") switching to read only mode";
279  d->mReadOnly = true;
280  } else {
281  d->mFileLocked = true;
282  }
283  break;
284 
285  case None:
286  d->mFileLocked = true;
287  break;
288  default:
289  break;
290  }
291 
292  if ( d->mFileLocked ) {
293  if ( !d->open() ) {
294  const bool unlocked = unlock();
295  Q_ASSERT( unlocked ); // If this fails we're in trouble.
296  Q_UNUSED( unlocked );
297  }
298  }
299 
300  d->startTimerIfNeeded();
301  return d->mFileLocked;
302 }
303 
304 bool MBox::locked() const
305 {
306  return d->mFileLocked;
307 }
308 
309 static bool lessThanByOffset( const MBoxEntry &left, const MBoxEntry &right )
310 {
311  return left.messageOffset() < right.messageOffset();
312 }
313 
314 bool MBox::purge( const MBoxEntry::List &deletedEntries, QList<MBoxEntry::Pair> *movedEntries )
315 {
316  if ( d->mMboxFile.fileName().isEmpty() ) {
317  return false; // No file loaded yet.
318  }
319 
320  if ( deletedEntries.isEmpty() ) {
321  return true; // Nothing to do.
322  }
323 
324  if ( !lock() ) {
325  return false;
326  }
327 
328  foreach ( const MBoxEntry &entry, deletedEntries ) {
329  d->mMboxFile.seek( entry.messageOffset() );
330  const QByteArray line = d->mMboxFile.readLine();
331 
332  if ( !d->isMBoxSeparator( line ) ) {
333  qDebug() << "Found invalid separator at:" << entry.messageOffset();
334  unlock();
335  return false; // The file is messed up or the index is incorrect.
336  }
337  }
338 
339  // All entries are deleted, so just resize the file to a size of 0.
340  if ( deletedEntries.size() == d->mEntries.size() ) {
341  d->mEntries.clear();
342  d->mMboxFile.resize( 0 );
343  kDebug() << "Purge comleted successfully, unlocking the file.";
344  return unlock();
345  }
346 
347  qSort( d->mEntries.begin(), d->mEntries.end(), lessThanByOffset );
348  quint64 writeOffset = 0;
349  bool writeOffSetInitialized = false;
350  MBoxEntry::List resultingEntryList;
351  QList<MBoxEntry::Pair> tmpMovedEntries;
352 
353  quint64 origFileSize = d->mMboxFile.size();
354 
355  QListIterator<MBoxEntry> i( d->mEntries );
356  while ( i.hasNext() ) {
357  MBoxEntry entry = i.next();
358 
359  if ( deletedEntries.contains( entry ) && !writeOffSetInitialized ) {
360  writeOffset = entry.messageOffset();
361  writeOffSetInitialized = true;
362  } else if ( writeOffSetInitialized &&
363  writeOffset < entry.messageOffset() &&
364  !deletedEntries.contains( entry ) ) {
365  // The current message doesn't have to be deleted, but must be moved.
366  // First determine the size of the entry that must be moved.
367  quint64 entrySize = 0;
368  if ( i.hasNext() ) {
369  entrySize = i.next().messageOffset() - entry.messageOffset();
370  i.previous(); // Go back to make sure that we also handle the next entry.
371  } else {
372  entrySize = origFileSize - entry.messageOffset();
373  }
374 
375  Q_ASSERT( entrySize > 0 ); // MBox entries really cannot have a size <= 0;
376 
377  // we map the whole area of the file starting at the writeOffset up to the
378  // message that have to be moved into memory. This includes eventually the
379  // messages that are the deleted between the first deleted message
380  // encountered and the message that has to be moved.
381  quint64 mapSize = entry.messageOffset() + entrySize - writeOffset;
382 
383  // Now map writeOffSet + mapSize into mem.
384  uchar *memArea = d->mMboxFile.map( writeOffset, mapSize );
385 
386  // Now read the entry that must be moved to writeOffset.
387  quint64 startOffset = entry.messageOffset() - writeOffset;
388  memmove( memArea, memArea + startOffset, entrySize );
389 
390  d->mMboxFile.unmap( memArea );
391 
392  MBoxEntry resultEntry;
393  resultEntry.d->mOffset = writeOffset;
394  resultEntry.d->mSeparatorSize = entry.separatorSize();
395  resultEntry.d->mMessageSize = entry.messageSize();
396 
397  resultingEntryList << resultEntry;
398  tmpMovedEntries << MBoxEntry::Pair( MBoxEntry( entry.messageOffset() ),
399  MBoxEntry( resultEntry.messageOffset() ) );
400  writeOffset += entrySize;
401  } else if ( !deletedEntries.contains( entry ) ) {
402  // Unmoved and not deleted entry, can only ocure before the first deleted
403  // entry.
404  Q_ASSERT( !writeOffSetInitialized );
405  resultingEntryList << entry;
406  }
407  }
408 
409  // Chop off remaining entry bits.
410  d->mMboxFile.resize( writeOffset );
411  d->mEntries = resultingEntryList;
412 
413  kDebug() << "Purge comleted successfully, unlocking the file.";
414  if ( movedEntries ) {
415  *movedEntries = tmpMovedEntries;
416  }
417  return unlock(); // FIXME: What if this fails? It will return false but the
418  // file has changed.
419 }
420 
421 QByteArray MBox::readRawMessage( const MBoxEntry &entry )
422 {
423  const bool wasLocked = locked();
424  if ( !wasLocked ) {
425  if ( !lock() ) {
426  return QByteArray();
427  }
428  }
429 
430  // TODO: Add error handling in case locking failed.
431 
432  quint64 offset = entry.messageOffset();
433 
434  Q_ASSERT( d->mFileLocked );
435  Q_ASSERT( d->mMboxFile.isOpen() );
436  Q_ASSERT( ( d->mInitialMboxFileSize + d->mAppendedEntries.size() ) > offset );
437 
438  QByteArray message;
439 
440  if ( offset < d->mInitialMboxFileSize ) {
441  d->mMboxFile.seek( offset );
442 
443  QByteArray line = d->mMboxFile.readLine();
444 
445  if ( !d->isMBoxSeparator( line ) ) {
446  kDebug() << "[MBox::readEntry] Invalid entry at:" << offset;
447  if ( !wasLocked ) {
448  unlock();
449  }
450  return QByteArray(); // The file is messed up or the index is incorrect.
451  }
452 
453  line = d->mMboxFile.readLine();
454  while ( !d->isMBoxSeparator( line ) ) {
455  message += line;
456  if ( d->mMboxFile.atEnd() ) {
457  break;
458  }
459  line = d->mMboxFile.readLine();
460  }
461  } else {
462  offset -= d->mInitialMboxFileSize;
463  if ( offset > static_cast<quint64>( d->mAppendedEntries.size() ) ) {
464  if ( !wasLocked ) {
465  unlock();
466  }
467  return QByteArray();
468  }
469 
470  QBuffer buffer( &( d->mAppendedEntries ) );
471  buffer.open( QIODevice::ReadOnly );
472  buffer.seek( offset );
473 
474  QByteArray line = buffer.readLine();
475 
476  if ( !d->isMBoxSeparator( line ) ) {
477  kDebug() << "[MBox::readEntry] Invalid appended entry at:" << offset;
478  if ( !wasLocked ) {
479  unlock();
480  }
481  return QByteArray(); // The file is messed up or the index is incorrect.
482  }
483 
484  line = buffer.readLine();
485  while ( !d->isMBoxSeparator( line ) && !buffer.atEnd() ) {
486  message += line;
487  line = buffer.readLine();
488  }
489  }
490 
491  // Remove te last '\n' added by writeEntry.
492  if ( message.endsWith( '\n' ) ) {
493  message.chop( 1 );
494  }
495 
496  MBoxPrivate::unescapeFrom( message.data(), message.size() );
497 
498  if ( !wasLocked ) {
499  if ( !d->startTimerIfNeeded() ) {
500  const bool unlocked = unlock();
501  Q_ASSERT( unlocked );
502  Q_UNUSED( unlocked );
503  }
504  }
505 
506  return message;
507 }
508 
509 KMime::Message *MBox::readMessage( const MBoxEntry &entry )
510 {
511  const QByteArray message = readRawMessage( entry );
512  if ( message.isEmpty() ) {
513  return 0;
514  }
515 
516  KMime::Message *mail = new KMime::Message();
517  mail->setContent( KMime::CRLFtoLF( message ) );
518  mail->parse();
519 
520  return mail;
521 }
522 
523 QByteArray MBox::readMessageHeaders( const MBoxEntry &entry )
524 {
525  const bool wasLocked = d->mFileLocked;
526  if ( !wasLocked ) {
527  if (!lock()) {
528  kDebug() << "Failed to lock";
529  return QByteArray();
530  }
531  }
532 
533  const quint64 offset = entry.messageOffset();
534 
535  Q_ASSERT( d->mFileLocked );
536  Q_ASSERT( d->mMboxFile.isOpen() );
537  Q_ASSERT( ( d->mInitialMboxFileSize + d->mAppendedEntries.size() ) > offset );
538 
539  QByteArray headers;
540  if ( offset < d->mInitialMboxFileSize ) {
541  d->mMboxFile.seek( offset );
542  QByteArray line = d->mMboxFile.readLine();
543 
544  while ( line[0] != '\n' && !d->mMboxFile.atEnd() ) {
545  headers += line;
546  line = d->mMboxFile.readLine();
547  }
548  } else {
549  QBuffer buffer( &( d->mAppendedEntries ) );
550  buffer.open( QIODevice::ReadOnly );
551  buffer.seek( offset - d->mInitialMboxFileSize );
552  QByteArray line = buffer.readLine();
553 
554  while ( line[0] != '\n' && !buffer.atEnd() ) {
555  headers += line;
556  line = buffer.readLine();
557  }
558  }
559 
560  if ( !wasLocked ) {
561  unlock();
562  }
563 
564  return headers;
565 }
566 
567 bool MBox::save( const QString &fileName )
568 {
569  if ( !fileName.isEmpty() && KUrl( fileName ).toLocalFile() != d->mMboxFile.fileName() ) {
570  if ( !d->mMboxFile.copy( fileName ) ) {
571  return false;
572  }
573 
574  if ( d->mAppendedEntries.size() == 0 ) {
575  return true; // Nothing to do
576  }
577 
578  QFile otherFile( fileName );
579  Q_ASSERT( otherFile.exists() );
580  if ( !otherFile.open( QIODevice::ReadWrite ) ) {
581  return false;
582  }
583 
584  otherFile.seek( d->mMboxFile.size() );
585  otherFile.write( d->mAppendedEntries );
586 
587  // Don't clear mAppendedEntries and don't update mInitialFileSize. These
588  // are still valid for the original file.
589  return true;
590  }
591 
592  if ( d->mAppendedEntries.size() == 0 ) {
593  return true; // Nothing to do.
594  }
595 
596  if ( !lock() ) {
597  return false;
598  }
599 
600  Q_ASSERT( d->mMboxFile.isOpen() );
601 
602  d->mMboxFile.seek( d->mMboxFile.size() );
603  d->mMboxFile.write( d->mAppendedEntries );
604  d->mAppendedEntries.clear();
605  d->mInitialMboxFileSize = d->mMboxFile.size();
606 
607  return unlock();
608 }
609 
610 bool MBox::setLockType( LockType ltype )
611 {
612  if ( d->mFileLocked ) {
613  kDebug() << "File is currently locked.";
614  return false; // Don't change the method if the file is currently locked.
615  }
616 
617  switch ( ltype ) {
618  case ProcmailLockfile:
619  if ( KStandardDirs::findExe( QLatin1String( "lockfile" ) ).isEmpty() ) {
620  kDebug() << "Could not find the lockfile executable";
621  return false;
622  }
623  break;
624  case MuttDotlock: // fall through
625  case MuttDotlockPrivileged:
626  if ( KStandardDirs::findExe( QLatin1String( "mutt_dotlock" ) ).isEmpty() ) {
627  kDebug() << "Could not find the mutt_dotlock executable";
628  return false;
629  }
630  break;
631  default:
632  break; // We assume fcntl available and lock_none doesn't need a check.
633  }
634 
635  d->mLockType = ltype;
636  return true;
637 }
638 
639 void MBox::setLockFile( const QString &lockFile )
640 {
641  d->mLockFileName = lockFile;
642 }
643 
644 void MBox::setUnlockTimeout( int msec )
645 {
646  d->mUnlockTimer.setInterval( msec );
647 }
648 
649 bool MBox::unlock()
650 {
651  if ( d->mLockType == None && !d->mFileLocked ) {
652  d->mFileLocked = false;
653  d->mMboxFile.close();
654  return true;
655  }
656 
657  int rc = 0;
658  QStringList args;
659 
660  switch ( d->mLockType ) {
661  case ProcmailLockfile:
662  // QFile::remove returns true on succes so negate the result.
663  if ( !d->mLockFileName.isEmpty() ) {
664  rc = !QFile( d->mLockFileName ).remove();
665  } else {
666  rc = !QFile( d->mMboxFile.fileName() + QLatin1String( ".lock" ) ).remove();
667  }
668  break;
669 
670  case MuttDotlock:
671  args << QLatin1String( "-u" )
672  << QString::fromLocal8Bit( QFile::encodeName( d->mMboxFile.fileName() ) );
673  rc = QProcess::execute( QLatin1String( "mutt_dotlock" ), args );
674  break;
675 
676  case MuttDotlockPrivileged:
677  args << QLatin1String( "-u" ) << QLatin1String( "-p" )
678  << QString::fromLocal8Bit( QFile::encodeName( d->mMboxFile.fileName() ) );
679  rc = QProcess::execute( QLatin1String( "mutt_dotlock" ), args );
680  break;
681 
682  case None: // Fall through.
683  default:
684  break;
685  }
686 
687  if ( rc == 0 ) { // Unlocking succeeded
688  d->mFileLocked = false;
689  }
690 
691  d->mMboxFile.close();
692 
693  return !d->mFileLocked;
694 }
KMBox::MBox::readMessage
KMime::Message * readMessage(const MBoxEntry &entry)
Reads the entire message from the file for the given mbox entry.
Definition: mbox.cpp:509
KMBox::MBox::save
bool save(const QString &fileName=QString())
Writes the mbox to disk.
Definition: mbox.cpp:567
KMBox::MBox::unlock
bool unlock()
Unlock the mbox file.
Definition: mbox.cpp:649
KMBox::MBox::MBox
MBox()
Creates a new mbox object.
Definition: mbox.cpp:41
KMBox::MBoxEntry::List
QList< MBoxEntry > List
Describes a list of mbox entry objects.
Definition: mboxentry.h:44
KMBox::MBox::setUnlockTimeout
void setUnlockTimeout(int msec)
By default the unlock method will directly unlock the file.
Definition: mbox.cpp:644
KMBox::MBox::purge
bool purge(const MBoxEntry::List &deletedEntries, QList< MBoxEntry::Pair > *movedEntries=0)
Removes all messages for the given mbox entries from the current reference file (i.e.
Definition: mbox.cpp:314
KMBox::MBox::readMessageHeaders
QByteArray readMessageHeaders(const MBoxEntry &entry)
Reads the headers of the message for the given mbox entry.
Definition: mbox.cpp:523
KMBox::MBoxEntry::messageOffset
quint64 messageOffset() const
Returns the offset of the message that is referenced by this mbox entry object.
Definition: mboxentry.cpp:70
KMBox::MBox::LockType
LockType
Describes the type of locking that will be used.
Definition: mbox.h:44
KMBox::MBox::appendMessage
MBoxEntry appendMessage(const KMime::Message::Ptr &message)
Appends message to the MBox and returns the corresponding mbox entry for it.
Definition: mbox.cpp:67
KMBox::MBoxEntry::messageSize
quint64 messageSize() const
Returns the size of the message that is referenced by this mbox entry object.
Definition: mboxentry.cpp:75
KMBox::MBox::~MBox
~MBox()
Destroys the mbox object.
Definition: mbox.cpp:52
KMBox::MBox::fileName
QString fileName() const
Returns the file name that was passed to the last call to load().
Definition: mbox.cpp:141
KMBox::MBox::entries
MBoxEntry::List entries(const MBoxEntry::List &deletedEntries=MBoxEntry::List()) const
Retrieve the mbox entry objects for all emails from the file except the deleteEntries.
Definition: mbox.cpp:123
KMBox::MBoxEntry
A class that encapsulates an entry of a MBox.
Definition: mboxentry.h:38
KMBox::MBox::locked
bool locked() const
Returns whether or not the mbox currently is locked.
Definition: mbox.cpp:304
KMBox::MBoxEntry::separatorSize
quint64 separatorSize() const
Returns the separator size of the message that is referenced by this mbox entry object.
Definition: mboxentry.cpp:80
KMBox::MBoxEntry::Pair
QPair< MBoxEntry, MBoxEntry > Pair
Describes a pair of mbox entry objects.
Definition: mboxentry.h:49
KMBox::MBox::setLockFile
void setLockFile(const QString &lockFile)
Sets the lockfile that should be used by the procmail or the KDE lock file method.
Definition: mbox.cpp:639
KMBox::MBox::lock
bool lock()
Locks the mbox file using the configured lock method.
Definition: mbox.cpp:210
KMBox::MBox::readRawMessage
QByteArray readRawMessage(const MBoxEntry &entry)
Reads the entire message from the file for the given mbox entry.
Definition: mbox.cpp:421
KMBox::MBox::setLockType
bool setLockType(LockType ltype)
Sets the locktype that should be used for locking the mbox file.
Definition: mbox.cpp:610
KMBox::MBox::load
bool load(const QString &fileName)
Loads the raw mbox data from disk into the current MBox object.
Definition: mbox.cpp:146
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 23:00:10 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KMBox Library

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

kdepimlibs API Reference

Skip menu "kdepimlibs API Reference"
  • akonadi
  •   contact
  •   kmime
  •   socialutils
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kldap
  • kmbox
  • kmime
  • kpimidentities
  • kpimtextedit
  • kresources
  • ktnef
  • kxmlrpcclient
  • microblog

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal