summaryrefslogtreecommitdiffstats
path: root/kmail/imapaccountbase.h
blob: 0795eb2abe99c423e6caa7354c800cfcd2149cfd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
/* -*- c++ -*-
 * imapaccountbase.h
 *
 * Copyright (c) 2000-2002 Michael Haeckel <haeckel@kde.org>
 * Copyright (c) 2002 Marc Mutz <mutz@kde.org>
 *
 * This file is based on work on pop3 and imap account implementations
 * by Don Sanders <sanders@kde.org> and Michael Haeckel <haeckel@kde.org>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; version 2 of the License
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

#ifndef __KMAIL_IMAPACCOUNTBASE_H__
#define __KMAIL_IMAPACCOUNTBASE_H__

#include <set>

#include "networkaccount.h"

#include <tqtimer.h>
#include <tqguardedptr.h>
#include <kio/global.h>

class AccountManager;
class KMFolder;
class KConfig/*Base*/;
class KMMessagePart;
class DwBodyPart;
class DwMessage;
class FolderStorage;
template <typename T> class TQValueVector;

namespace KIO {
  class Job;
}

namespace KPIM {
  class ProgressItem;
}

namespace KMail {
  struct ACLListEntry;
  struct QuotaInfo;
  typedef TQValueVector<KMail::ACLListEntry> ACLList;

  class AttachmentStrategy;

  class ImapAccountBase : public KMail::NetworkAccount {
    Q_OBJECT
  protected:
    ImapAccountBase( AccountManager * parent, const TQString & name, uint id );
  public:
    virtual ~ImapAccountBase();

    /** Set the config options to a decent state */
    virtual void init();

    /** A weak assignment operator */
    virtual void pseudoAssign( const KMAccount * a );

    /** @return whether to automatically expunge deleted messages when
        leaving the folder */
    bool autoExpunge() const { return mAutoExpunge; }
    virtual void setAutoExpunge( bool expunge );

    /** @return whether to show hidden files on the server */
    bool hiddenFolders() const { return mHiddenFolders; }
    virtual void setHiddenFolders( bool show );

    /** @return whether to show only subscribed folders */
    bool onlySubscribedFolders() const { return mOnlySubscribedFolders; }
    virtual void setOnlySubscribedFolders( bool show );

    /** @return whether to show only locally subscribed folders */
    bool onlyLocallySubscribedFolders() const { return mOnlyLocallySubscribedFolders; }
    virtual void setOnlyLocallySubscribedFolders( bool show );


    /** @return whether to load attachments on demand */
    bool loadOnDemand() const { return mLoadOnDemand; }
    virtual void setLoadOnDemand( bool load );

    /** @return whether to list only open folders */
    bool listOnlyOpenFolders() const { return mListOnlyOpenFolders; }
    virtual void setListOnlyOpenFolders( bool only );

    /** Configure the slave by adding to the meta data map */
    virtual KIO::MetaData slaveConfig() const;

    virtual void readConfig( KConfig& config );
    virtual void writeConfig( KConfig& config );

    /**
     * The state of the kioslave connection
     */
    enum ConnectionState { Error = 0, Connected, Connecting };

    // possible list types
    enum ListType {
      List,
      ListSubscribed,
      ListSubscribedNoCheck,
      ListFolderOnly,
      ListFolderOnlySubscribed
    };

    /**
     * Connect to the server, if no connection is active
     * Returns Connected (ok), Error (ko) or Connecting - which means
     * that one should wait for the slaveConnected signal from KIO::Scheduler
     * before proceeding.
     */
    ConnectionState makeConnection();

    // namespace defines
    enum imapNamespace { PersonalNS=0, OtherUsersNS=1, SharedNS=2 };

    // map a namespace type to a list of namespaces
    typedef TQMap<imapNamespace, TQStringList> nsMap;

    // map a namespace to a delimiter
    typedef TQMap<TQString, TQString> namespaceDelim;

    // map a namespace type to a map with the namespace and the delimiter
    typedef TQMap<imapNamespace, namespaceDelim> nsDelimMap;

