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