1 /* 2 ** Copyright 2002, Double Precision Inc. 3 ** 4 ** See COPYING for distribution information. 5 */ 6 #ifndef libmail_mbox_H 7 #define libmail_mbox_H 8 9 #include "libmail_config.h" 10 #include "mail.H" 11 12 #include <courier-unicode.h> 13 #include "maildir/maildirkeywords.h" 14 15 #include <time.h> 16 #include <unistd.h> 17 #include <stdio.h> 18 #include <queue> 19 #include <map> 20 #include <set> 21 #include <vector> 22 23 #include "mboxmagictag.H" 24 #include "generic.H" 25 26 #include "namespace.H" 27 28 struct ll_mail; 29 30 LIBMAIL_START 31 32 class file; 33 34 ///////////////////////////////////////////////////////////////////////// 35 // 36 // Legacy mbox driver. 37 // 38 // 39 class mbox : public mail::account, public generic { 40 41 void resumed(); 42 void handler(std::vector<pollfd> &fds, int &timeout); 43 44 bool calledDisconnected; // True if the disconnect callback was invoked 45 bool magicInbox; // True if this account uses INBOX 46 std::string inboxSpoolPath; // Path to the system spool inbox 47 std::string inboxMailboxPath; // $HOME/mboxAccount 48 49 std::string rootPath; // Root path for folders. 50 51 class folder : public mail::folder { 52 53 std::string path; 54 std::string name; 55 mbox &mboxAccount; 56 57 bool saveHasMessages; 58 bool saveHasFolders; 59 60 class closeCallback : public mail::callback { 61 reportProgress(size_t bytesCompleted,size_t bytesEstimatedTotal,size_t messagesCompleted,size_t messagesEstimatedTotal)62 void reportProgress(size_t bytesCompleted, 63 size_t bytesEstimatedTotal, 64 65 size_t messagesCompleted, 66 size_t messagesEstimatedTotal) {} 67 //TODO 68 69 public: 70 ptr<mbox> origmbox; 71 mail::callback &origCallback; 72 mail::callback::folder &origFolderCallback; 73 std::string origPath; 74 75 closeCallback(mbox *origmboxArg, 76 mail::callback &origCallbackArg, 77 mail::callback::folder 78 &origFolderCallbackarg, 79 std::string origPathArg); 80 ~closeCallback(); 81 82 void success(std::string); 83 void fail(std::string); 84 }; 85 86 class add; 87 88 public: 89 friend class mbox; 90 91 folder(std::string pathArg, 92 mbox &mboxArg); 93 ~folder(); 94 95 folder(const mbox::folder &); 96 97 static std::string defaultName(std::string path); 98 99 void sameServerAsHelperFunc() const; 100 101 std::string getName() const; 102 std::string getPath() const; 103 104 bool hasMessages() const; 105 bool hasSubFolders() const; 106 107 bool isParentOf(std::string path) const; 108 109 void hasMessages(bool); 110 void hasSubFolders(bool); 111 112 113 void getParentFolder(callback::folderList &callback1, 114 callback &callback2) const; 115 116 void readFolderInfo( mail::callback::folderInfo 117 &callback1, 118 mail::callback &callback2) const; 119 120 void readSubFolders( mail::callback::folderList &callback1, 121 mail::callback &callback2) const; 122 123 mail::addMessage *addMessage(mail::callback &callback) const; 124 125 void createSubFolder(std::string name, bool isDirectory, 126 mail::callback::folderList &callback1, 127 mail::callback &callback2) const; 128 129 void create(bool isDirectory, 130 mail::callback &callback) const; 131 132 void destroy(mail::callback &callback, bool destroyDir) 133 const; 134 135 void renameFolder(const mail::folder *newParent, 136 std::string newName, 137 mail::callback::folderList &callback1, 138 callback &callback) const; 139 140 mail::folder *clone() const; 141 std::string toString() const; 142 143 void open(mail::callback &openCallback, 144 snapshot *restoreSnapshot, 145 mail::callback::folder &folderCallback) const; 146 }; 147 148 // Special folders 149 150 folder inboxFolder, hierarchyFolder; 151 152 // Stuff gets done by creating a task object, and pushing it into 153 // the tasks queue (see below). The first task in the queue gets 154 // its doit() method called. doit() receives the timeout parameter 155 // from mbox::handler(), which it can adjust, if necessary. 156 // 157 // The doit() method should invoke done() when its done, otherwise 158 // it can simply exit, and be re-invoked the next time the handler 159 // is invoked. 160 // 161 // The task's disconnected() method gets invoked if the mbox 162 // object is destroyed in mid-stream, or if there's a fatal timeout 163 // trying to lock the mboxAccount file. disconnected() should NOT invoke 164 // done(), because that's going to happen anyway as soon as 165 // disconnected() wraps up. disconnected() is present so that 166 // the task can invoke any application callbacks the task is 167 // responsible for. 168 169 class task { 170 171 protected: 172 mbox &mboxAccount; 173 174 public: 175 task(mbox &mboxAccount); 176 virtual ~task(); 177 178 virtual void doit(int &timeout)=0; 179 virtual void disconnected()=0; 180 181 virtual void done(); 182 }; 183 184 // TimedTask subclasses from task, to provide a task with a timeout. 185 // 186 // Subclasses should implement bool doit(). bool doit() should return 187 // true if the task succeeded, or failed. If the task is deferred, 188 // the subclass's doit() method should return false. 189 // 190 // The subclass should call either fail() or success(), which invokes 191 // the callback's method, then invokes done(). 192 // 193 // The timedOut() method invokes the callback's fail method, if this 194 // tasks times out. The subclass can override this method to provide 195 // some value-added functionality. 196 // 197 198 class TimedTask : public mbox::task { 199 200 time_t timeout; 201 time_t nextTry; 202 203 protected: 204 mail::callback &callback; 205 public: 206 TimedTask(mbox &mboxAccount, 207 mail::callback &callbackArg, int timeoutArg=60); 208 ~TimedTask(); 209 210 void doit(int &timeout); 211 212 void fail(std::string errmsg); 213 virtual bool doit()=0; 214 virtual void timedOut(); 215 virtual void disconnected(); 216 }; 217 218 // This is a wrapper for liblock's locking functions 219 220 class lock { 221 struct ll_mail *ll; 222 223 int fd; 224 225 bool readOnlyLock; 226 227 lock(); 228 229 public: 230 lock(std::string filename); // File to create an mboxAccount lock for. 231 ~lock(); 232 233 bool operator()(bool readOnly=false); 234 // Attempt to lock this mboxAccount file, via liblock. 235 // Set readOnly to true if a read-only lock is permissible. 236 getfd()237 int getfd() const { return fd; } 238 // Success - return the file descriptor of locked file. 239 readOnly()240 bool readOnly() const { return readOnlyLock; } 241 // Indicator whether the file was locked in read-only mode. 242 243 244 lock *copy(); 245 // Copy this lock structure to another object, used for 246 // optimizing consecutive parallel locks. 247 248 }; 249 250 class StatusTask; 251 class sighandler; 252 class OpenTask; 253 class CheckNewMailTask; 254 255 class LockTask; 256 class GenericReadTask; 257 class GenericGetMessageTask; 258 class ExpungeTask; 259 260 class MultiLock; 261 class MultiLockGenericMessageRead; 262 class MultiLockGenericAttributes; 263 class MultiLockRelease; 264 class RenameTask; 265 266 std::queue<task *> tasks; 267 268 void installTask(task *); 269 270 // The currently open folder. 271 272 std::string currentFolder; 273 bool currentFolderReadOnly; // Folder opened in readonly mode. 274 275 off_t folderSavedSize; 276 time_t folderSavedTimestamp; 277 // Detect if someone else modified the folder file. 278 279 std::string multiLockFilename; 280 lock *multiLockLock; 281 282 bool folderDirty; 283 // Set to true when message metadata has been modified, but the 284 // folder file has not been updated to reflect these changes. 285 286 bool newMessages; 287 // Set when index is updated from folderMessageIndex, and new messages 288 // were found. 289 290 //////////////////////////////////////////////////////// 291 // 292 // The actual parsed contents of the folder: 293 294 struct mboxMessageIndex { 295 296 off_t startingPos; // Starting offset 297 time_t internalDate; // Synthesized message arrival date 298 mboxMagicTag tag; // The synthesized UID. 299 }; 300 301 mail::keywords::Hashtable keywordHashtable; 302 std::vector<mboxMessageIndex> folderMessageIndex; // The folder 303 304 std::map<std::string, size_t> uidmap; // Look up index from uid. 305 306 // Generic interface caches the temporary file with the most recently 307 // opened message: 308 309 std::string cachedMessageUid; // The cached uid 310 struct rfc2045 *cachedMessageRfcp; 311 FILE *cachedMessageFp; 312 313 void resetFolder(); 314 315 mail::callback::folder *currentFolderCallback; 316 317 // The application sees the following index: 318 319 std::vector<mail::messageInfo> index; 320 321 // Update the mboxAccount file. This is where everything happens. 322 323 bool scan(file &scanFile, 324 file *saveFile, 325 bool reopening, 326 std::set<std::string> *deleteMsgs, 327 bool rewrite, 328 mail::callback *progress); 329 330 void checkNewMail(); 331 332 public: 333 friend class folder; 334 friend class task; 335 friend class TimedTask; 336 friend class StatusTask; 337 friend class OpenTask; 338 friend class CheckNewMailTask; 339 friend class RenameTask; 340 341 friend class LockTask; 342 friend class GenericReadTask; 343 friend class GenericGetMessageTask; 344 friend class ExpungeTask; 345 friend class MultiLock; 346 friend class MultiLockGenericMessageRead; 347 friend class MultiLockGenericAttributes; 348 friend class MultiLockRelease; 349 350 mbox(bool magicInboxArg, 351 std::string folderRootArg, mail::callback &callback, 352 mail::callback::disconnect &disconnect_callback); 353 ~mbox(); 354 355 void logout(mail::callback &callback); 356 void checkNewMail(mail::callback &callback); 357 358 bool hasCapability(std::string capability); 359 std::string getCapability(std::string capability); 360 361 mail::folder *folderFromString(std::string); 362 363 void readTopLevelFolders(mail::callback::folderList &callback1, 364 mail::callback &callback2); 365 366 void findFolder(std::string folder, 367 mail::callback::folderList &callback1, 368 mail::callback &callback2); 369 std::string translatePath(std::string path); 370 371 static std::string translatePathCommon(std::string path, 372 const char *sep); 373 374 void readMessageAttributes(const std::vector<size_t> &messages, 375 MessageAttributes attributes, 376 mail::callback::message &callback); 377 378 void readMessageContent(const std::vector<size_t> &messages, 379 bool peek, 380 enum mail::readMode readType, 381 mail::callback::message &callback); 382 383 void readMessageContent(size_t messageNum, 384 bool peek, 385 const mimestruct &msginfo, 386 enum mail::readMode readType, 387 mail::callback::message &callback); 388 389 void readMessageContentDecoded(size_t messageNum, 390 bool peek, 391 const mimestruct &msginfo, 392 mail::callback::message &callback); 393 394 size_t getFolderIndexSize(); 395 mail::messageInfo getFolderIndexInfo(size_t); 396 397 void saveFolderIndexInfo(size_t, 398 const mail::messageInfo &, 399 mail::callback &); 400 401 void updateFolderIndexFlags(const std::vector<size_t> &messages, 402 bool doFlip, 403 bool enableDisable, 404 const mail::messageInfo &flags, 405 mail::callback &callback); 406 407 void updateFolderIndexInfo(mail::callback &); 408 409 410 void updateKeywords(const std::vector<size_t> &messages, 411 const std::set<std::string> &keywords, 412 bool setOrChange, 413 // false: set, true: see changeTo 414 bool changeTo, 415 callback &cb); 416 void getFolderKeywordInfo(size_t, std::set<std::string> &); 417 418 bool genericProcessKeyword(size_t messageNumber, 419 generic::updateKeywordHelper &helper); 420 421 void removeMessages(const std::vector<size_t> &messages, 422 callback &cb); 423 424 void copyMessagesTo(const std::vector<size_t> &messages, 425 mail::folder *copyTo, 426 mail::callback &callback); 427 428 void searchMessages(const class mail::searchParams &searchInfo, 429 class mail::searchCallback &callback); 430 431 bool verifyUid(std::string uid, size_t &messageNumber, 432 mail::callback &callback); 433 434 435 void genericMessageRead(std::string uid, 436 size_t messageNumber, 437 bool peek, 438 mail::readMode, 439 mail::callback::message &callback); 440 441 void genericMessageSize(std::string uid, 442 size_t messageNumber, 443 mail::callback::message &callback); 444 445 void genericGetMessageFd(std::string uid, 446 size_t messageNumber, 447 bool peek, 448 int &fdRet, 449 mail::callback &callback); 450 451 void genericGetMessageStruct(std::string uid, 452 size_t messageNumber, 453 struct rfc2045 *&structRet, 454 mail::callback &callback); 455 456 bool genericCachedUid(std::string uid); 457 458 void genericGetMessageFdStruct(std::string uid, 459 size_t messageNumber, 460 bool peek, 461 int &fdRet, 462 struct rfc2045 *&structret, 463 mail::callback &callback); 464 void genericMarkRead(size_t messageNumber); 465 }; 466 467 LIBMAIL_END 468 469 #endif 470