• 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.14
  • 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() || d->mReadOnly ) {
317  return false; // No file loaded yet or it's readOnly
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  } else {
573  // if the original file was read-only, also the copied file is read-only
574  // Let's make it writable now
575  QFile::setPermissions(fileName, d->mMboxFile.permissions() | QFile::WriteOwner);
576  }
577 
578  if ( d->mAppendedEntries.size() == 0 ) {
579  return true; // Nothing to do
580  }
581 
582  QFile otherFile( fileName );
583  Q_ASSERT( otherFile.exists() );
584  if ( !otherFile.open( QIODevice::ReadWrite ) ) {
585  return false;
586  }
587 
588  otherFile.seek( d->mMboxFile.size() );
589  otherFile.write( d->mAppendedEntries );
590 
591  // Don't clear mAppendedEntries and don't update mInitialFileSize. These
592  // are still valid for the original file.
593  return true;
594  }
595 
596  if ( d->mReadOnly )
597  return false;
598 
599  if ( d->mAppendedEntries.size() == 0 ) {
600  return true; // Nothing to do.
601  }
602 
603  if ( !lock() ) {
604  return false;
605  }
606 
607  Q_ASSERT( d->mMboxFile.isOpen() );
608 
609  d->mMboxFile.seek( d->mMboxFile.size() );
610  d->mMboxFile.write( d->mAppendedEntries );
611  d->mAppendedEntries.clear();
612  d->mInitialMboxFileSize = d->mMboxFile.size();
613 
614  return unlock();
615 }
616 
617 bool MBox::setLockType( LockType ltype )
618 {
619  if ( d->mFileLocked ) {
620  kDebug() << "File is currently locked.";
621  return false; // Don't change the method if the file is currently locked.
622  }
623 
624  switch ( ltype ) {
625  case ProcmailLockfile:
626  if ( KStandardDirs::findExe( QLatin1String( "lockfile" ) ).isEmpty() ) {
627  kDebug() << "Could not find the lockfile executable";
628  return false;
629  }
630  break;
631  case MuttDotlock: // fall through
632  case MuttDotlockPrivileged:
633  if ( KStandardDirs::findExe( QLatin1String( "mutt_dotlock" ) ).isEmpty() ) {
634  kDebug() << "Could not find the mutt_dotlock executable";
635  return false;
636  }
637  break;
638  default:
639  break; // We assume fcntl available and lock_none doesn't need a check.
640  }
641 
642  d->mLockType = ltype;
643  return true;
644 }
645 
646 void MBox::setLockFile( const QString &lockFile )
647 {
648  d->mLockFileName = lockFile;
649 }
650 
651 void MBox::setUnlockTimeout( int msec )
652 {
653  d->mUnlockTimer.setInterval( msec );
654 }
655 
656 bool MBox::unlock()
657 {
658  if ( d->mLockType == None && !d->mFileLocked ) {
659  d->mFileLocked = false;
660  d->mMboxFile.close();
661  return true;
662  }
663 
664  int rc = 0;
665  QStringList args;
666 
667  switch ( d->mLockType ) {
668  case ProcmailLockfile:
669  // QFile::remove returns true on succes so negate the result.
670  if ( !d->mLockFileName.isEmpty() ) {
671  rc = !QFile( d->mLockFileName ).remove();
672  } else {
673  rc = !QFile( d->mMboxFile.fileName() + QLatin1String( ".lock" ) ).remove();
674  }
675  break;
676 
677  case MuttDotlock:
678  args << QLatin1String( "-u" )
679  << QString::fromLocal8Bit( QFile::encodeName( d->mMboxFile.fileName() ) );
680  rc = QProcess::execute( QLatin1String( "mutt_dotlock" ), args );
681  break;
682 
683  case MuttDotlockPrivileged:
684  args << QLatin1String( "-u" ) << QLatin1String( "-p" )
685  << QString::fromLocal8Bit( QFile::encodeName( d->mMboxFile.fileName() ) );
686  rc = QProcess::execute( QLatin1String( "mutt_dotlock" ), args );
687  break;
688 
689  case None: // Fall through.
690  default:
691  break;
692  }
693 
694  if ( rc == 0 ) { // Unlocking succeeded
695  d->mFileLocked = false;
696  }
697 
698  d->mMboxFile.close();
699 
700  return !d->mFileLocked;
701 }
702 
703 void MBox::setReadOnly(bool ro)
704 {
705  d->mReadOnly = ro;
706 }
707 
708 bool MBox::isReadOnly() const
709 {
710  return d->mReadOnly;
711 }
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
QProcess::execute
int execute(const QString &program, const QStringList &arguments)
KMBox::MBox::save
bool save(const QString &fileName=QString())
Writes the mbox to disk.
Definition: mbox.cpp:567
QFile::seek
virtual bool seek(qint64 pos)
KMBox::MBox::unlock
bool unlock()
Unlock the mbox file.
Definition: mbox.cpp:656
KMBox::MBox::MBox
MBox()
Creates a new mbox object.
Definition: mbox.cpp:41
QListIterator::next
const T & next()
QByteArray
QListIterator::previous
const T & previous()
QFile::remove
bool remove()
KMBox::MBox::setReadOnly
void setReadOnly(bool ro=true)
Set the access mode of the mbox file to read only.
Definition: mbox.cpp:703
QByteArray::chop
void chop(int n)
QByteArray::isEmpty
bool isEmpty() const
KMBox::MBox::setUnlockTimeout
void setUnlockTimeout(int msec)
By default the unlock method will directly unlock the file.
Definition: mbox.cpp:651
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 (the file that is loa...
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
QBuffer
QFile::setPermissions
bool setPermissions(QFlags< QFile::Permission > permissions)
QFile::exists
bool exists() const
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
QFile
QList::size
int size() const
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
QBuffer::atEnd
virtual bool atEnd() const
QString::fromLocal8Bit
QString fromLocal8Bit(const char *str, int size)
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
QList::isEmpty
bool isEmpty() const
QString::isEmpty
bool isEmpty() const
KMBox::MBoxEntry
A class that encapsulates an entry of a MBox.
Definition: mboxentry.h:38
QBuffer::open
virtual bool open(QFlags< QIODevice::OpenModeFlag > flags)
QString
KMBox::MBox::locked
bool locked() const
Returns whether or not the mbox currently is locked.
Definition: mbox.cpp:304
QList
QFile::open
virtual bool open(QFlags< QIODevice::OpenModeFlag > mode)
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
QStringList
QList::contains
bool contains(const T &value) const
KMBox::MBoxEntry::Pair
QPair< MBoxEntry, MBoxEntry > Pair
Describes a pair of mbox entry objects.
Definition: mboxentry.h:49
QLatin1String
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:646
KMBox::MBox::lock
bool lock()
Locks the mbox file using the configured lock method.
Definition: mbox.cpp:210
QByteArray::data
char * data()
QIODevice::write
qint64 write(const char *data, qint64 maxSize)
KMBox::MBox::readRawMessage
QByteArray readRawMessage(const MBoxEntry &entry)
Reads the entire message from the file for the given mbox entry.
Definition: mbox.cpp:421
QListIterator
QByteArray::size
int size() const
QBuffer::seek
virtual bool seek(qint64 pos)
QByteArray::endsWith
bool endsWith(const QByteArray &ba) const
QFile::encodeName
QByteArray encodeName(const QString &fileName)
KMBox::MBox::setLockType
bool setLockType(LockType ltype)
Sets the locktype that should be used for locking the mbox file.
Definition: mbox.cpp:617
QIODevice::readLine
qint64 readLine(char *data, qint64 maxSize)
KMBox::MBox::isReadOnly
bool isReadOnly() const
Returns if the current access mode is set to readOnly.
Definition: mbox.cpp:708
QListIterator::hasNext
bool hasNext() const
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-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:37:15 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
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2

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