| 1 |
#ifndef H_MAILBOX /* -*- mode: c++ -*- */ |
| 2 |
/* |
| 3 |
* Copyright (C) 2009-2016 TSUBAKIMOTO Hiroya <z0rac@users.sourceforge.jp> |
| 4 |
* |
| 5 |
* This software comes with ABSOLUTELY NO WARRANTY; for details of |
| 6 |
* the license terms, see the LICENSE.txt file included with the program. |
| 7 |
*/ |
| 8 |
#define H_MAILBOX |
| 9 |
|
| 10 |
#include <ctime> |
| 11 |
#include <exception> |
| 12 |
#include <list> |
| 13 |
#include <memory> |
| 14 |
#include <string> |
| 15 |
|
| 16 |
using namespace std; |
| 17 |
|
| 18 |
class tokenizer { |
| 19 |
protected: |
| 20 |
string _s; |
| 21 |
string::size_type _next; |
| 22 |
string uppercase(string::size_type to) const |
| 23 |
{ return uppercase(_s.substr(_next, to - _next)); } |
| 24 |
string::size_type findf(const char* s) const |
| 25 |
{ return _s.find_first_of(s, _next); } |
| 26 |
string::size_type findf(const char* s, string::size_type pos) const |
| 27 |
{ return _s.find_first_of(s, pos); } |
| 28 |
string::size_type findq(const char* s) const { return findq(s, _next); } |
| 29 |
string::size_type findq(const char* s, string::size_type pos) const; |
| 30 |
public: |
| 31 |
tokenizer() : _next(0) {} |
| 32 |
tokenizer(const string& s) : _s(s), _next(0) {} |
| 33 |
operator bool() const { return _next < _s.size(); } |
| 34 |
const string& data() const { return _s; } |
| 35 |
string remain() const { return *this ? _s.substr(_next) : string(); } |
| 36 |
int peek() const { return _next < _s.size() ? _s[_next] & 255 : -1; } |
| 37 |
|
| 38 |
static bool digit(const string& s, int& value); |
| 39 |
static bool digit(const string& s) { int v; return digit(s, v); } |
| 40 |
static string uppercase(string s); |
| 41 |
}; |
| 42 |
|
| 43 |
class mail { |
| 44 |
string _uid; |
| 45 |
string _subject; // The subject of this mail. |
| 46 |
pair<string, string> _from; // The 1st is name of sender, and the 2nd is a header line. |
| 47 |
time_t _date; // The received date and time. |
| 48 |
public: |
| 49 |
mail() {} |
| 50 |
mail(const string& uid) : _uid(uid) {} |
| 51 |
const string& uid() const { return _uid; } |
| 52 |
const string& subject() const { return _subject; } |
| 53 |
const pair<string, string>& from() const { return _from; } |
| 54 |
time_t date() const { return _date; } |
| 55 |
const string& sender() const { return _from.first; } |
| 56 |
bool header(const string& headers); |
| 57 |
public: |
| 58 |
// decoder - parse and decode a message. |
| 59 |
class decoder : public tokenizer { |
| 60 |
string _field; |
| 61 |
protected: |
| 62 |
static string trim(const string& text); |
| 63 |
string eword(string::size_type to); |
| 64 |
static string eword(const string& text, bool unescape); |
| 65 |
static string eword(const string& text, |
| 66 |
string::size_type pos = 0, |
| 67 |
string::size_type end = string::npos); |
| 68 |
static string decodeB(const string& text); |
| 69 |
static string decodeQ(const string& text); |
| 70 |
string token(bool comment = false); |
| 71 |
public: |
| 72 |
decoder() {} |
| 73 |
decoder(const string& s) : tokenizer(s) {} |
| 74 |
int field(const char* names); |
| 75 |
const string& field() const { return _field; } |
| 76 |
string unstructured() { return eword(_s.size()); } |
| 77 |
pair<string, string> address(); |
| 78 |
time_t date(); |
| 79 |
}; |
| 80 |
}; |
| 81 |
|
| 82 |
class uri { |
| 83 |
string _part[6]; |
| 84 |
public: |
| 85 |
uri() {} |
| 86 |
explicit uri(const string& uri); |
| 87 |
operator string() const; |
| 88 |
string& operator[](int i) { return _part[i]; } |
| 89 |
const string& operator[](int i) const { return _part[i]; } |
| 90 |
enum { scheme, user, host, port, path, fragment }; |
| 91 |
}; |
| 92 |
|
| 93 |
class mailbox { |
| 94 |
mailbox* _next; |
| 95 |
string _name; |
| 96 |
uri _uri; |
| 97 |
string _passwd; |
| 98 |
int _domain; |
| 99 |
int _verify; |
| 100 |
list<mail> _mails; |
| 101 |
int _recent; |
| 102 |
list<string> _ignore; |
| 103 |
public: |
| 104 |
mailbox(const string& name = string()) |
| 105 |
: _next(NULL), _name(name), _domain(0), _verify(0), _recent(0) {} |
| 106 |
virtual ~mailbox() {} |
| 107 |
const mailbox* next() const { return _next; } |
| 108 |
mailbox* next() { return _next; } |
| 109 |
mailbox* next(mailbox* next) { return _next = next; } |
| 110 |
const string& name() const { return _name; } |
| 111 |
string uristr() const { return _uri; } |
| 112 |
mailbox& uripasswd(const string& uri, const string& passwd); |
| 113 |
mailbox& domain(int domain) { _domain = domain; return *this; } |
| 114 |
mailbox& verify(int verify) { _verify = verify; return *this; } |
| 115 |
const list<mail>& mails() const { return _mails; } |
| 116 |
const list<mail>& mails(list<mail>& mails) |
| 117 |
{ return _mails.swap(mails), _mails; } |
| 118 |
int recent() const { return _recent; } |
| 119 |
const mail* find(const string& uid) const; |
| 120 |
const list<string>& ignore() const { return _ignore; } |
| 121 |
const list<string>& ignore(list<string>& ignore) |
| 122 |
{ return _ignore.swap(ignore), _ignore; } |
| 123 |
void fetchmail(); |
| 124 |
public: |
| 125 |
class backend { |
| 126 |
class _stream { |
| 127 |
public: |
| 128 |
virtual ~_stream() {} |
| 129 |
virtual size_t read(char* buf, size_t size) = 0; |
| 130 |
virtual size_t write(const char* data, size_t size) = 0; |
| 131 |
virtual int tls() const = 0; |
| 132 |
virtual _stream* starttls(const string& host) = 0; |
| 133 |
}; |
| 134 |
unique_ptr<_stream> _st; |
| 135 |
protected: |
| 136 |
int tls() const { return _st->tls(); } |
| 137 |
void starttls(const string& host); |
| 138 |
string read(size_t size); |
| 139 |
string read(); |
| 140 |
void write(const char* data, size_t size); |
| 141 |
void write(const string& data); |
| 142 |
public: |
| 143 |
typedef _stream stream; |
| 144 |
virtual ~backend() {} |
| 145 |
void tcp(const string& host, const string& port, int domain, int verify); |
| 146 |
void ssl(const string& host, const string& port, int domain, int verify); |
| 147 |
virtual void login(const uri& uri, const string& passwd) = 0; |
| 148 |
virtual void logout() = 0; |
| 149 |
virtual size_t fetch(mailbox& mbox, const uri& uri) = 0; |
| 150 |
}; |
| 151 |
public: |
| 152 |
class error : public exception { |
| 153 |
string _msg; |
| 154 |
public: |
| 155 |
error(const char* msg) : _msg(msg) {} |
| 156 |
error(const string& msg) : _msg(msg) {} |
| 157 |
~error() throw() {} |
| 158 |
const char* what() const throw() { return _msg.c_str(); } |
| 159 |
const string& msg() const { return _msg; } |
| 160 |
}; |
| 161 |
}; |
| 162 |
|
| 163 |
#endif |