    /**
     * Info Data for the Job
     */
    struct jobData
    {
      // Needed by TQMap, don't use
      jobData() : url(TQString::null), parent(0), current(0), total(1), done(0), offset(0), progressItem(0),
                  onlySubscribed(false), quiet(false), cancellable(false) {}
      // Real constructor
      jobData( const TQString& _url, KMFolder *_parent = 0,
          int _total = 1, int _done = 0, bool _quiet = false,
          bool _cancelable = false )
        : url(_url), parent(_parent), current(0), total(_total), done(_done), offset(0),
          progressItem(0), quiet(_quiet), cancellable(_cancelable) {}

      TQString path;
      TQString url;
      TQString curNamespace;
      TQByteArray data;
      TQCString cdata;
      TQStringList items;
      KMFolder *parent, *current;
      TQPtrList<KMMessage> msgList;
      int total, done, offset;
      KPIM::ProgressItem *progressItem;
      bool onlySubscribed, quiet, cancellable;
    };

    typedef TQMap<KIO::Job *, jobData>::Iterator JobIterator;
    /**
     * Call this when starting a new job
     */
    void insertJob( KIO::Job* job, const jobData& data ) {
      mapJobData.insert( job, data );
    }
    /**
     * Look for the jobData related to a given job. Compare with end()
     */
    JobIterator findJob( KIO::Job* job ) { return mapJobData.find( job ); }
    JobIterator jobsEnd() { return mapJobData.end(); }
    /**
     * Call this when a job is finished.
     * Don't use @p *it afterwards!
     */
    void removeJob( JobIterator& it );

    void removeJob( KIO::Job* job );

    /**
     * Subscribe (@p subscribe = TRUE) / Unsubscribe the folder
     * identified by @p imapPath.
     * Emits subscriptionChanged signal on success.
     * Emits subscriptionChangeFailed signal when it fails.
     * @param quiet if false, an error message will be displayed if the job fails.
     */
    void changeSubscription(bool subscribe, const TQString& imapPath, bool quiet = false );

    /**
     * Returns whether the account is locally subscribed to the
     * folder @param imapPath. No relation to server side subscription above.
     */
    bool locallySubscribedTo( const TQString& imapPath );

    /**
     * Locally subscribe (@p subscribe = TRUE) / Unsubscribe the folder
     * identified by @p imapPath.
     */
    void changeLocalSubscription( const TQString& imapPath, bool subscribe );


    /**
     * Retrieve the users' right on the folder
     * identified by @p folder and @p imapPath.
     * Emits receivedUserRights signal on success/error.
     */
    void getUserRights( KMFolder* folder, const TQString& imapPath );

    /**
     * Retrieve the complete list of ACLs on the folder
     * identified by @p imapPath.
     * Emits receivedACL signal on success/error.
     */
    void getACL( KMFolder* folder, const TQString& imapPath );

    /**
     * Retrieve the the quota inforamiton on the folder
     * identified by @p imapPath.
     * Emits receivedQuotaInfo signal on success/error.
     */
    void getStorageQuotaInfo( KMFolder* folder, const TQString& imapPath );

    /**
     * Set the status on the server
     * Emits imapStatusChanged signal on success/error.
     */
    void setImapStatus( KMFolder* folder, const TQString& path, const TQCString& flags );

    /**
     * Set seen status on the server.
     * Emits imapStatusChanged signal on success/error.
     */
    void setImapSeenStatus( KMFolder* folder, const TQString& path, bool seen );

    /**
     * The KIO-Slave died
     */
    void slaveDied() { mSlave = 0; killAllJobs(); }

    /**
     * Kill the slave if any jobs are active
     */
    void killAllJobs( bool disconnectSlave=false ) = 0;

    /**
     * Abort all running mail checks. Used when exiting.
     */
    virtual void cancelMailCheck();

    /**
     * Init a new-mail-check for a single folder, and optionally its subfolders.
     */
    enum FolderListType { Single, Recursive };
    void processNewMailInFolder( KMFolder* folder, FolderListType type = Single );

    /**
     * Return true if we are processing a mailcheck for a single folder
     */
    bool checkingSingleFolder() { return mCheckingSingleFolder; }

