1 /*
2 ** Copyright 2003, Double Precision Inc.
3 **
4 ** See COPYING for distribution information.
5 */
6 
7 #ifndef myfolder_H
8 #define myfolder_H
9 
10 #include "config.h"
11 
12 #include "previousscreen.H"
13 #include "myreferences.H"
14 #include "libmail/mail.H"
15 #include "libmail/snapshot.H"
16 #include "curses/timer.H"
17 
18 #include <string>
19 #include <vector>
20 #include <map>
21 #include <fstream>
22 
23 #include <courier-unicode.h>
24 
25 #include "libmail/objectmonitor.H"
26 
27 //////////////////////////////////////////////////////////////////////////
28 //
29 // This object represents the index of the currently open folder.
30 //
31 // It's set up to receive folder events from libmail.a, as a subclass of
32 // mail::callback::folder.
33 
34 class myServer;
35 class CursesMessage;
36 class myMessage;
37 
38 class myFolder : public mail::callback::folder,
39 		 public mail::obj,
40 		 public PreviousScreen {
41 
42 	mail::folder *folder;		// The folder that's opened
43 	class myServer *server;		// My server
44 
45 	// A minimum subclass of mail::callback, used when marking/unmarking
46 	// messages.
47 
48 	class DelUndelCallback : public mail::callback {
49 
50 		void reportProgress(size_t bytesCompleted,
51 				    size_t bytesEstimatedTotal,
52 
53 				    size_t messagesCompleted,
54 				    size_t messagesEstimatedTotal);
55 
56 	public:
57 		DelUndelCallback();
58 		~DelUndelCallback();
59 		void success(std::string);
60 		void fail(std::string);
61 	};
62 
63 public:
64 	bool isClosing; // The folder is being closed.
65 
66 	void quiesce(); // Wait until all pending stuff is done.
67 
68 
69 	// Helper class for restoring previously saved folder index snapshots.
70 	// With mail account classes that support snaphots, the folder's index
71 	// is dumped to a temporary file and is restored the next time the
72 	// folder is opened, then the server sends any changes to the folder's
73 	// saved contents to bring the current contents up to date.
74 	//
75 	// See LibMAIL documentation for more information.
76 
77 
78 	class RestoreSnapshot : public mail::snapshot {
79 		std::ifstream i;
80 		std::string snapshotId;
81 		size_t nmessages;
82 		std::string cachefile;
83 
84 	public:
85 		RestoreSnapshot(myFolder *);
86 		~RestoreSnapshot();
87 
88 		void getSnapshotInfo(std::string &snapshotId,
89 				     size_t &nMessages);
90 		void restoreSnapshot(mail::snapshot::restore &);
91 	};
92 
93 	size_t saveFirstRowShown; // Exit/reenter index screen
94 
95 	bool isExpungingDrafts; // Don't announce expunges.
96 	bool mustReopen;
97 	// This folder may not really be open on the server any more, due to
98 	// an error when trying to open another folder.
99 
100 	class Index {
101 	public:
102 		std::string uid;
103 
104 		time_t arrivalDate;
105 		time_t messageDate;
106 
107 		unsigned long messageSize;
108 		char	status_code;
109 		size_t tag;
110 		std::string subject_utf8;
111 		std::string name_utf8;
112 
113 		std::string upperSubject_utf8;	// In uppercase
114 		std::string upperName_utf8;
115 
116 		messageId messageid;
117 		std::vector<messageId> references;
118 
119 		// For a threaded display only:
120 
121 		size_t threadLevel;
122 		std::vector<size_t> active_threads; // Vertical bars
123 
124 		// Watch level:
125 
126 		size_t watchLevel;
127 		time_t expires;
128 		Index();
129 		~Index();
130 		void toupper();
131 		void checkwatch(myFolder &);
132 		void setStatusCode(const class mail::messageInfo &flags);
133 		void setTag(std::set<std::string> &keywords);
134 	};
135 
136 	// Predicate for std::sort()
137 	class IndexSort {
138 		myFolder &f;
139 	public:
IndexSort(myFolder & F)140 		IndexSort(myFolder &F) : f(F) {}
141 		bool operator()(size_t, size_t);
142 	};
143 
144 	class FolderFilter;
145 
146 	FolderFilter *currentFilter;
147 
148 	FolderFilter *installFilter();
149 private:
150 
151 
152 	myMessageIds msgIds; // All message IDs in use.
153 	Watch watchList; // watched message IDs (declaration order IMPORTANT!)
154 
155 	std::vector<Index> serverIndex;	// The index, in server order
156 
157 	std::vector<size_t> sorted_index; // The index, in sorted order
158 	size_t currentMessage; // current message in the sorted index
159 
160 	class FolderIndexUpdate;
161 	class NewMailUpdate;
162 public:
163 	CursesMessage *mymessage; // Currently open message, if any.
164 
165 
166 	// Interface for displaying the folder's index.  The index is not
167 	// always displayed, only when the folder index screen is actually
168 	// shown.  The folder index screen is subclasses from IndexDisplay,
169 	// whose constructor initilized the currentDisplay pointer below,
170 	// and the destructor NULLs it out.
171 
172 	class IndexDisplay {
173 	public:
174 		myFolder *f;
175 
176 		IndexDisplay(myFolder *);
177 		virtual ~IndexDisplay();
178 		virtual void draw()=0;
179 		virtual void draw(size_t)=0;
getFolderIndex()180 		myFolder *getFolderIndex() const { return f; }
181 	};
182 
183 private:
184 	IndexDisplay *currentDisplay;
185 
186 	size_t expunge_count; // # of messages expunges during current cmd.
187 
188 public:
189 	// Mark msg deleted/undeleted.
190 
191 	void markDeleted(size_t n, bool isDeleted, // Deleted/undeleting
192 			 bool setStatusFlag); // True: update status bar
193 
194 	void toggleMark(size_t n); // Toggle mark/unmarked flag.
195 
196 	void setTag(size_t n, size_t tag);
197 	void setTag(std::vector<size_t> &v, size_t tag);
198 
199 	void watch(size_t, unsigned, unsigned); // Watch msg
200 	void unwatch(size_t); // Unwatch msg
201 
202 	// Internal functions:
203 
204 	void setWatch(size_t n, unsigned nDays, unsigned nLevels);
205 	void setUnwatch(size_t n);
206 
207 private:
208 	void watchUpdated();
209 
210 public:
211 
212 	void checkExpunged(); // Check for expunged messages.
213 
214 	friend class FolderIndexUpdate;
215 	friend class IndexDisplay;
216 	friend class myServer;
217 
218 	myFolder(myServer *serverArg, const mail::folder *folderArg);
219 	~myFolder();
220 
221 	bool init();
222 
223 private:
224 	// Try to find a saved snapshot, and restore it.
225 	bool loadFolderIndex(std::map<std::string, size_t> &uid_list);
226 public:
227 
size()228 	size_t size() const { return sorted_index.size(); }
getCurrentMessage()229 	size_t getCurrentMessage() const { return currentMessage; }
setCurrentMessage(size_t n)230 	void setCurrentMessage(size_t n) { currentMessage=n; }
231 
232 	class iterator {
233 
234 		size_t n;
235 
236 		myFolder *f;
237 
238 	public:
iterator(size_t N,myFolder * F)239 		iterator(size_t N, myFolder *F) : n(N), f(F)
240 		{
241 		}
242 
iterator(const myFolder::iterator & o)243 		iterator(const myFolder::iterator &o) : n(o.n), f(o.f)
244 		{
245 		}
246 
247 		iterator &operator++()
248 		{
249 			++n;
250 			return *this;
251 		}
252 
253 		iterator operator++(int foo)
254 		{
255 			iterator cpy(*this);
256 
257 			++n;
258 			return cpy;
259 		}
260 
261 		iterator &operator--()
262 		{
263 			--n;
264 			return *this;
265 		}
266 
267 		iterator operator--(int foo)
268 		{
269 			iterator cpy(*this);
270 
271 			--n;
272 			return cpy;
273 		}
274 
275 		iterator operator+(int delta)
276 		{
277 			iterator cpy(*this);
278 
279 			cpy.n += delta;
280 
281 			return cpy;
282 		}
283 
284 		Index &operator*()
285 		{
286 			return (f->serverIndex[f->sorted_index[n]]);
287 		}
288 
289 		Index *operator->()
290 		{
291 			return (&f->serverIndex[f->sorted_index[n]]);
292 		}
293 
294 		bool operator==(iterator &i)
295 		{
296 			return n == i.n;
297 		}
298 
299 		bool operator!=(iterator &i)
300 		{
301 			return n != i.n;
302 		}
303 
304 	};
305 
306 	class const_iterator {
307 
308 		size_t n;
309 
310 		const myFolder *f;
311 
312 	public:
const_iterator(size_t N,const myFolder * F)313 		const_iterator(size_t N, const myFolder *F) : n(N), f(F)
314 		{
315 		}
316 
const_iterator(const myFolder::const_iterator & o)317 		const_iterator(const myFolder::const_iterator &o) : n(o.n), f(o.f)
318 		{
319 		}
320 
321 		const_iterator &operator++()
322 		{
323 			++n;
324 			return *this;
325 		}
326 
327 		const_iterator operator++(int foo)
328 		{
329 			const_iterator cpy(*this);
330 
331 			++n;
332 			return cpy;
333 		}
334 
335 		const_iterator operator+(int delta)
336 		{
337 			const_iterator cpy(*this);
338 
339 			cpy.n += delta;
340 
341 			return cpy;
342 		}
343 
344 		const_iterator &operator--()
345 		{
346 			--n;
347 			return *this;
348 		}
349 
350 		const_iterator operator--(int foo)
351 		{
352 			const_iterator cpy(*this);
353 
354 			--n;
355 			return cpy;
356 		}
357 
358 		const Index &operator*()
359 		{
360 			return (f->serverIndex[f->sorted_index[n]]);
361 		}
362 
363 		const Index *operator->()
364 		{
365 			return (&f->serverIndex[f->sorted_index[n]]);
366 		}
367 
368 		bool operator==(const_iterator &i)
369 		{
370 			return n == i.n;
371 		}
372 
373 		bool operator!=(const_iterator &i)
374 		{
375 			return n != i.n;
376 		}
377 	};
378 
begin()379 	iterator begin() { return iterator(0, this); }
end()380 	iterator end() { return iterator(sorted_index.size(), this); }
381 
begin()382 	const_iterator begin() const
383 	{
384 		return const_iterator(0, this);
385 	}
386 
end()387 	const_iterator end() const
388 	{
389 		return const_iterator(sorted_index.size(), this);
390 	}
391 
getIndex(size_t n)392 	const Index &getIndex(size_t n) const
393 	{
394 		return serverIndex[sorted_index[n]];
395 	}
396 
getIndex(size_t n)397 	Index &getIndex(size_t n)
398 	{
399 		return serverIndex[sorted_index[n]];
400 	}
401 
402 	mail::messageInfo getFlags(size_t n) const;
403 
getServerIndex(size_t n)404 	size_t getServerIndex(size_t n) const { return sorted_index[n]; }
405 
406 	class myServer *getServer() const;
getFolder()407 	const mail::folder *getFolder() const { return (folder); }
408 
409 	// Inherited from mail::callback::folder:
410 
411 	void newMessages();
412 	void messagesRemoved(std::vector< std::pair<size_t, size_t> > &list);
413 	void messageChanged(size_t n);
414 	void saveSnapshot(std::string snapshotId);
415 
416 private:
417 	// Don't pile on expunge messages.  Set a timer, if no expunge
418 	// events are reported within the prescribed time interval, notify
419 	// the user.
420 
421 	TimerRedirect<myFolder> expungedTimer;
422 
423 	void unsolicitedExpunge();
424 public:
425 
426 	//////////////////////////////////////////////////////
427 
428 	void checkNewMail(class mail::callback &cb);
429 	void newMessagesReceived();
430 	void newMessagesReceivedAndFiltered(size_t filteredCnt);
431 	void messagesFiltered();
432 
433 	void resort();
434 
435 	void setSortFunction(std::string sortBy);
436 
437 	std::string getSortFunction() const;
438 
439 	// Rather than force everything to recompile whenever a change is
440 	// necessary to the threading algorithm, use a class to encapsulate
441 	// all the needed functions to implement threading.
442 
443 	class thread;
444 
445 	friend class thread;
446 
447 	//////////////////////////////////////////////////////
448 	//
449 	// Message navigation - used by CursesMessageDisplay
450 
451 	bool getNextUnreadMessage(size_t &messageNum);
452 	bool getNextMessage(size_t &messageNum);
453 	bool getPrevMessage(size_t &messageNum);
454 
455 	// Open a specific message, or its message/rfc822 attachment.
456 	// If goMessage is not null, the new message's indicated member
457 	// function is invoked.
458 
459 	void goMessage(size_t messageNum,
460 		       std::string mimeid,
461 		       void (myMessage::*completedFuncArg)()=NULL);
462 
463 	// Download a draft, and open it.
464 
465 	void goDraft();
466 
467 	// View attachments to a message.
468 	void viewAttachments(size_t messageNum);
469 
470 private:
471 
472 	// Download a message, that invoke completedFuncArg
473 
474 	void openMessage(size_t messageNum, std::string mimeid,
475 			 bool attachmentsOnly,
476 			 void (myMessage::*completedFuncArg)());
477 
478 	size_t newMailCheckCount;
479 public:
480 	bool isCheckingNewMail();
481 	// TRUE if this object is busy checking for new mail.
482 
483 private:
484 	void setSortFunctionNoSave(std::string sortBy);
485 	void setSortFunctionNoSort(std::string sortBy);
486 
487 	bool sort_function_not;
488 
489 	bool (myFolder::*sort_function)(size_t, size_t);
490 	std::string sort_function_name;
491 
492 	bool sortByArrival(size_t, size_t);
493 	bool sortByDate(size_t, size_t);
494 	bool sortBySubject(size_t, size_t);
495 	bool sortByName(size_t, size_t);
496 
497 };
498 
499 #endif
500