/*! Writes UID, and flags to the message, and notifies the protocol that a message has been fetched. This method also closes the \a file passed in. */ void IMAPFolder::MessageStored(entry_ref& ref, BFile& file, uint32 fetchFlags, uint32 uid, uint32 flags) { _WriteUniqueIDValidity(file); _WriteUniqueID(file, uid); if ((fetchFlags & IMAP::kFetchFlags) != 0) _WriteFlags(file, flags); BMessage attributes; _IMAPToMailFlags(flags, attributes); fProtocol.MessageStored(*this, ref, file, fetchFlags, attributes); file.Unset(); fRefMap.insert(std::make_pair(uid, ref)); if (uid > fLastUID) { // Update last known UID fLastUID = uid; BNode directory(&fRef); status_t status = _WriteUInt32(directory, kLastUIDAttribute, uid); if (status != B_OK) { fprintf(stderr, "IMAP: Could not write last UID for mailbox " "%s: %s\n", fMailboxName.String(), strerror(status)); } } }
/*! Synchronizes the message flags/state from the server with the local one. */ void IMAPFolder::SyncMessageFlags(uint32 uid, uint32 mailboxFlags) { if (uid > LastUID()) return; entry_ref ref; BNode node; while (true) { status_t status = GetMessageEntryRef(uid, ref); if (status == B_ENTRY_NOT_FOUND) { // The message does not exist anymore locally, delete it on the // server // TODO: copy it to the trash directory first! fProtocol.UpdateMessageFlags(*this, uid, IMAP::kDeleted); return; } if (status == B_OK) status = node.SetTo(&ref); if (status == B_TIMED_OUT) { // We don't know the message state yet fPendingFlagsMap.insert(std::make_pair(uid, mailboxFlags)); } if (status != B_OK) return; break; } fSynchronizedUIDsSet.insert(uid); uint32 previousFlags = MessageFlags(uid); uint32 currentFlags = previousFlags; if (_MailToIMAPFlags(node, currentFlags) != B_OK) return; // Compare flags to previous/current flags, and update either the // message on the server, or the message locally (or even both) uint32 nextFlags = mailboxFlags; _TestMessageFlags(previousFlags, mailboxFlags, currentFlags, IMAP::kSeen, nextFlags); _TestMessageFlags(previousFlags, mailboxFlags, currentFlags, IMAP::kAnswered, nextFlags); if (nextFlags != previousFlags) _WriteFlags(node, nextFlags); if (currentFlags != nextFlags) { // Update mail message attributes BMessage attributes; _IMAPToMailFlags(nextFlags, attributes); node << attributes; fFlagsMap[uid] = nextFlags; } if (mailboxFlags != nextFlags) { // Update server flags fProtocol.UpdateMessageFlags(*this, uid, nextFlags); } }
status_t IMAPStorage::SetFlags(int32 uid, int32 flags) { MailEntryMap::iterator it = fMailEntryMap.find(uid); if (it == fMailEntryMap.end()) return B_ENTRY_NOT_FOUND; StorageMailEntry& entry = (*it).second; BPath filePath = fMailboxPath; filePath.Append(entry.fileName); BNode node(filePath.Path()); status_t status = _WriteFlags(flags, node); if (status != B_OK) return status; entry.flags = flags; return B_OK; }
status_t IMAPStorage::AddNewMessage(int32 uid, int32 flags, BPositionIO** file) { if (file != NULL) *file = NULL; // TODO: make sure there is not a valid mail with this name BString fileName = "Downloading file... uid: "; fileName << uid; BPath filePath = fMailboxPath; filePath.Append(fileName); TRACE("AddNewMessage %s\n", filePath.Path()); BFile* newFile = new BFile(filePath.Path(), B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE); if (newFile == NULL) return B_NO_MEMORY; StorageMailEntry storageEntry; storageEntry.uid = uid; storageEntry.flags = flags; storageEntry.fileName = fileName; newFile->GetNodeRef(&storageEntry.nodeRef); if (_WriteUniqueID(*newFile, uid) != B_OK) { delete newFile; return B_ERROR; } status_t status = _WriteFlags(flags, *newFile); if (status != B_OK) { delete newFile; return status; } if (file) *file = newFile; else delete newFile; fMailEntryMap[uid] = storageEntry; return B_OK; }