    /**
     * Called when we're completely done checking mail for this account
     * When @p seStatusMsg is true a status msg is shown
     */
    void postProcessNewMail( bool seStatusMsg = true );

    /**
     * Check whether we're checking for new mail
     * and the folder is included
     */
    bool checkingMail( KMFolder *folder );

    bool checkingMail() { return NetworkAccount::checkingMail(); }

    /**
     * Handles the result from a BODYSTRUCTURE fetch
     */
    void handleBodyStructure( TQDataStream & stream, KMMessage * msg,
                              const AttachmentStrategy *as );

    /**
     * Reimplemented. Additionally set the folder label
     */
    virtual void setFolder(KMFolder*, bool addAccount = false);

    /**
     * Returns false if the IMAP server for this account doesn't support ACLs.
     * (and true if it does, or if we didn't try yet).
     */
    bool hasACLSupport() const { return mACLSupport; }

    /**
     * Returns false if the IMAP server for this account doesn't support annotations.
     * (and true if it does, or if we didn't try yet).
     */
    bool hasAnnotationSupport() const { return mAnnotationSupport; }

    /**
     * Called if the annotation command failed due to 'unsupported'
     */
    void setHasNoAnnotationSupport() { mAnnotationSupport = false; }

    /**
     * Returns false if the IMAP server for this account doesn't support quotas.
     * (and true if it does, or if we didn't try yet).
     */
    bool hasQuotaSupport() const { return mQuotaSupport; }

    /**
     * Called if the quota command failed due to 'unsupported'
     */
    void setHasNoQuotaSupport() { mQuotaSupport = false; }

    /**
     * React to an error from the job. Uses job->error and job->errorString and calls
     * the protected virtual handleJobError with them. See handleError below for details.
     */
    bool handleJobError( KIO::Job* job, const TQString& context, bool abortSync = false );

    /**
     * Returns the root folder of this account
     */
    virtual FolderStorage* rootFolder() const = 0;

    /**
     * Progress item for listDir
     */
    KPIM::ProgressItem* listDirProgressItem();

    /**
     * @return the number of (subscribed, if applicable) folders in this
     * account.
     */
    virtual unsigned int folderCount() const;

    /**
     * @return defined namespaces
     */
    nsMap namespaces() const { return mNamespaces; }

    /**
     * Set defined namespaces
     */
    virtual void setNamespaces( nsMap map )
    { mNamespaces = map; }

    /**
     * Full blown section - namespace - delimiter map
     * Do not call this very often as the map is constructed on the fly
     */
    nsDelimMap namespacesWithDelimiter();

    /**
     * @return the namespace for the @p folder
     */
     TQString namespaceForFolder( FolderStorage* );

     /**
      * Adds "/" as needed to the given namespace
      */
     TQString addPathToNamespace( const TQString& ns );

     /**
      * @return the delimiter for the @p namespace
      */
     TQString delimiterForNamespace( const TQString& prefix );

     /**
      * @return the delimiter for the @p folderstorage
      */
     TQString delimiterForFolder( FolderStorage* );

     /**
      * @return the namespace - delimiter map
      */
     namespaceDelim namespaceToDelimiter() const
     { return mNamespaceToDelimiter; }

     /**
      * Set the namespace - delimiter map
      */
     void setNamespaceToDelimiter( namespaceDelim map )
     { mNamespaceToDelimiter = map; }

     /**
      * Returns true if the given string is a namespace
      */
     bool isNamespaceFolder( TQString& name );

     /**
      * Returns true if the account has the given capability
      */
     bool hasCapability( const TQString& capa ) {
      return mCapabilities.tqcontains( capa ); }

     /**
      * Create an IMAP path for a parent folder and a foldername
      * Parent and folder are separated with the delimiter of the account
      * The path starts and ends with '/'
      */
     TQString createImapPath( FolderStorage* parent, const TQString& folderName );

     /**
      * Create an IMAP path for a parent imapPath and a folderName
      */
     TQString createImapPath( const TQString& parent, const TQString& folderName );


  public slots:
    /**
     * Call this to get the namespaces
     * You are notified by the signal namespacesFetched
     */
    void getNamespaces();

