summaryrefslogtreecommitdiffstats
path: root/kbiff/kbiffmonitor.h
blob: 71a9be445415746bc2f0258599a0d8ddfcc5c699 (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
/*
 * kbiffmonitor.h
 * Copyright (C) 1999-2001 Kurt Granroth <granroth@kde.org>
 *
 * $Id$
 *
 */
#ifndef KBIFFMONITOR_H
#define KBIFFMONITOR_H

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h> // Needed on some systems.
#endif

#include <sys/time.h>

#include <ntqobject.h>
#include <ntqptrlist.h>
#include <ntqfileinfo.h>

#ifdef USE_SSL
#include <kssl.h>
#endif

class KBiffURL;
class TQString;

/**
 * @internal
 * Internal class to store UIDL list
 */
class KBiffUidlList : public TQPtrList<TQString>
{
protected:
    int compareItems(Item s1, Item s2)
    {
        TQString *str1, *str2;
        str1 = (TQString *)s1;
        str2 = (TQString *)s2;
        if((*str1) == (*str2))
            return 0;
        else
            return -1;
    }
};

/**
 * @internal
 */

#define SOCKET_TIMEOUT 5

class KBiffSocket
{
public:
    KBiffSocket();
    virtual ~KBiffSocket();

    bool connectSocket(const TQString& host, unsigned short int port);
    bool active();

    bool isAsync();
    void setAsync(bool on);
    
#ifdef USE_SSL
    bool isSSL();
    void setSSL(bool on);
#endif // USE_SSL

    int numberOfMessages();
    int numberOfNewMessages();

    void close();

protected:
    TQString readLine();
    int writeLine(const TQString& line);

    bool    async;
    
    struct timeval socketTO;

    int socketFD;
    fd_set socketFDS;
    int messages;
    int newMessages;
    TQString banner;   // the first line read from a new connection

#ifdef USE_SSL
    bool usessl;
    KSSL *ssltunnel;
#endif // USE_SSL
};

/**
 * @internal
 */
class KBiffImap : public KBiffSocket
{
public:
    KBiffImap();
    virtual ~KBiffImap();

    bool command(const TQString& line, unsigned int seq);
    TQString mungeUserPass(const TQString& old_user);
    void resetNumbers();
    /**
     * @internal
     *
     * @brief Encapsulates all authentication to the IMAP server
     *
     * All authentication, including the determination of which authentication
     * mechanism to use, is performed in this method.  To add an
     * authentication method, one will need to modify this method,
     * KBiffMonitor::checkImap and KBiffImap::command
     *
     * @param pseq a pointer to the number of the next IMAP command.
     *        This value will be incremented depending on the number of
     *        commands necessary for authentication.
     * @param user the user name required for authentication
     * @param pass the password required for authentication
     */
    bool authenticate(int *pseq, const TQString& user, const TQString& pass);

protected:
    /**
     * @internal
     *
     * @brief does the IMAP server support AUTH=CRAM-MD5 ?
     */
    bool auth_cram_md5;

    /**
     * @internal
     *
     * @brief the CRAM-MD5 challenge (base64 decoded) as issued by the server
     */
    TQString chall_cram_md5;
};

/**
 * @internal
 */
class KBiffPop : public KBiffSocket
{
public:
    KBiffPop();
    virtual ~KBiffPop();

    bool command(const TQString& line);
    KBiffUidlList getUidlList() const;

    void close();
    
    // Parses the banner message in the initial server response
    bool parseBanner(void);
    // Unset to disable APOP authentication
    void setApop( bool enabled );
    /**
     * @internal
     *
     * @brief Encapsulates all authentication to the POP3 server
     *
     * All authentication, including the determination of which authentication
     * mechanism to use, is performed in this method.  To add an
     * authentication method, one will need to modify this method,
     * KBiffMonitor::checkPop and KBiffPop::command
     *
     * @param user the user name required for authentication
     * @param pass the password required for authentication
     */
    bool authenticate(const TQString& user, const TQString& pass);

protected:
    KBiffUidlList  uidlList;    
    /**
     * @internal
     * @brief does the server support APOP authentication ?
     */
    bool auth_apop;
    /**
     * @internal
     * @brief the APOP challenge from the server
     */
    TQCString chall_apop;
    /**
     * @internal
     * @brief does the server support CRAM-MD5 authentication ?
     */
    bool auth_cram_md5;
    /**
     * @internal
     * @brief the CRAM-MD5 challenge (base64 decoded)
     */
    TQString chall_cram_md5;  // the CRAM-MD5 challenge (base64 decoded)
    /**
     * @internal
     * @brief does the user want APOP authentication
     */
    bool use_apop;
};

/**
 * @internal
 */
class KBiffNntp : public KBiffSocket
{
public:
    virtual ~KBiffNntp();

    bool command(const TQString& line);
    int first() const;
    int last() const;
protected:
    int firstMsg;
    int lastMsg;
};

typedef enum
{
    NewMail = 0,
    NoMail,
    OldMail,
    NoConn,
    UnknownState
} KBiffMailState;

/**
 * A "biff"-like class that can monitor local and remote mailboxes for new
 * mail.  KBiffMonitor currently supports eight protocols.
 * 
 * <UL>
 * <LI>mbox</LI> Unix style mailbox files
 * <LI>pop3</LI> POP3 
 * <LI>imap4</LI> imap4 
 * <LI>maildir</LI> Mailboxes in maildir format
 * <LI>mh</LI> Mailboxes in MH format
 * <LI>file</LI> Simple files (no parsing)
 * <LI>nntp</LI> USENET newsgroups
 * <LI>imap4s</LI> imap4 over SSL
 * <LI>pop3s</LI> POP3 over SSL
 * </UL>
 *
 * A typical usage would look like so:
 *
 * <PRE>
 *    KBiffMonitor mon;
 *    mon.setMailbox("imap4://user:password@some.host.net/mailbox");
 *    mon.setPollInterval(15);
 *    mon.start();
 *
 *    connect(&mon, SIGNAL(signal_newMail()), this, SLOT(processNewMail()));
 *    connect(&mon, SIGNAL(signal_oldMail()), this, SLOT(processOldMail()));
 *    connect(&mon, SIGNAL(signal_noMail()), this, SLOT(processNoMail()));
 *    connect(&mon, SIGNAL(signal_noConn()), this, SLOT(processNoConn()));
 * </PRE>
 *
 * @short A "biff" class that monitors local and remote mailboxes
 * @author Kurt Granroth <granroth@kde.org>
 * @version $Id$
 */
class KBiffMonitor : public TQObject
{

    Q_OBJECT
public:

    /**
     * Constructor.  Does not take any arguments
     */
    KBiffMonitor();

    /**
     * Destructor.
     */
    virtual ~KBiffMonitor();

    /**
     * Returns the current state of the mailbox (NewMail, OldMail, NoMail, or
     * UnknownState)
     */
    KBiffMailState getMailState() const { return mailState; }

    /**
     * Returns the simpleURL of current mailbox being monitored
     */
    const TQString getMailbox() const { return simpleURL; }

    /**
     * Sets or Returns the key of current mailbox being monitored
     */
    const TQString getMailboxKey() const { return key; }

    /**
     * Returns the type of mailbox being monitored
     */
    const TQString getProtocol() const { return protocol; }
    /**
     * Returns <CODE>true</CODE> is KBiffMonitor is currently monitoring
     * a mailbox.
     */
    bool isRunning() { return started; }

    /**
     * Returns the number of new messages for the current mailbox
     */
    int newMessages() { return newCount; }

    /**
     * Returns the number of messages for the current mailbox
     */
    int curMessages() { return curCount; }


    void saveConfig();
    void readConfig();

public slots:
    /**
     * Sets the mailbox to monitor.  It uses a KBiffURL to specify the
     * protocol, host, username, password, port and path (depending on
     * protocol type).  KBiffMonitor recognizes eight protocols:
     * 
     * <UL>
     * <LI>mbox</LI> Unix style mailbox files
     * <LI>pop3</LI> POP3 
     * <LI>imap4</LI> IMAP4 
     * <LI>maildir</LI> Mailboxes in maildir format
     * <LI>mh</LI> Mailboxes in MH format
     * <LI>nttp</LI> USENET newsgroups
     * <LI>imap4s</LI> imap4 over SSL
     * <LI>pop3s</LI> POP3 over SSL
     * </UL>
     *
     * Some examples:
     * <PRE>
     * mbox:/var/spool/mail/granroth
     * </PRE>
     *
     * This would monitor a local file called '/var/spool/mail/granroth'
     *
     * <PRE>
     * pop3://granroth:password@host.net:1234
     * </PRE>
     *
     * This would monitor POP3 mailbox 'granroth' on server 'host.net'
     * using 1234 as the port and 'password' as the password.
     *
     * <PRE>
     * imap4://granroth:password@host.net/Mail/mailbox
     * </PRE>
     *
     * This would monitor IMAP4 mailbox 'Mail/mailbox' on server 'host.net'
     * with 'granroth' as the user and 'password' as the password.
     */
    void setMailbox(KBiffURL& url);

    /**
     * Overloaded for convenience
     */
    void setMailbox(const TQString& url);
    void setMailboxKey(const TQString& k);

    /**
     * Sets the password for the POP3 and IMAP4 protocols.
     */
    void setPassword(const TQString& password);

    /**
     * Set the interval between mailbox reads.  This is in seconds.
     */
    void setPollInterval(const int interval);

    /**
     * Start monitoring the mailbox
     */
    void start();

    /**
     * Stop monitoring the mailbox
     */
    void stop();

    /**
     * Fakes KBiffMonitor into thinking that the mailbox was just read
     */
    void setMailboxIsRead();

    /**
     * Forces a mailbox check
     */
    void checkMailNow();

signals:
    /**
     * This will get <CODE>emit</CODE>ed when new mail arrives
     */
    void signal_newMail();

    /**
     * This will get <CODE>emit</CODE>ed when new mail arrives
     */
    void signal_newMail(const int num_new, const TQString& mailbox);

    /**
     * This will get <CODE>emit</CODE>ed when no mail exists
     */
    void signal_noMail();

    /**
     * This will get <CODE>emit</CODE>ed when no mail exists
     */
    void signal_noMail(const TQString& mailbox);

    /**
     * This will get <CODE>emit</CODE>ed when the mailbox is read
     */
    void signal_oldMail();

    /**
     * This will get <CODE>emit</CODE>ed when the mailbox is read
     */
    void signal_oldMail(const TQString& mailbox);

   /**
    * This will get <CODE>emit</CODE>ed when no connection can be
    * established
    */
    void signal_noConn();
               
   /**
    * This will get <CODE>emit</CODE>ed when no connection can
    * be established
    */
    void signal_noConn(const TQString& mailbox);

    /**
     * This will get <CODE>emit</CODE>ed everytime mail will be
     * fetched externally
     */
    void signal_fetchMail(const TQString& fetchClient);

    /**
     * This will get <CODE>emit</CODE>ed everytime the mailbox
     * should be checked (determined by @ref #setPollInterval)
     */
    void signal_checkMail();

    /**
     * This will get <CODE>emit</CODE>ed everytime the mailbox is
     * checked.  It contains the current mailbox name, state, and number
     * of new messages
     */
    void signal_currentStatus(const int, const TQString& , const KBiffMailState);

    /**
     * This will get <CODE>emit</CODE>ed everytime there was an
     * invalid login or incomplete connection to a remote server.
     */
    void signal_invalidLogin(const TQString& mailbox);

protected:
    void timerEvent(TQTimerEvent *);

protected slots:
    void checkLocal();
    void checkMbox();
    void checkPop();
    void checkMaildir();
    void checkImap();
    void checkMHdir();
    void checkNntp();

protected:
    // protected (non-slot) functions
    void determineState(unsigned int size, const TQDateTime& last_read,
                        const TQDateTime& last_modified);
    void determineState(unsigned int size);
    
    void determineState(KBiffUidlList uidl_list);
    void determineState(KBiffMailState state);
    void onStateChanged();
    int  mboxMessages();

    void invalidLogin();

private:
    // General stuff
    int     poll;
    int     oldTimer;
    bool    started;
    int     newCount;
    int     curCount;
    int     oldCount;
    bool    firstRun;

    // Mailbox stuff
    TQString key;
    TQString simpleURL;
    TQString protocol;
    TQString mailbox;
    TQString server;
    TQString user;
    TQString password;
    TQString fetchCommand;
    unsigned short int port;
    bool    preauth;
    bool    keepalive;

    // New state cache
    unsigned int   new_lastSize;
    TQDateTime      new_lastRead;
    TQDateTime      new_lastModified;
    KBiffUidlList  new_uidlList;
    bool           b_new_lastSize;
    bool           b_new_lastRead;
    bool           b_new_lastModified;
    bool           b_new_uidlList;
    // State variables
    KBiffMailState mailState;
    unsigned int   lastSize;
    TQDateTime      lastRead;
    TQDateTime      lastModified;
    KBiffUidlList  uidlList;

    // Socket protocols
    KBiffImap      *imap;
    KBiffPop       *pop;
    KBiffNntp      *nntp;
};

#endif // KBIFFMONITOR_H