1 /*
2 ** Copyright 2003-2008, Double Precision Inc.
3 **
4 ** See COPYING for distribution information.
5 */
6 #ifndef libmail_nntp_H
7 #define libmail_nntp_H
8 
9 #include "libmail_config.h"
10 #include	"mail.H"
11 #include	<sys/types.h>
12 
13 #include	"maildir/maildirkeywords.h"
14 
15 #include	"logininfo.H"
16 #include	"fd.H"
17 #include	"generic.H"
18 #include	"search.H"
19 #include	<stdio.h>
20 #include	<time.h>
21 #include	<string>
22 #include	<map>
23 #include	<list>
24 #include	<vector>
25 
26 ///////////////////////////////////////////////////////////////////////////
27 //
28 // An NNTP implementation
29 //
30 
31 LIBMAIL_START
32 
33 //////////////////////////////////////////////////////////////////////////////
34 
35 class nntp : public fd, public generic {
36 
37 public:
38 	class newsrc;
39 	typedef unsigned long msgnum_t;
40 
41 private:
42 
43 	time_t timeoutSetting;
44 	time_t autologoutSetting;
45 
46 	loginInfo nntpLoginInfo;
47 
48 	loginInfo savedLoginInfo;
49 
50 	time_t inactivityTimeout;
51 
52 	callback::folder *folderCallback;
53 
54 	void resumed();
55 	void handler(std::vector<pollfd> &fds, int &timeout);
56 	int socketRead(const std::string &readbuffer);
57 
58 	void disconnect(const char *reason);
59 
60 	// Superclass of NNTP tasks.  Methods create subclasses of Task
61 	// objects, and push them to the tasks queue.  Replies from the
62 	// NNTP server are routed to the foremost Task on the queue.
63 
64 	class Task {
65 
66 	protected:
67 		callback *callbackPtr;	// App callback.
68 		nntp * volatile myserver;
69 		// Marked volatile due to destructor monkey business
70 
71 	public:
72 		time_t defaultTimeout;
73 
74 		virtual void done();
75 		// Task completed, start the next task on the queue,
76 		// and delete this Task object.
77 
78 		void resetTimeout();
79 
80 		virtual void success(std::string);
81 		virtual void fail(std::string);
82 		// success/fail for use by subclasses.  Invoke the callback
83 		// method, then done.
84 
85 		Task(callback *callbackArg,
86 		     nntp &myserverArg);
87 		virtual ~Task();
88 
89 		virtual int getTimeout();
90 		// How long before this task times out.
91 
92 		virtual void emptyQueue();
93 		// After removing this task, the task queue is now empty
94 
95 		virtual void serverResponse(const char *message)=0;
96 		// Process a line of text from the server
97 
98 		virtual void disconnected(const char *reason);
99 		// Server has disconnected.
100 		// The default implementation takes this task off the queue,
101 		// calls the next Task's disconnect method, then deletes
102 		// itself.
103 
104 		virtual void installedTask();
105 		// This task is now at the front of the queue
106 	};
107 
108 	std::list<Task *> tasks;
109 
110 	std::vector<std::string> newgroups;
111 	bool hasNewgroups;
112 
113 	std::map<std::string, newsrc> cachedNewsrc;
114 	bool didCacheNewsrc;
115 
116 	void cacheNewsrc();
117 	bool updateCachedNewsrc();
118 	void discardCachedNewsrc();
119 	bool updateOpenedNewsrc(newsrc &);
120 
121 	void createNewsrc(newsrc &);
122 
123 	class cachedNewsrcSort;
124 
125 	class folder;
126 	class add;
127 	class LoggedInTask;
128 	class LoginTask;
129 	class LogoutTask;
130 	class ListActiveTask;
131 	class GroupTask;
132 	class GroupInfoTask;
133 	class GroupOpenTask;
134 	class FetchTask;
135 	class FetchTaskBase;
136 	class CacheMessageTask;
137 	class CacheTask;
138 	class XoverTask;
139 	class PostTask;
140 	class CheckNewTask;
141 
142 	class XpatTask;
143 	class XpatTaskCallback;
144 
145 	std::string newsrcFilename;	// .newsrc file
146 
147 	std::string openedGroup; // Group we have logically opened
148 
149 	// Here's the index of an opened group.  'cause Usenet groups can
150 	// be fairly large, we try to be extra skimpy on memory usage.
151 
152 	class nntpMessageInfo {
153 	public:
154 		nntpMessageInfo();
155 		~nntpMessageInfo();
156 		msgnum_t msgNum;
157 
158 		mail::keywords::Message keywords;
159 
160 		unsigned char msgFlag;
161 #define IDX_DELETED 1
162 #define IDX_FLAGGED 2
163 
164 #define IDX_SEARCH  128  // Flag used to mark msgs found by search
165 	};
166 
167 private:
168 	static bool equalMsgNums(nntpMessageInfo a,
169 				 nntpMessageInfo b);
170 
171 public:
172 	mail::keywords::Hashtable keywordHashtable;
173 	std::vector<nntpMessageInfo> index;
174 
175 	msgnum_t loWatermark, hiWatermark; // Saved from last GROUP
176 
177 	std::string serverGroup; // Group actually open on the server
178 
179 	callback::disconnect *disconnectCallback;
180 
181 	void installTask(Task *);
182 public:
183 
184 	friend class Task;
185 	friend class LoggedInTask;
186 	friend class folder;
187 	friend class LogoutTask;
188 	friend class ListActiveTask;
189 	friend class GroupTask;
190 	friend class GroupInfoTask;
191 	friend class GroupOpenTask;
192 	friend class FetchTask;
193 	friend class FetchTaskBase;
194 	friend class CacheMessageTask;
195 	friend class CacheTask;
196 	friend class XoverTask;
197 	friend class add;
198 	friend class PostTask;
199 	friend class CheckNewTask;
200 	friend class XpatTask;
201 	friend class XpatTaskCallback;
202 
203 	nntp(std::string url, std::string passwd,
204 	     std::vector<std::string> &certificates,
205 	     std::string newsrcFilename,
206 	     mail::loginCallback *loginCallbackFunc,
207 	     callback &callback,
208 	     callback::disconnect &disconnectCallbackArg);
209 
210 	nntp(const nntp &); // UNDEFINED
211 	nntp &operator=(const nntp &); // UNDEFINED
212 
213 	~nntp();
214 
215 	void logout(callback &callback);
216 
217 	void checkNewMail(callback &callback);
218 	bool hasCapability(std::string capability);
219 	std::string getCapability(std::string capability);
220 
221 	mail::folder *folderFromString(std::string);
222 
223 	void readTopLevelFolders(callback::folderList &callback1,
224 				 callback &callback2);
225 	void findFolder(std::string folder,
226 			class callback::folderList &callback1,
227 			class callback &callback2);
228 	std::string translatePath(std::string path);
229 
230 	mail::folder *getSendFolder(const smtpInfo &info,
231 				    const mail::folder *folder,
232 				    std::string &errmsg);
233 
234 	void readMessageAttributes(const std::vector<size_t> &messages,
235 				   MessageAttributes attributes,
236 				   callback::message &callback);
237 
238 	void readMessageContent(const std::vector<size_t> &messages,
239 				bool peek,
240 				enum mail::readMode readType,
241 				callback::message &callback);
242 
243 	void readMessageContent(size_t messageNum,
244 				bool peek,
245 				const mimestruct &msginfo,
246 				enum mail::readMode readType,
247 				callback::message &callback);
248 
249 	void readMessageContentDecoded(size_t messageNum,
250 				       bool peek,
251 				       const mimestruct &msginfo,
252 				       callback::message &callback);
253 
254 	size_t getFolderIndexSize();
255 	messageInfo getFolderIndexInfo(size_t);
256 
257 	void saveFolderIndexInfo(size_t,
258 				 const messageInfo &,
259 				 callback &);
260 
261 	void updateFolderIndexFlags(const std::vector<size_t> &messages,
262 				    bool doFlip,
263 				    bool enableDisable,
264 				    const messageInfo &flags,
265 				    callback &callback);
266 
267 	void updateFolderIndexInfo(callback &);
268 
269 	void getFolderKeywordInfo(size_t, std::set<std::string> &);
270 
271 	void updateKeywords(const std::vector<size_t> &messages,
272 			    const std::set<std::string> &keywords,
273 			    bool setOrChange,
274 			    // false: set, true: see changeTo
275 			    bool changeTo,
276 			    callback &cb);
277 private:
278 	bool genericProcessKeyword(size_t msgNum,
279 				   updateKeywordHelper &helper);
280 public:
281 	void removeMessages(const std::vector<size_t> &messages,
282 			    callback &cb);
283 
284 	void copyMessagesTo(const std::vector<size_t> &messages,
285 			    mail::folder *copyTo,
286 			    callback &callback);
287 
288 	void searchMessages(const searchParams &searchInfo,
289 			    searchCallback &callback);
290 
291 	void saveSnapshot();
292 private:
293 	void searchMessagesXpat(std::string hdr, std::string srch,
294 				bool searchNot,
295 				searchParams::Scope searchScope,
296 				size_t rangeLo, size_t rangeHi,
297 				searchCallback &callback);
298 
299 	bool fixGenericMessageNumber(std::string uid, size_t &messageNumber);
300 
301 	void genericMessageRead(std::string uid,
302 				size_t messageNumber,
303 				bool peek,
304 				mail::readMode readTypeArg,
305 				callback::message &callback);
306 
307 	void genericMessageSize(std::string uid,
308 				size_t messageNumber,
309 				callback::message &callback);
310 
311 	void genericGetMessageFd(std::string uid,
312 				 size_t messageNumber,
313 				 bool peek,
314 				 int &fdRet,
315 				 callback &callback);
316 	void genericMarkRead(size_t messageNumber);
317 
318 	void genericGetMessageStruct(std::string uid,
319 				     size_t messageNumber,
320 				     struct rfc2045 *&structRet,
321 				     callback &callback);
322 
323 	bool genericCachedUid(std::string uid);
324 
325 	// One message is cached to a temp file, and parsed.
326 
327 	std::string cachedUid;
328 	FILE *genericTmpFp;
329 	struct rfc2045 *genericTmpRfcp;
330 
331 	void cleartmp();
332 };
333 
334 LIBMAIL_END
335 
336 #endif
337