  private slots:
    /**
     * is called when the changeSubscription has finished
     * emits subscriptionChanged
     */
    void slotSubscriptionResult(KIO::Job * job);

  protected slots:
    virtual void slotCheckQueuedFolders();

    /// Handle a message coming from the KIO scheduler saying that the slave is now connected
    void slotSchedulerSlaveConnected(KIO::Slave *aSlave);
    /// Handle an error coming from the KIO scheduler
    void slotSchedulerSlaveError(KIO::Slave *aSlave, int, const TQString &errorMsg);

    /**
     * Only delete information about the job and ignore write errors
     */
    void slotSeStatusResult(KIO::Job * job);

    /// Result of getUserRights() job
    void slotGetUserRightsResult( KIO::Job* _job );

    /// Result of getACL() job
    void slotGetACLResult( KIO::Job* _job );

    /// Result of getStorageQuotaInfo() job
    void slotGetStorageQuotaInfoResult( KIO::Job* _job );

    /**
     * Send a NOOP command regularly to keep the slave from disconnecting
     */
    void slotNoopTimeout();
    /**
     * Log out when idle
     */
    void slotIdleTimeout();

    /**
     * Kills all jobs
     */
    void slotAbortRequested( KPIM::ProgressItem* );

    /**
     * Only delete information about the job
     */
    void slotSimpleResult(KIO::Job * job);

    /** Gets and parses the namespaces */
    void slotNamespaceResult( KIO::Job*, const TQString& str );

    /**
     * Saves the fetched namespaces
     */
    void slotSaveNamespaces( const ImapAccountBase::nsDelimMap& map );

    /**
     * Saves the capabilities list
     */
    void slotCapabilitiesResult( KIO::Job*, const TQString& result );

  protected:

  /**
     * Handle an error coming from a KIO job or from a KIO slave (via the scheduler)
     * and abort everything (in all cases) if abortSync is true [this is for slotSchedulerSlaveError].
     * Otherwise (abortSync==false), dimap will only abort in case of severe errors (connection broken),
     * but on "normal" errors (no permission to delete, etc.) it will ask the user.
     *
     * @param error the error code, usually job->error())
     * @param errorMsg the error message, usually job->errorText()
     * @param job the kio job (can be 0). If set, removeJob will be called automatically.
     * This is important! It means you should not call removeJob yourself in case of errors.
     * We can't let the caller do that, since it should only be done afterwards, and only if we didn't abort.
     *
     * @param context a sentence that gives some context to the error, e.g. i18n("Error while uploading message [...]")
     * @param abortSync if true, abort sync in all cases (see above). If false, ask the user (when possible).
     * @return false when aborting, true when continuing
     */
    virtual bool handleError( int error, const TQString &errorMsg, KIO::Job* job, const TQString& context, bool abortSync = false );

    /** Handle an error during KIO::put - helper method */
    bool handlePutError( KIO::Job* job, jobData& jd, KMFolder* folder );

    virtual TQString protocol() const;
    virtual unsigned short int defaultPort() const;

    /**
     * Build KMMessageParts and DwBodyParts from the bodystructure-stream
     */
    void constructParts( TQDataStream & stream, int count, KMMessagePart* parentKMPart,
       DwBodyPart * parent, const DwMessage * dwmsg );

    /** Migrate the prefix */
    void migratePrefix();

    // used for writing the blacklist out to the config file
    TQStringList locallyBlacklistedFolders() const;
    void localBlacklistFromStringList( const TQStringList & );
    TQString prettifyQuotaError( const TQString& _error, KIO::Job * job );

  protected:
    TQPtrList<TQGuardedPtr<KMFolder> > mOpenFolders;
    TQStringList mSubfolderNames, mSubfolderPaths,
        mSubfolderMimeTypes, mSubfolderAttributes;
    TQMap<KIO::Job *, jobData> mapJobData;
    /** used to detect when the slave has not been used for a while */
    TQTimer mIdleTimer;
    /** used to send a noop to the slave in regular intervals to keep it from disonnecting */
    TQTimer mNoopTimer;
    int mTotal, mCountUnread, mCountLastUnread;
    TQMap<TQString, int> mUnreadBeforeCheck;
    bool mAutoExpunge : 1;
    bool mHiddenFolders : 1;
    bool mOnlySubscribedFolders : 1;
    bool mOnlyLocallySubscribedFolders : 1;
    bool mLoadOnDemand : 1;
    bool mListOnlyOpenFolders : 1;
    bool mProgressEnabled : 1;

    bool mErrorDialogIsActive : 1;
    bool mPasswordDialogIsActive : 1;
    bool mACLSupport : 1;
    bool mAnnotationSupport : 1;
    bool mQuotaSupport : 1;
    bool mSlaveConnected : 1;
    bool mSlaveConnectionError : 1;
    bool mCheckingSingleFolder : 1;

    // folders that should be checked for new mails
    TQValueList<TQGuardedPtr<KMFolder> > mMailCheckFolders;
    // folders that should be checked after the current check is done
    TQValueList<TQGuardedPtr<KMFolder> > mFoldersQueuedForChecking;
    // holds messageparts from the bodystructure
    TQPtrList<KMMessagePart> mBodyPartList;
    // the current message for the bodystructure
    KMMessage* mCurrentMsg;

    TQGuardedPtr<KPIM::ProgressItem> mListDirProgressItem;

    // our namespaces in the form section=namespaceList
    nsMap mNamespaces;

    // namespace - delimiter map
    namespaceDelim mNamespaceToDelimiter;

    // old prefix for migration
    TQString mOldPrefix;

    // capabilities
    TQStringList mCapabilities;

    std::set<TQString> mLocalSubscriptionBlackList;

  signals:
    /**
     * Emitted when the slave managed or failed to connect
     * This is always emitted at some point after makeConnection returned Connecting.
     * @param errorCode 0 for success, != 0 in case of error
     * @param errorMsg if errorCode is != 0, this goes with errorCode to call KIO::buildErrorString
     */
    void connectionResult( int errorCode, const TQString& errorMsg );

    /**
     * Emitted when the subscription has changed,
     * as a result of a changeSubscription call.
     */
    void subscriptionChanged(const TQString& imapPath, bool subscribed);

    /**
     * Emitted when changeSubscription() failed.
     * @param errorMessage the error message that tqcontains the reason for the failure
     */
    void subscriptionChangeFailed( const TQString &errorMessage );

    /**
     * Emitted upon completion of the job for setting the status for a group of UIDs,
     * as a result of a setImapStatus call.
     * On error, if the user chooses abort (not continue), cont is set to false.
     */
    void imapStatusChanged( KMFolder*, const TQString& imapPath, bool cont );

    /**
     * Emitted when the get-user-rights job is done,
     * as a result of a getUserRights call.
     * Use userRights() to retrieve them after using userRightsState() to see if the results are
     * valid.
     */
    void receivedUserRights( KMFolder* folder );

    /**
     * Emitted when the get-the-ACLs job is done,
     * as a result of a getACL call.
     * @param folder the folder for which we were listing the ACLs (can be 0)
     * @param job the job that was used for doing so (can be used to display errors)
     * @param entries the ACL list. Make your copy of it, it comes from the job.
     */
    void receivedACL( KMFolder* folder, KIO::Job* job, const KMail::ACLList& entries );

    /**
     * Emitted when the getQuotaInfo job is done,
     * as a result of a getQuotaInfo call.
     * @param folder The folder for which we were getting quota info (can be 0)
     * @param job The job that was used for doing so (can be used to display errors)
     * @param info The quota information for this folder. Make your copy of it,
     * it comes from the job.
     */
    void receivedStorageQuotaInfo( KMFolder* folder, KIO::Job* job, const KMail::QuotaInfo& entries );

    /**
     * Emitted when we got the namespaces
     */
    void namespacesFetched( const ImapAccountBase::nsDelimMap& );

    /**
     * Emitted when we got the namespaces, and they were set on the object.
     */
    void namespacesFetched();
  };


} // namespace KMail

#endif // __KMAIL_IMAPACCOUNTBASE_H__